From 3035b9f098ba2449690fca7f141b05f13f5df2ae Mon Sep 17 00:00:00 2001 From: Eric Lee Date: Sun, 26 Jul 2026 03:01:15 -0700 Subject: [PATCH] perf(prompt): restore the dropped "maximize parallel tool calls" guidance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Iteration 2 on the trajectory-step gap against the latest Claude Code (same model, same effort). Iteration 1 (#749) took the subset mean from 25.5 to 13.2 steps against CC's 7.5; this addresses the largest remaining structural difference. Measured on the same tasks: clawcodex emits more than one tool call per assistant turn in **5.7%** of steps, the latest Claude Code in **18.1%**. Every independent pair it does not batch is an extra step, so that ratio is most of what remains between the two step counts. Reading the trajectories side by side shows it plainly — on regex-log CC issued 8 calls, all Bash, batching probes ("for c in node deno perl ruby; do command -v $c; done") and creating files with heredocs; clawcodex issued 17, alternating Write then Bash and probing one command at a time. Cause is a truncated port. The reference bullet has three parts: You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. ... clawcodex kept only the first sentence. What was dropped is what turns a permission into a practice: the imperative to maximize, and the dependency carve-out. The carve-out matters as much as the push — without a statement of when NOT to parallelize, "call them in parallel" is risky advice a careful model will mostly decline, which is what the 5.7% looks like. Same defect class as #748 (dropped qualifiers on the file-creation bullet), and general rather than benchmark-specific: batching independent work is better agent behavior everywhere. Tests: 8843 passed. The new test pins all three clauses, since restoring only the push would leave the model without the safety half. Co-Authored-By: Claude Opus 5 --- src/context_system/prompt_assembly.py | 15 ++++++++++++++- tests/test_system_prompt_full.py | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/context_system/prompt_assembly.py b/src/context_system/prompt_assembly.py index 5ef6b4e9..41bb12ae 100644 --- a/src/context_system/prompt_assembly.py +++ b/src/context_system/prompt_assembly.py @@ -1009,9 +1009,22 @@ def _emit_group( "operations that require shell execution. If you are unsure and there " "is a relevant dedicated tool, default to using the dedicated tool.\n" "- Break down and manage your work with the TaskCreate tool.\n" + # Two clauses were dropped in the port, and together they are what turns + # a permission into a practice: the imperative to maximize, and the + # dependency carve-out that tells the model when NOT to — without which + # "in parallel" is risky advice a careful model will mostly decline. + # Measured effect of the truncation: clawcodex emits more than one tool + # call per assistant turn in 5.7% of steps against the latest Claude + # Code's 18.1% on the same tasks — and every un-batched pair is an extra + # step, which is most of what the two harnesses' step counts differ by. "- You can call multiple tools in a single response. If you intend to " "call multiple tools and there are no dependencies between them, " - "make all independent tool calls in parallel." + "make all independent tool calls in parallel. Maximize use of parallel " + "tool calls where possible to increase efficiency. However, if some " + "tool calls depend on previous calls to inform dependent values, do " + "NOT call these tools in parallel and instead call them sequentially. " + "For instance, if one operation must complete before another starts, " + "run these operations sequentially instead." ) # Module 6: Tone and style diff --git a/tests/test_system_prompt_full.py b/tests/test_system_prompt_full.py index be5843d9..45af95b7 100644 --- a/tests/test_system_prompt_full.py +++ b/tests/test_system_prompt_full.py @@ -137,6 +137,30 @@ def test_task_prompt_scopes_escalation_to_genuine_blockage(self): assert "genuinely stuck after investigation" in prompt assert "not as a first response to friction" in prompt + def test_tools_prompt_pushes_parallel_tool_calls(self): + """Bare permission to batch is not enough — the port dropped the push. + + Reference wording carries three parts: you may call multiple tools, + MAXIMIZE parallel calls for efficiency, and do NOT parallelize + dependent calls. clawcodex kept only the first, which reads as + permission without direction — and the dependency carve-out is what + makes acting on it safe. + + Measured cost: clawcodex emitted >1 tool call per assistant turn in + 5.7% of steps against the latest Claude Code's 18.1% on the same + terminal-bench 2.1 tasks (2026-07-26). Each un-batched independent + pair is an extra step, which is most of the two harnesses' step-count + difference. + """ + prompt = build_full_system_prompt(use_cache=False) + assert "make all independent tool calls in parallel" in prompt + assert "Maximize use of parallel tool calls" in prompt, ( + "without the imperative, batching stays theoretical" + ) + assert "do NOT call these tools in parallel" in prompt, ( + "the dependency carve-out is what makes parallelizing safe to act on" + ) + def test_identity_prompt_backward_compat(self): """_IDENTITY_PROMPT is an alias for _INTRO_SECTION.""" assert _IDENTITY_PROMPT is _INTRO_SECTION