From 9c14f5cabd43e7a0c8f0a4838ed5f7da61981d76 Mon Sep 17 00:00:00 2001 From: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:50:28 -0700 Subject: [PATCH] =?UTF-8?q?feat(delegate):=20plan-then-dispatch=20guidance?= =?UTF-8?q?=20=E2=80=94=20batch=20independent=20delegations=20in=20one=20t?= =?UTF-8?q?urn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured eval runs showed roots delegating in 3-4 sequential waves, idle 91-94% of wall time, with ~57% of wall structurally recoverable by batching independent delegations into a single turn. The machinery already parallelizes multiple delegate calls emitted in one assistant turn (asyncio.gather, one parallel_group_id per turn) -- the defect is the root model's one-delegation-wave-per-turn planning policy, not missing machinery. This is Stage 1 ("Option A", guidance-only) of the approved pg1-parallel-delegation spec. Every existing mention of parallelism argued quality ("different agents bring different tools") but never argued wall-clock, and never told the model to enumerate its full delegation set before dispatching. This change replaces the weak/buried guidance with instructions that state the wall-clock cost directly and give the model an explicit independence test. Three verbatim text replacements, no code/schema/behavior changes: - modules/tool-delegate/amplifier_module_tool_delegate/__init__.py: replace the delegate tool's "Agent usage notes" block (rendered into every request's tool spec) with explicit batching guidance. - context/agents/multi-agent-patterns.md: replace "## Parallel Agent Dispatch" with "## Plan the Whole Set, Then Dispatch", adding the wall-clock framing and an explicit independence test. - context/agents/delegation-instructions.md: replace "## Scaling with Multiple Instances" with "## Wave Discipline: Batch Everything Independent", covering both same-agent and cross-agent batching. Token cost: +175 tokens/request (budgeted in the spec against a ~12,000 token foundation context load). Each edit replaces its section rather than appending, per ISSUE_HANDLING.md's guidance on not growing files without cause. Stage 2 (a `hooks-delegation-batching` nudge hook that reinforces this guidance at the actual decision point -- after wave N's results land, before wave N+1 is planned) is fully specified but deferred. It ships only if Stage 1's DTU measurement misses the >=40% wall-reduction target. Verified: full suite green (uv run pytest tests/ -q --tb=short: 1634 passed, 1 skipped), modules/tool-delegate/tests/ green (62 passed), python_check clean on the touched .py file (only pre-existing warnings elsewhere in the file, none introduced), and the tool-schema token estimator's `ast.literal_eval` extraction confirmed still succeeds (no `return{` substring introduced). Spec: pg1-parallel-delegation-spec.md (openai_improvement-pg1) Note for reviewers: after merge, `amplifier reset --remove cache -y` is required before the new guidance is loaded by a running Amplifier process -- foundation context files are read from the bundle cache. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com> --- context/agents/delegation-instructions.md | 27 +++++++++++---- context/agents/multi-agent-patterns.md | 33 ++++++++++++++----- .../__init__.py | 15 ++++++++- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/context/agents/delegation-instructions.md b/context/agents/delegation-instructions.md index fce620a8..5b8d0f0b 100644 --- a/context/agents/delegation-instructions.md +++ b/context/agents/delegation-instructions.md @@ -276,21 +276,34 @@ Use session resumption when: --- -## Scaling with Multiple Instances +## Wave Discipline: Batch Everything Independent -For large codebases or complex investigations, dispatch MULTIPLE instances of the same agent with different scopes: +**Every delegate call in one turn runs concurrently. Every delegate call in a separate turn +runs sequentially, and you block on the previous one first.** + +Plan your full delegation set before dispatching any of it. Emit every independently +resolvable delegation in a single turn — different agents, same agent with different +scopes, or both. ```python -# Parallel dispatch - independent surveys +# One turn, three concurrent agents - different specialists +delegate(agent="foundation:explorer", instruction="Survey auth/", context_depth="none") +delegate(agent="python-dev:code-intel", instruction="Trace authenticate() callers") +delegate(agent="foundation:git-ops", instruction="Summarize recent auth/ commits") + +# One turn, three concurrent instances - same agent, split scope delegate(agent="foundation:explorer", instruction="Survey auth/", context_depth="none") delegate(agent="foundation:explorer", instruction="Survey api/", context_depth="none") delegate(agent="foundation:explorer", instruction="Survey models/", context_depth="none") ``` -**When to scale:** -- Large codebase with distinct areas -- Multiple independent questions to answer -- Time-sensitive investigations where parallelism helps +**Only a delegation that consumes another delegation's output belongs in a later turn.** +Everything else goes now. Before you dispatch a second wave, ask whether it could have +gone out with the first — if it could have, batch what remains rather than repeating the +mistake. + +**When to scale out:** large codebase with distinct areas; multiple independent questions; +any investigation where you would otherwise wait on one agent before starting the next. --- diff --git a/context/agents/multi-agent-patterns.md b/context/agents/multi-agent-patterns.md index 8aee3336..fbbd6f90 100644 --- a/context/agents/multi-agent-patterns.md +++ b/context/agents/multi-agent-patterns.md @@ -4,22 +4,39 @@ This context provides patterns for orchestrating multiple agents effectively. --- -## Parallel Agent Dispatch +## Plan the Whole Set, Then Dispatch -**CRITICAL**: For non-trivial investigations or tasks, use MULTIPLE agents to get richer results. Different agents have different tools, perspectives, and context that complement each other. +**Delegations emitted in ONE turn run concurrently. Delegations split across turns run +sequentially — and you sit idle through each one.** -When investigating or analyzing, dispatch multiple agents IN PARALLEL in a single message: +Before your first delegate call, write down every delegation the task needs. Then emit, +in a single turn, every one of them that does not consume another delegation's output. ```python +# ONE turn - all three run at once, total time = the slowest one delegate(agent="foundation:explorer", instruction="Survey the authentication module structure") delegate(agent="python-dev:code-intel", instruction="Trace the call hierarchy of authenticate()") -delegate(agent="foundation:zen-architect", instruction="Review auth module for design patterns") +delegate(agent="foundation:git-ops", instruction="Summarize recent commits touching auth/") ``` -**Why parallel matters:** -- Each agent brings different tools (LSP vs grep vs design analysis) -- Deterministic tools (LSP) find actual code paths; text search finds references and docs -- TOGETHER they reveal: actual behavior + dead code + documentation gaps + design issues +**Two reasons this matters, and the second is the one usually missed:** + +1. **Richer results** — each agent brings different tools and perspective; together they + reveal actual behavior + dead code + documentation gaps + design issues. +2. **Wall-clock** — a task delegated in three sequential waves takes roughly the sum of + those waves. The same agents batched into one wave take the length of the longest. + Sequential waves of independent work are pure waste. + +### The Independence Test + +Before dispatching a wave, ask: **would I write any of these instructions differently if I +had the others' results first?** + +- **No** → they are independent. They belong in the SAME turn. Emit them now. +- **Yes** → only the ones that consume a result wait. Everything else still goes now. + +And before dispatching wave N+1, ask: **could this have gone out with wave N?** If yes, you +already paid for the mistake — batch the remainder. --- diff --git a/modules/tool-delegate/amplifier_module_tool_delegate/__init__.py b/modules/tool-delegate/amplifier_module_tool_delegate/__init__.py index 7312b97b..3f594501 100644 --- a/modules/tool-delegate/amplifier_module_tool_delegate/__init__.py +++ b/modules/tool-delegate/amplifier_module_tool_delegate/__init__.py @@ -257,8 +257,21 @@ def description(self) -> str: # Add usage notes base_description += """ +BATCH YOUR DELEGATIONS. Every delegate call you emit in a single turn runs +CONCURRENTLY. Delegations you split across separate turns run SEQUENTIALLY, and +you block on each one before planning the next. + +Before emitting any delegate call, enumerate every delegation this task needs. +Emit ALL of them that do not consume another delegation's output in THIS turn. +Only a delegation that literally needs a prior result as input belongs in a +later turn. + +- Two independent delegations in one turn: finishes in the time of the slower one +- The same two split across two turns: takes the sum, plus your own planning turn +- "I'll see what the first one says first" is the failure mode - if you would not + change the second instruction based on the first result, it was independent + Agent usage notes: -- Launch multiple agents concurrently when tasks are independent - When an agent completes, it returns a single message back to you - Each agent invocation is stateless - provide complete context in your instruction - DEFAULT TO DELEGATION - only do simple single-step work yourself"""