Class: SwarmSDK::Agent::ChatHelpers::ContextTracker
- Inherits:
-
Object
- Object
- SwarmSDK::Agent::ChatHelpers::ContextTracker
- 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
-
#agent_context ⇒ Object
readonly
Returns the value of attribute agent_context.
-
#finish_reason_override ⇒ Object
writeonly
Set a custom finish reason for the next agent_stop event.
Instance Method Summary collapse
-
#extract_delegate_agent_name(tool_name) ⇒ String
Extract agent name from delegation tool name.
-
#initialize(chat, agent_context) ⇒ ContextTracker
constructor
A new instance of ContextTracker.
-
#setup_logging ⇒ void
Setup logging callbacks.
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_context ⇒ Object (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.
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"
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_logging ⇒ void
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 |