Skip to content

Commit 075bac8

Browse files
authored
fix(skills): dispatch subagents only when they pay off (EveryInc#1815)
1 parent c61e8f6 commit 075bac8

16 files changed

Lines changed: 71 additions & 74 deletions

File tree

‎assets/demo/play.sh‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,10 @@ tool "Skill" "compound-engineering:ce-compound"
7777
res "Launching skill: compound-engineering:ce-compound"
7878
p ""
7979
pause 0.4
80-
agent "ce-compound Context Analyzer"
81-
p ""
82-
pause 0.3
83-
agent "ce-compound Solution Extractor"
84-
p ""
85-
pause 0.3
8680
agent "ce-compound Related Docs Finder"
8781
p ""
8882
spin "Compounding" 2200
89-
say "All three research agents reported. Assembling the learning:"
83+
say "Related docs found and the draft is ready. Assembling the learning:"
9084
p ""
9185
pause 0.5
9286
tool "Write" "docs/solutions/runtime-errors/tenant-gate-worktree-env-gate.md"

‎docs/guides/ce-compound.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Most teams solve the same problem twice, sometimes with the same person, because
9090

9191
### Two modes, agent-selected
9292

93-
Full mode runs three research subagents in parallel (Context Analyzer, Solution Extractor, Related Docs Finder), plus an automatic session-history probe across Claude Code, Codex, Cursor, Pi, and oh-my-pi (omp). It cross-references existing docs, detects duplicates, and runs specialized reviews.
93+
Full mode classifies the learning and drafts its body in the main session, which holds the conversation, while a Related Docs Finder subagent searches existing docs, plus an automatic session-history probe across Claude Code, Codex, Cursor, Pi, and oh-my-pi (omp). It cross-references existing docs, detects duplicates, and runs specialized reviews.
9494

9595
Lightweight mode writes the same doc type in a single pass. No subagents, no overlap detection, no session-history research, no semantic grounding validation.
9696

@@ -139,7 +139,7 @@ You've just spent 45 minutes debugging an N+1 query in the brief-generation flow
139139

140140
The completion phrase marks the checkpoint. The agent applies the counterfactual, determines that a future engineer could plausibly repeat the investigation from the final implementation alone, and auto-invokes `ce-compound`. With plenty of context left, it picks Full mode and notes "Ran Full mode." at the top of its output. No prompt.
141141

142-
Three subagents dispatch in parallel. Context Analyzer classifies the work as `performance_issue` (bug track) and proposes the filename and category. Solution Extractor structures the fix with before/after code. Related Docs Finder reports moderate overlap with an older doc on a different N+1 case. Alongside them, the session-history probe scans recent sessions; none clear the relevance bar, so it records "no relevant prior sessions."
142+
The Related Docs Finder dispatches in the background. While it searches, the agent classifies the work as `performance_issue` (bug track), picks the filename and category, and drafts the fix with before/after code and the dead ends from the session. The finder reports moderate overlap with an older doc on a different N+1 case. Alongside them, the session-history probe scans recent sessions; none clear the relevance bar, so it records "no relevant prior sessions."
143143

144144
The orchestrator assembles the doc, validates frontmatter, and writes `docs/solutions/performance-issues/n-plus-one-brief-generation.md`. Grounding validation runs next: the mechanical script confirms every cited path and SHA resolves, and the validator subagent quotes the source line behind the doc's claim about the ORM's default batching behavior. The discoverability check finds `AGENTS.md` does not mention `docs/solutions/`, proposes a one-line addition, and applies it after you confirm.
145145

‎docs/solutions/skill-design/portable-agent-skill-authoring.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ Always-loaded skill prose remains in context throughout the workflow. Extract su
313313
- Do not inline a summary complete enough to suppress loading the authoritative reference.
314314
- Pass large context to subagents by file path plus a short gist rather than duplicating it into prompts.
315315

316-
When delegation is used, each task needs a distinct scope, output contract, and synthesis owner. Use parallel work for genuinely independent questions, not as a reflex. A single capable model may be better when the work depends on one evolving context or requires tight synthesis.
316+
Dispatch a subagent only for a reason that survives better compaction. There are four: the work must read far more than it returns and the parent will not need the raw material again; independent judgment is the product (review, verification, ideation, judging), so the parent's context would anchor it; substantial units can run in parallel without shared files or state; or the harness can actually select a different model for it. Do the work in the parent when its input lives only in the parent (the conversation, decisions settled this session), when the parent will read the full output back anyway, or when it is a small change to code the parent already read. A fresh subagent sees only what its prompt carries, so a subagent told to "extract the conversation" without being handed it is a broken dispatch, not a cheap one: `ce-compound` once drafted every learning that way. Inlining is not free either. Tokens added to a long-lived parent, such as an `lfg` or `ce-babysit-pr` chain, are re-read on every later turn, and in one measured `ce-code-review` run the orchestrator's cache reads were twice those of its six subagents combined (`review-cost-is-in-entering-the-spine-not-the-findings.md`). Each delegated task still needs a distinct scope, output contract, and synthesis owner.
317317

318318
Stable cross-skill fields, enums, and return statuses are protocols. Version or parity-test them when independently evolving skills depend on exact agreement.
319319

@@ -437,6 +437,7 @@ Measure the outcome the skill exists to improve, not proxy volume:
437437
- [ ] Higher-priority prohibitions remain intact.
438438
- [ ] Inherited authority is explicit and can only narrow.
439439
- [ ] Delegated tasks have distinct scopes, output contracts, and a synthesis owner.
440+
- [ ] Each subagent dispatch names its reason (flood protection, independent judgment, parallel units, or a selectable model) and receives every input it needs; work whose input lives only in the parent stays in the parent.
440441

441442
### Evidence and evaluation
442443

‎skills/ce-compound/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Lightweight mode skips session history entirely; non-interactive Full runs the s
7070
Run these in order. Each reference is a required read at the step that names it.
7171

7272
1. **Research** — read `references/research.md`.
73-
2. **Session history** — read `references/session-history.md`, and start it *after* launching the parallel block so the two overlap rather than serialize. Session history is the final Phase 1 input, not a workflow stop. When it returns, including with "no relevant prior sessions", go straight to assembly without pausing or summarizing.
73+
2. **Session history** — read `references/session-history.md`, and start it *after* dispatching the Related Docs Finder so it overlaps your drafting rather than serializing. Session history is the final Phase 1 input, not a workflow stop. When it returns, including with "no relevant prior sessions", go straight to assembly without pausing or summarizing.
7474
3. **Assembly and write** — wait for every Phase 1 input, then read `references/assembly.md`.
7575
4. **Refresh check and discoverability** — read `references/refresh-and-discoverability.md`.
7676
5. **Optional enhancement** — read `references/enhancement.md`. Interactive only.

‎skills/ce-compound/references/assembly.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
<sequential_tasks>
66

7-
**WAIT for all Phase 1 inputs to complete before proceeding.** Those inputs are the three parallel subagents and, in Full mode, the internal session-history flow, which may have stopped at the probe with `no relevant prior sessions`. Session history is a Phase 1 input even though it runs in the orchestrator rather than as a public skill.
7+
**WAIT for all Phase 1 inputs to complete before proceeding.** Those inputs are your classification and body draft, the Related Docs Finder, and, in Full mode, the internal session-history flow, which may have stopped at the probe with `no relevant prior sessions`. Session history is a Phase 1 input even though it runs in the orchestrator rather than as a public skill.
88

99
The orchestrating agent (main conversation) performs these steps:
1010

11-
1. **Collect Phase 1 results from the run artifacts.** For each Phase 1 subagent, `Read` its artifact file under `{run_dir}/` (`context.json`, `solution.md`, `related.json`, and `session-history.md` when session history ran). The artifact holds the subagent's full output. **Fall back to the subagent's inline return only when its artifact file is absent or empty** (e.g., `{run_id}` did not resolve, or the subagent failed to write). The artifact is authoritative when present. Reading it is what keeps the workflow working through the issue #956 summary-collapse, where the inline return is only an executive summary.
11+
1. **Collect Phase 1 results from the run artifacts.** For each Phase 1 subagent, `Read` its artifact file under `{run_dir}/` (`related.json`, and `session-history.md` when session history ran). The artifact holds the subagent's full output. **Fall back to the subagent's inline return only when its artifact file is absent or empty** (e.g., `{run_id}` did not resolve, or the subagent failed to write). The artifact is authoritative when present. Reading it is what keeps the workflow working through the issue #956 summary-collapse, where the inline return is only an executive summary.
1212
2. **Check the overlap assessment** from the Related Docs Finder before deciding what to write:
1313

1414
| Overlap | Action |
@@ -28,7 +28,7 @@ The orchestrating agent (main conversation) performs these steps:
2828
- Tag session-sourced content with "(session history)" so its origin is clear to future readers
2929
- If findings are thin or "no relevant prior sessions," proceed without session context
3030
4. **Decide the destination before assembling.** The destination fixes two things every later step uses, the output path and the frontmatter shape, so settle it here, once. The default is a learning: the existing doc's path when step 2 chose to update, otherwise `<root>/solutions/[category]/[filename].md`, in the shape of `assets/resolution-template.md` and `references/schema.yaml`. **Offer a pack destination (interactive Full mode only)** when both of these hold: the capture is prescriptive-shaped, meaning it states a standing always/never rule rather than narrating an incident, and at least one resolved pack root is **writable** (its `roots` entry has no `url`/`ref` keys, so it is a path source rather than a git cache). Ask via the blocking question tool where it lands: `<root>/solutions/` (default), a named writable pack, or scaffold a new pack (create the directory and append the entry to `.compound-engineering/config.yaml`'s `packs:` list; this is the one config write this skill may make, and only here). A pack destination is `<pack dir>/<kebab-case of the title>.md`, at the pack's top level, because discovery reads rules only there. Write it in the shape of a rule: `title` plus a situational `applies_when` list, prescriptive prose, and no bug-track fields (`symptoms`, `root_cause`, `severity`). Git-sourced roots render in the options as `(upstream: manual)` and are never written. Incident-shaped captures, and every non-interactive run, skip the offer: the default destination stands.
31-
5. Assemble the complete markdown file in the destination's shape from the collected pieces, then validate its YAML frontmatter: a learning against `references/schema.yaml`, a pack rule against the rule shape (`title` present, `applies_when` a non-empty list). The YAML-safety quoting rule for array items (see `references/yaml-schema.md` > YAML Safety Rules) applies to both.
31+
5. Assemble the complete markdown file in the destination's shape from your draft and the collected pieces, then validate its YAML frontmatter: a learning against `references/schema.yaml`, a pack rule against the rule shape (`title` present, `applies_when` a non-empty list). The YAML-safety quoting rule for array items (see `references/yaml-schema.md` > YAML Safety Rules) applies to both.
3232
6. Create the destination's directory if needed (`mkdir -p`)
3333
7. Write the file at the destination path
3434
8. **Validate parser-safety of the written frontmatter** to catch silent-corruption issues the prose rules miss: malformed `---` delimiter lines, unquoted ` #` in scalar values (silent comment truncation), and unquoted `: ` in scalar values (silent mapping confusion). The bundled validator ships **inside the skill bundle**; set `SKILL_DIR` to the absolute path of the directory containing this SKILL.md and run it against the destination path through an existence guard so platforms that cannot locate the script fall back to a manual check instead of silently skipping the protection:

‎skills/ce-compound/references/modes.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Both are decisions the agent is better positioned to make than the user. Depth d
44

55
**Full is the right choice for essentially every documented learning.** Its token cost is small next to the engineering work that produced the learning, and it is dwarfed by the value of a doc that compounds. Lightweight buys back context at the cost of cross-referencing, overlap detection, and semantic grounding validation, so it is for real context pressure only. If Lightweight turns out to be the wrong call for the user's taste, re-running is a rare, cheap correction. It is cheaper than taxing every run with a question.
66

7-
**The session-history probe is near-free on wall-clock** because it runs alongside the research subagents, and it escalates to the expensive extraction and synthesis only when genuinely relevant candidate sessions turn up (`references/session-history.md`). This support exists only inside the compounding workflow; there is no standalone session-history feature for users.
7+
**The session-history probe is near-free on wall-clock** because it runs alongside the Related Docs Finder and your drafting, and it escalates to the expensive extraction and synthesis only when genuinely relevant candidate sessions turn up (`references/session-history.md`). This support exists only inside the compounding workflow; there is no standalone session-history feature for users.
88

99
## Auto-Invoke
1010

‎skills/ce-compound/references/report.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ Documentation skipped
6161
Ran Full mode.
6262
Auto memory: 2 relevant entries used as supplementary evidence
6363
64-
Subagent Results:
65-
✓ Context Analyzer: Identified performance_issue in background_job (component from corpus), category: performance-issues/
66-
✓ Solution Extractor: 3 code fixes, prevention strategies
64+
Research Results:
65+
✓ Classified: performance_issue in background_job (component from corpus), category: performance-issues/
66+
✓ Drafted: 3 code fixes, prevention strategies
6767
✓ Related Docs Finder: 2 related issues
6868
✓ Session History: 3 prior sessions on same branch, 2 failed approaches surfaced
6969

0 commit comments

Comments
 (0)