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