class

Anthropic::ToolRunner

Inherits Reference < Object

Automatic tool execution loop

Runs a conversation with Claude where tools are automatically executed and their results are fed back to Claude until the conversation completes.

Supports auto-compaction to manage conversation length in extended sessions.

# Basic usage - iterate all messages
runner = client.beta.messages.tool_runner(
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [Anthropic::MessageParam.user("What's the weather?")],
  tools: [weather_tool]
)
runner.each_message { |msg| pp msg.content }

# Step-by-step control
runner = client.beta.messages.tool_runner(...)
while msg = runner.next_message
  pp msg.content
  if some_condition
    runner.feed_messages([MessageParam.user("Actually, also check...")])
  end
end

# Streaming with tool execution
runner.each_streaming do |event|
  case event
  when Anthropic::ContentBlockDeltaEvent
    print event.text # event.text is a streaming helper, not Message#text
  end
end

Constructors

new(client : Client, model : String, max_tokens : Int32, messages : Array(MessageParam), tools : Array(Tool), max_iterations : Int32 = 10, system : String | Nil = nil, compaction : CompactionConfig | Nil = nil, speed : String | Nil = nil, thinking : ThinkingConfig | Nil = nil, output_config : OutputConfig | Nil = nil, inference_geo : String | Nil = nil, container : String | ContainerConfig | Nil = nil, betas : Array(String) = [] of String, use_beta : Bool = false)
Source

Instance methods

current_messages

Get the current accumulated messages (including tool results)

Source
each_message

Iterate through messages, auto-executing tools

Yields each message response, including those with tool use. Continues until max_iterations is reached or Claude stops using tools.

If compaction is enabled, automatically compresses conversation when token usage exceeds the configured threshold.

Note: This resets the runner state before iterating.

Source
each_streaming

Iterate through streaming events while auto-executing tools

Similar to each_message but yields streaming events in real-time. Tool execution still happens between streaming responses.

runner.each_streaming do |event|
  case event
  when Anthropic::ContentBlockDeltaEvent
    if text = event.text
      print text
    end
  end
end
Source
feed_message(message : MessageParam)

Add a single message to the conversation

Source
feed_messages(messages : Array(MessageParam))

Add messages to the conversation mid-loop

Use this to inject additional context or instructions during tool execution. Messages are added after the current tool results.

while msg = runner.next_message
  # Check content and inject more messages if needed
  runner.feed_messages([
    Anthropic::MessageParam.user("Here's additional context: ..."),
  ])
end
Source
final_message

Get final message after all tool execution

Runs the entire conversation and returns the last message.

Source
finished?

Check if the runner has finished (no more tool calls or max iterations reached)

Source
last_response

Get the last response received

Source
next_message

Get the next message in the tool execution loop

Returns nil when the loop is complete (no more tool calls or max iterations). Use this for fine-grained control over the execution loop.

while msg = runner.next_message
  pp msg.content
  # Optionally inject messages
  runner.feed_messages([...]) if some_condition
end
Source
params

Get current runner parameters (read-only)

Useful for inspecting or logging the current state.

Source
reset

Reset the runner to its initial state

Source
run_until_finished

Run until finished and return all messages

Executes the entire tool loop and returns all messages generated.

messages = runner.run_until_finished
messages.each { |msg| pp msg.content }
Source