Class: SwarmSDK::Agent::ChatHelpers::ContextTracker

Inherits:
Object
  • Object
show all
Includes:
LoggingHelpers
Defined in:
lib/swarm_sdk/agent/chat_helpers/context_tracker.rb

Overview

Manages context tracking, delegation tracking, and logging callbacks

Responsibilities:

  • Register RubyLLM callbacks for logging
  • Track tool executions
  • Track delegations (which tool calls are delegations)
  • Emit log events via LogStream
  • Check context warnings

This is a stateful helper that's instantiated per Agent::Chat instance.

Thread Safety and Fiber-Local Storage

IMPORTANT: LogStream.emit calls in this class DO NOT explicitly pass swarm_id, parent_swarm_id, or execution_id. These values are automatically injected from Fiber-local storage (Fiber, etc.) by LogStream.emit.

Why: In threaded environments (Puma, Sidekiq), swarm/agent instances may be reused across multiple requests/jobs. If we explicitly pass @agent_context.swarm_id, callbacks would use STALE values from the first request, causing events to be lost or misattributed.

By relying on Fiber-local storage, each request/job gets the correct context even when reusing the same swarm instance. Fiber storage is set at the start of Swarm#execute and inherited by child fibers (tool calls, delegations).

This design works correctly in both:

  • Single-threaded environments (rails runner, console)
  • Multi-threaded environments (Puma, Sidekiq)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LoggingHelpers

#calculate_cost, #format_tool_calls, #serialize_result, #zero_cost

Constructor Details

#initialize(chat, agent_context) ⇒ ContextTracker

Returns a new instance of ContextTracker.



40
41
42
43
44
45
# File 'lib/swarm_sdk/agent/chat_helpers/context_tracker.rb', line 40

def initialize(chat, agent_context)
  @chat = chat
  @agent_context = agent_context
  @tool_executions = []
  @finish_reason_override = nil
end

Instance Attribute Details

#agent_contextObject (readonly)

Returns the value of attribute agent_context.



38
39
40
# File 'lib/swarm_sdk/agent/chat_helpers/context_tracker.rb', line 38

def agent_context
  @agent_context
end

#finish_reason_override=(value) ⇒ Object (writeonly)

Set a custom finish reason for the next agent_stop event

This is used when finish_agent or finish_swarm terminates execution early.

Parameters:

  • reason (String)

    Custom finish reason (e.g., "finish_agent", "finish_swarm")



52
53
54
# File 'lib/swarm_sdk/agent/chat_helpers/context_tracker.rb', line 52

def finish_reason_override=(value)
  @finish_reason_override = value
end

Instance Method Details

#extract_delegate_agent_name(tool_name) ⇒ String

Extract agent name from delegation tool name

Converts "#Tools::Delegate::TOOL_NAME_PREFIX" to "agent_name" Example: "WorkWithWorker" -> "worker"

Parameters:

  • tool_name (String)

    Delegation tool name

Returns:

  • (String)

    Agent name



75
76
77
78
79
80
81
# File 'lib/swarm_sdk/agent/chat_helpers/context_tracker.rb', line 75

def extract_delegate_agent_name(tool_name)
  # Remove tool name prefix and lowercase first letter
  agent_name = tool_name.to_s.sub(/^#{Tools::Delegate::TOOL_NAME_PREFIX}/, "")
  # Convert from PascalCase to lowercase (e.g., "Worker" -> "worker", "BackendDev" -> "backendDev")
  agent_name[0] = agent_name[0].downcase unless agent_name.empty?
  agent_name
end

#setup_loggingvoid

This method returns an undefined value.

Setup logging callbacks

Registers RubyLLM callbacks to collect data and emit log events. Should only be called when LogStream.emitter is set. This method is idempotent - calling it multiple times has no effect.



61
62
63
64
65
66
# File 'lib/swarm_sdk/agent/chat_helpers/context_tracker.rb', line 61

def setup_logging
  return if @logging_setup

  register_logging_callbacks
  @logging_setup = true
end