Module: Agents

Defined in:
lib/agents/tool.rb,
lib/agents.rb,
lib/agents/agent.rb,
lib/agents/result.rb,
lib/agents/runner.rb,
lib/agents/handoff.rb,
lib/agents/version.rb,
lib/agents/agent_tool.rb,
lib/agents/run_context.rb,
lib/agents/agent_runner.rb,
lib/agents/tool_context.rb,
lib/agents/tool_wrapper.rb,
lib/agents/callback_manager.rb,
lib/agents/message_extractor.rb

Overview

ToolContext provides tools with controlled access to execution state during their invocation. It wraps the RunContext and adds tool-specific metadata like retry count. This is a critical component of the thread-safe design - tools receive all their execution state through this context object rather than storing it in instance variables.

## How Thread Safety is Ensured

ToolContext enables thread-safe tool execution by enforcing a critical principle: all execution state must flow through method parameters, never through instance variables.

Here’s how it works:

  1. **Tool instances are stateless** - They only store configuration (name, description), never execution data like current user, session, or request details.

  2. **State flows through parameters** - When a tool is executed, it receives a ToolContext parameter that contains all the execution-specific state it needs.

  3. **Each execution is isolated** - Multiple threads can call the same tool instance simultaneously, but each call gets its own ToolContext with its own state.

This is similar to how web frameworks handle concurrent requests - the controller instance might be shared, but each request gets its own params and session objects. The ToolContext serves the same purpose, providing isolation without requiring new object creation for each execution.

Examples:

Tool receiving context during execution

class CalculatorTool < Agents::Tool
  def perform(tool_context, expression:)
    # Access shared context data
    precision = tool_context.context[:precision] || 2

    # Track retry attempts
    if tool_context.retry_count > 0
      logger.warn "Retrying calculation (attempt #{tool_context.retry_count + 1})"
    end

    result = eval(expression)
    result.round(precision)
  end
end

Runner creating ToolContext for execution

run_context = Agents::RunContext.new({ user: current_user })
tool_context = Agents::ToolContext.new(
  run_context: run_context,
  retry_count: 0
)

result = tool.execute(tool_context, expression: "2 + 2")

Defined Under Namespace

Classes: Agent, AgentRunner, AgentTool, CallbackManager, Configuration, Error, HandoffTool, MessageExtractor, RunContext, RunResult, Runner, Tool, ToolContext, ToolWrapper

Constant Summary collapse

"# System context\n" \
"You are part of a multi-agent system called the Ruby Agents SDK, designed to make agent " \
"coordination and execution easy. Agents uses two primary abstraction: **Agents** and " \
"**Handoffs**. An agent encompasses instructions and tools and can hand off a " \
"conversation to another agent when appropriate. " \
"Handoffs are achieved by calling a handoff function, generally named " \
"`handoff_to_<agent_name>`. Transfers between agents are handled seamlessly in the background; " \
"do not mention or draw attention to these transfers in your conversation with the user.\n"
VERSION =
"0.5.0"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.loggerObject

Logger for debugging (can be set by users)



28
29
30
# File 'lib/agents.rb', line 28

def logger
  @logger
end

Class Method Details

.configurationObject



37
38
39
# File 'lib/agents.rb', line 37

def configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Configure both Agents and RubyLLM in one block

Yields:



31
32
33
34
35
# File 'lib/agents.rb', line 31

def configure
  yield(configuration) if block_given?
  configure_ruby_llm!
  configuration
end