[FEATURE] Programmatic tool calling for Claude Code's built-in tools (data-dependent Read/Grep/Edit steps without a model round trip each)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet (#33761 asked for it and was closed as not planned and locked, so it can't take a comment; #56849 asked for the MCP-only version and is closed; this re-file adds a week of measurements)
- [x] This is a single feature request (not multiple features)
Problem Statement
In Claude Code, every step whose input depends on an earlier result costs a full model round trip.
Claude Code 2.1.280 already handles fixed batches well: several tool_use blocks in one message run, with read-only ones running concurrently and Write, Edit and Bash running in the order emitted. Please keep that; an ordered "batch" wrapper would duplicate it.
The gap is data-dependent work: Glob, then Read each returned path, then keep the matches, then Edit or test them. Each hop is another request that re-reads the whole context.
Measured on one machine over one week (2026-09-16T15:55Z to 2026-09-23T15:55Z, 25,864 tool-result cycles, Claude Code 2.1.280):
- A round trip after a tool result costs a median 4.0 s and 232,743 context tokens in main sessions, and 3.0 s and 111,720 in subagents; 99% and 98% of that is cache reads.
- Summed over the week: 38.89 agent-hours of waiting and 4.234 billion context tokens.
- About 765 follow-ups were a Read or
sedof a file that a search had just found, and 810 were a lone confirmation after a write.
Proposed Solution
Expose API programmatic tool calling for Claude Code's built-in tools, or add one native tool (say ToolProgram) that runs a bounded program of built-in calls with no model inference between steps:
- explicit sequential and parallel groups;
- references to earlier step results as later inputs;
mapover a result list, and simple conditions;on_error: stop | continue, and a cap on steps and output size.
Every nested call goes through its normal permission check, hooks, sandbox, result limits, diff display and transcript record, and returns a structured result per step. Writes are never reordered.
Done looks like this: one response Globs the matching files, maps Read over the returned paths, selects the matches, then runs a check whose input references those results. The read-only map steps overlap, later writes stay in order, denied and failed steps are reported explicitly, and the transcript and hooks look the same as for direct calls.
Out of scope: speculative execution against expected results (that's #96404), transactional rollback, and replacing parallel tool calls or Workflow.
Alternative Solutions
- Several
tool_useblocks in one message. Fixed inputs only: a step can't use an earlier step's result, and one failure takes down the batch (#22264). - One Bash command. Loops work, but it can't call Read, Edit or Grep with their own permission checks, hooks, limits and diffs, and permissions see one opaque command.
- An MCP server. It can reimplement the operations but can't invoke the host's built-in tools with the same semantics.
- #96404, speculative sequences with
expect. Saves round trips on a predicted path, but deliberately has no loops or result references, so a map over Glob output still costs one trip per step. - API programmatic tool calling. It runs in Anthropic's remote container and isn't exposed for Claude Code's client-side tools (#33761, #12836).
Priority
High - Significant impact on productivity
Feature Category
Performance and speed
Use Case Example
An agent must find every skill file that mentions a rule and fix the stale line in each. Today that's Grep (1 trip), Read each hit (1 trip, if batched), Edit each (1 trip), then re-read or test (1 trip): four round trips, about 16 s and 930k context tokens at the main-session median. It's more when the reads can't be planned before the grep returns.
With a tool program, it's one trip for the grep, map-read, select and checks, then one model turn to write the edits.
Additional Context
Method: transcripts under ~/.claude/projects, grouped by message ID. A round trip runs from the last tool_result of a message to the first row of the next distinct assistant message. Cycles interrupted by a human message are excluded. Only 17.5% of messages containing a write already carried the next independent call. The analyzer is a 500-line Python script over the transcript JSONL, and we can attach it.
Related: #33761 (closed, locked), #12836 (closed, locked), #56849 (MCP programmatic execution, closed), #96404 (speculative sequences, open), #22264 (a failure in parallel calls fails the batch).
Claude Code 2.1.280, Linux.