Anthropic::ToolRunner
Bounded tool-runner loop for agentic workflows.
Manages the tool_use -> tool_result conversation loop with configurable bounds. The runner automatically handles the cycle of:
- Sending a request to the API
- Checking if the response contains tool_use blocks
- Executing each tool via the provided block
- Appending assistant response + tool results to the conversation
- Repeating until no tool_use or max_iterations is reached
Usage
client = Anthropic::Client.new
request = Anthropic::Messages::Request.new(
model: Anthropic::Model.sonnet,
messages: [Anthropic::Message.user("What's the weather in SF?")],
max_tokens: 1024,
tools: [weather_tool]
)
result = Anthropic::ToolRunner.run(client, request) do |tool_block|
# Execute the tool and return JSON result
if tool_block.name == "get_weather"
JSON.parse(%({"temperature": 72, "condition": "sunny"}))
else
JSON.parse(%({"error": "Unknown tool"}))
end
end
puts result.text # Final response after tool execution
Bounds
max_iterations: Maximum number of tool rounds (default: 10)- Returns early if stop_reason != "tool_use"
Class methods
run(client : Client, initial_request : Messages::Request, max_iterations : Int32 = 10, request_options : RequestOptions | Nil = nil, & : ResponseToolUseBlock -> String | JSON::Any) : Messages::Response
Run a bounded tool loop.
Parameters:
- client: The Anthropic client to use
- initial_request: The initial messages request
- max_iterations: Maximum tool execution rounds (default: 10)
- request_options: Per-request options forwarded to each API call
- block: Executor that receives each tool_use block and returns a JSON result
Returns:
- The final Messages::Response (when stop_reason != "tool_use" or max_iterations reached)
Yields:
- ResponseToolUseBlock for each tool that needs execution
Example:
result = ToolRunner.run(client, request, max_iterations: 5) do |tool|
execute_tool(tool.name, tool.input)
end