Class: SwarmSDK::Result

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_sdk/result.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content: nil, agent:, cost: nil, tokens: nil, duration: 0.0, logs: [], error: nil, metadata: {}) ⇒ Result

Returns a new instance of Result.



7
8
9
10
11
12
13
14
15
16
# File 'lib/swarm_sdk/result.rb', line 7

def initialize(content: nil, agent:, cost: nil, tokens: nil, duration: 0.0, logs: [], error: nil, metadata: {})
  @content = content
  @agent = agent
  @duration = duration
  @logs = logs
  @error = error
  @metadata = 
  # Legacy parameters kept for backward compatibility but not stored
  # Use total_cost and tokens methods instead which calculate from logs
end

Instance Attribute Details

#agentObject (readonly)

Returns the value of attribute agent.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def agent
  @agent
end

#contentObject (readonly)

Returns the value of attribute content.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def content
  @content
end

#durationObject (readonly)

Returns the value of attribute duration.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def duration
  @duration
end

#errorObject (readonly)

Returns the value of attribute error.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def error
  @error
end

#logsObject (readonly)

Returns the value of attribute logs.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def logs
  @logs
end

#metadataObject (readonly)

Returns the value of attribute metadata.



5
6
7
# File 'lib/swarm_sdk/result.rb', line 5

def 
  @metadata
end

Instance Method Details

#agents_involvedObject

Get list of all agents involved in execution



108
109
110
# File 'lib/swarm_sdk/result.rb', line 108

def agents_involved
  @logs.map { |entry| entry[:agent] }.compact.uniq.map(&:to_sym)
end

#costFloat

Calculate total cost from logs

Delegates to total_cost for consistency. This attribute is calculated dynamically rather than stored.

Returns:

  • (Float)

    Total cost in dollars



32
33
34
# File 'lib/swarm_sdk/result.rb', line 32

def cost
  total_cost
end

#failure?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/swarm_sdk/result.rb', line 22

def failure?
  !success?
end

#llm_requestsObject

Count total LLM requests made Each LLM API call produces either agent_step (tool calls) or agent_stop (final answer)



166
167
168
# File 'lib/swarm_sdk/result.rb', line 166

def llm_requests
  @logs.count { |entry| entry[:type] == "agent_step" || entry[:type] == "agent_stop" }
end

#per_agent_usageHash{Symbol => Hash}

Get per-agent usage breakdown from logs

Aggregates context usage, tokens, and cost for each agent from their final agent_stop or agent_step events. Each agent's entry includes:

  • input_tokens, output_tokens, total_tokens
  • context_limit, usage_percentage, tokens_remaining
  • input_cost, output_cost, total_cost

Examples:

result.per_agent_usage[:backend]
# => {
#   input_tokens: 15000,
#   output_tokens: 5000,
#   total_tokens: 20000,
#   context_limit: 200000,
#   usage_percentage: "10.0%",
#   tokens_remaining: 180000,
#   input_cost: 0.045,
#   output_cost: 0.075,
#   total_cost: 0.12
# }

Returns:

  • (Hash{Symbol => Hash})

    Per-agent usage breakdown



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/swarm_sdk/result.rb', line 135

def per_agent_usage
  # Find the last usage entry for each agent
  agent_entries = {}

  @logs.each do |entry|
    next unless entry[:usage] && entry[:agent]
    next unless entry[:type] == "agent_step" || entry[:type] == "agent_stop"

    agent_name = entry[:agent].to_sym
    agent_entries[agent_name] = entry[:usage]
  end

  # Build breakdown from final usage entries
  agent_entries.transform_values do |usage|
    {
      input_tokens: usage[:cumulative_input_tokens] || 0,
      output_tokens: usage[:cumulative_output_tokens] || 0,
      total_tokens: usage[:cumulative_total_tokens] || 0,
      cached_tokens: usage[:cumulative_cached_tokens] || 0,
      context_limit: usage[:context_limit],
      usage_percentage: usage[:tokens_used_percentage],
      tokens_remaining: usage[:tokens_remaining],
      input_cost: usage[:input_cost] || 0.0,
      output_cost: usage[:output_cost] || 0.0,
      total_cost: usage[:total_cost] || 0.0,
    }
  end
end

#success?Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/swarm_sdk/result.rb', line 18

def success?
  @error.nil?
end

#to_hObject



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/swarm_sdk/result.rb', line 52

def to_h
  {
    content: @content,
    agent: @agent,
    cost: cost,
    tokens: tokens,
    duration: @duration,
    success: success?,
    error: @error&.message,
    metadata: @metadata,
  }.compact
end

#to_json(*args) ⇒ Object



65
66
67
# File 'lib/swarm_sdk/result.rb', line 65

def to_json(*args)
  to_h.to_json(*args)
end

#tokensHash

Get token breakdown from logs

Returns input and output tokens from the last log entry with usage data. This attribute is calculated dynamically rather than stored.

Returns:

  • (Hash)

    Token breakdown with :input and :output keys, or empty hash if no usage data



42
43
44
45
46
47
48
49
50
# File 'lib/swarm_sdk/result.rb', line 42

def tokens
  last_entry = @logs.reverse.find { |entry| entry.dig(:usage, :cumulative_input_tokens) }
  return {} unless last_entry

  {
    input: last_entry.dig(:usage, :cumulative_input_tokens) || 0,
    output: last_entry.dig(:usage, :cumulative_output_tokens) || 0,
  }
end

#tool_calls_countObject

Count total tool calls made



171
172
173
# File 'lib/swarm_sdk/result.rb', line 171

def tool_calls_count
  @logs.count { |entry| entry[:type] == "tool_call" }
end

#total_costObject

Calculate total cost across all LLM responses

Cost accumulation works as follows:

  • Input cost: The LAST response's input_cost already includes the cost for the full conversation history (all previous messages + current context)
  • Output cost: Each response generates NEW tokens, so we SUM all output_costs
  • Total = Last input_cost + Sum of all output_costs

IMPORTANT: Do NOT sum total_cost across all entries - that would count input costs multiple times since each call includes the full history!



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/swarm_sdk/result.rb', line 79

def total_cost
  entries_with_usage = @logs.select { |entry| entry.dig(:usage, :total_cost) }
  return 0.0 if entries_with_usage.empty?

  # Last entry's input cost (includes full conversation history)
  last_input_cost = entries_with_usage.last.dig(:usage, :input_cost) || 0.0

  # Sum all output costs (each response generates new tokens)
  total_output_cost = entries_with_usage.sum { |entry| entry.dig(:usage, :output_cost) || 0.0 }

  last_input_cost + total_output_cost
end

#total_tokensObject

Get total tokens from the last LLM response with cumulative tracking

Token accumulation works as follows:

  • Input tokens: Each API call sends the full conversation history, so the latest response's cumulative_input_tokens already represents the full context
  • Output tokens: Each response generates new tokens, cumulative_output_tokens sums them
  • The cumulative_total_tokens in the last response already does this correctly

IMPORTANT: Do NOT sum total_tokens across all log entries - that would count input tokens multiple times since each call includes the full history!



102
103
104
105
# File 'lib/swarm_sdk/result.rb', line 102

def total_tokens
  last_entry = @logs.reverse.find { |entry| entry.dig(:usage, :cumulative_total_tokens) }
  last_entry&.dig(:usage, :cumulative_total_tokens) || 0
end