How programmatic tool calling works
When you configure a tool to be callable from code execution and Claude determines that tool is needed:
- Claude writes Python code that invokes the tool as a function, potentially including multiple tool calls and pre/post-processing logic
- Claude runs this code in a sandboxed container through code execution
- When a tool function is called, code execution pauses and the API returns a
tool_useblock - You provide the tool result, and code execution continues (intermediate results are not loaded into Claude's context window)
- Once all code execution completes, Claude receives the final output and continues working on the task
This approach is particularly useful for:
Large data processing: Filter or aggregate tool results before they reach Claude's context
Multistep workflows: Save tokens and latency by calling tools serially or in a loop without sampling Claude in-between tool calls
Conditional logic: Make decisions based on intermediate tool results
Tools that allow a code execution caller are exposed to Claude's code as async Python functions, so Claude can run them in parallel with
asyncio.gather. Each function takes a single dict of arguments and returns a string: the text of thetool_resultyou send back. Claude's code awaits these functions with top-levelawaitand parses results that it needs as structured data, for examplerows = json.loads(await query_database(\{"sql": "<sql>"\})).