--- name: agent-wiki-synthesize-skill description: Read a normalized Claude Code trajectory JSON and produce a wiki-resident SKILL.md page that future agents can invoke. Use when a trajectory captured a non-trivial successful workflow worth promoting from a free-text guideline to an executable, callable artifact. --- # Agent Wiki — Synthesize Skill ## Overview Promote a successful workflow from a saved trajectory into an **executable agent skill** living inside a wiki at `/skills//SKILL.md`. The output is the procedural counterpart to `agent-wiki-extract-guidelines`'s declarative pages: a guideline tells a future agent *what to do*; a synthesized skill is a structured workflow page the future agent can read and *execute directly*, optionally invoking sibling scripts via Bash. This is the per-trajectory **promote-to-procedural** pass of the `agent-wiki` family. Run it after one or more trajectories captured the same recipe and you want future agents to invoke that recipe instead of re-deriving it. > **Ingesting a whole batch end-to-end?** Prefer the `agent-wiki-ingest` > skill, which sequences summarize → extract → synthesize → **consolidate** > → catalog. It runs this skill at the right point (after extraction, before > consolidation) and guarantees the consolidation pass that clusters the > surviving atomics is never skipped. Use this standalone skill only to > promote a single trajectory's workflow. ## When To Use Use this skill when a trajectory captured: - A **non-trivial successful workflow** — multiple tool calls, with at least one custom script or non-obvious sequence — that produced the answer after trial-and-error. The eventual happy path is worth saving. - A **reusable command sequence or script** the agent wrote. Particularly if the agent had to reconstruct it across multiple attempts. - A pattern a future agent will hit on a similar-but-not-identical task — parsing a binary format, walking a structured directory, reaching a specific tool fallback. Skip this skill — let `agent-wiki-extract-guidelines` cover the case with a guideline alone — when: - The workflow is a single trivial command (`grep -c TODO ...`). - The path embeds secrets, tokens, or one-off user inputs. - A skill with the same trigger already exists in `/skills/`. - The session ended without reaching a clear successful answer. ## Input A path that is either: - a normalized trajectory JSON file - a directory of such files Default if no path is given: `trajectories/normalized`. ## Workflow ### Step 1: Resolve input files Use `Glob` to enumerate JSON files. ### Step 2: Glance at existing skills `Glob /skills/*/SKILL.md` to see what's already there. **Don't re-author a skill with the same name** unless the trajectory's recipe materially refines or generalizes it. ### Step 3: For each trajectory Read the file. The fields you need: - `session_id`, `agent`, `model` - `openai_chat_completion.messages` — the source of truth for what happened Walk the messages and identify: #### 3a. The successful workflow The **final, working** tool sequence — the one that produced the answer. Distinguish it from the trial-and-error leading up to it. Capture the exact tool calls, scripts, or command sequences verbatim. #### 3b. The trial-and-error context What didn't work — the dead ends. You'll use this to author a *trigger description* so a future agent knows when to reach for this skill **instead of** the failing approaches. #### 3c. Environment assumptions What was missing or had to be installed (no `exiftool`, `pip install Pillow` needed, etc.). If no clearly successful workflow is in the trajectory, output zero skills for it and continue. ### Step 4: Decide a skill name and trigger The skill **name** must be: - kebab-case, action-oriented (`extract-jpeg-exif-camera-optics`, `parse-png-dimensions`, `walk-zip-central-directory`) - specific enough that a future agent reading just the name can guess what it does - not a duplicate of any existing skill in `/skills/` The skill **description** (one line in frontmatter) describes the *task*, not the trajectory. Bad: "Solves the lens-model question from session 07d60d9f." Good: "Read camera-optics fields (lens model, focal length, aperture, ISO) from JPEG EXIF using stdlib `struct` when system EXIF tools are unavailable." The **trigger** (frontmatter + `## When To Use`) describes the broad task context, not the narrow original request. ### Step 5: Synthesize a JSON object ```json { "name": "", "description": "", "trigger": "", "session_id": "", "normalized_path": "", "related_summary": "summaries/.md", "agent": "", "tags": ["<2-4 short tags>"], "overview": "<1-2 sentences: what the skill does and when>", "when_to_use": [ "", "" ], "workflow_steps": [ "", "" ], "scripts": [ { "name": ".py", "language": "python", "content": "" } ] } ``` Notes on each field: - **`overview`** — the SKILL.md's `## Overview` section body. Keep it to 1-2 sentences. Don't retell the original session. - **`when_to_use`** — a bulleted list of trigger conditions. The future agent matches its current task against these. - **`workflow_steps`** — the procedural body. Each step is an instruction the agent will follow. Reference scripts as `Run \`bash /skills//scripts/.sh\`` (the helper resolves `` at write time). - **`scripts`** — optional. If the workflow needs a non-trivial script, include it here. The helper writes it to `/skills//scripts/` and references it in the workflow body. Keep scripts minimal — strip incidental log lines or one-off args; replace literal file names with positional arguments. ### Step 6: Pipe the JSON to the helper ```bash echo '' | uv run python explorations/agent-wiki/skills/scripts/build_agent_wiki.py render-skill ``` Add `--rewrite` to overwrite an existing skill page. The helper: - Validates the JSON: `name` must be kebab-case, `description` and `workflow_steps` non-empty; sibling scripts must have `name` matching `^[\w.-]+$`. - Writes `/skills//SKILL.md` with frontmatter (`name`, `description`, `trigger`, `agent`, `sources`, `related_summary`, `tags`, `verified_at`) and body (Overview, When To Use, Workflow, Sources). - Writes `/skills//scripts/` for each script, marks shell scripts executable. - Updates `/skills/_id_index.json` (skill slug → relpath). - Appends `synthesize_skill` to `/_audit.log` with session_id + slug. - Skips silently if the skill already exists and `--rewrite` was not passed. ### Step 7: Refresh indexes After processing all trajectories, run **once**: ```bash uv run python explorations/agent-wiki/skills/scripts/build_agent_wiki.py catalog ``` This regenerates `/skills/index.md`, the section indexes, and `_index.jsonl` (which gains a `kind: "skill"` row per skill, sorted between `cluster:` and `guideline:` rows). No LLM cost. ## Output structure ``` /skills/ ├── _id_index.json skill slug → relpath ├── index.md alphabetical listing (auto-generated) └── / ├── SKILL.md the synthesized skill └── scripts/ optional supporting scripts └── .{sh,py} ``` The SKILL.md frontmatter shape: ```yaml --- id: skill: type: skill name: description: trigger: agent: claude-code sources: - related_summary: summaries/.md verified_at: tags: [] --- ``` ## Skills vs guidelines vs clusters - **Guideline** (in `/guidelines/`): the agent reads it and *decides* what to do. Free-text advice. Use when the lesson is conceptual. - **Cluster** (in `/guidelines/__cluster.md`): an aggregator page grouping related atomics. Recall-preferred over its members. - **Skill** (in `/skills//SKILL.md`): a structured workflow page the agent reads and *executes*. Use when the lesson is a concrete, reusable recipe with a well-defined input/output. At retrieval time, `_index.jsonl` lists all three kinds. Sort order is `cluster` → `skill` → `guideline` → `task` so callable artifacts surface first. The agent reads the SKILL.md, follows its Workflow section, and invokes any sibling scripts via Bash. ## Best practices 1. **One skill per workflow.** Two unrelated successful workflows in one trajectory → two synthesize calls with different names. 2. **Cite the trajectory.** The helper records `sources` + `related_summary` automatically; you just need to set `session_id` and `normalized_path` correctly. 3. **Don't promote one-shots.** A skill is worth synthesizing only if the trigger is plausibly recurring. Single-use trajectories should stay as guidelines (or nothing at all). 4. **Don't paraphrase failure.** The skill describes what *worked*. If you're tempted to write "this skill avoids the problem where exiftool isn't installed," restate as "uses Pillow / stdlib struct; works in environments without system EXIF tools." 5. **Keep scripts minimal.** Strip log lines, debug prints, validation that wasn't actually exercised in the trajectory. 6. **Generality is everything.** A skill named `extract-gps-from-jpeg` will not match a lens-model query. If the trajectory only exercised one EXIF field, name the skill broadly (`extract-jpeg-exif-camera-optics`) so future agents recognize its applicability to siblings.