Class: ActionAgent::AgentExecutions
- Inherits:
-
Object
- Object
- ActionAgent::AgentExecutions
- Defined in:
- app/queries/action_agent/agent_executions.rb
Overview
One agent execution, whoever ran it.
The platform records executions it initiates as AgentRun rows; agents
running inside a customer's own app only ever produce a TelemetryTrace.
They are the same grain — one attempt at one agent action — so the
dashboard treats them as one list with a source discriminator rather
than as two competing tabs:
dashboard — an AgentRun (we executed it; has lifecycle, logs, cancel)
reported — a trace no AgentRun claims (their app executed it)
A platform execution usually writes BOTH an AgentRun and a trace sharing a trace_id, so traces are counted only when unclaimed. The reverse is not symmetric: a run that fails before its root span exists has no trace at all, which is why runs — not traces — are the authoritative source when both exist.
Distinct from AgentContext, which is a stream: one durable conversation per agent action that many executions append to. A stream is a parent of executions, not an alternative to them.
Defined Under Namespace
Classes: Row
Constant Summary collapse
- SOURCES =
%w[dashboard reported].freeze
- SORTS =
What to rank a list of executions by. "Popular" is deliberately absent: it's an aggregate property of an agent or a model, not of one attempt — the agent list and the metrics table sort by it, this list can't.
{ "recent" => "Most recent", "longest" => "Longest running", "cost" => "Highest cost", "tokens" => "Most tokens" }.freeze
- DEFAULT_SORT =
"recent"
Class Method Summary collapse
-
.unclaimed_traces(agent_ids, since: nil, owner: nil) ⇒ Object
Traces attributed to these agents that no AgentRun already accounts for.
Instance Method Summary collapse
-
#initialize(agents:, owner: nil, window_minutes: nil, source: nil, status: nil, sort: nil) ⇒ AgentExecutions
constructor
A new instance of AgentExecutions.
-
#page(page: 1, per_page: 20) ⇒ Object
Ranked by the chosen dimension, descending.
- #rows ⇒ Object
- #sorted_rows ⇒ Object
Constructor Details
#initialize(agents:, owner: nil, window_minutes: nil, source: nil, status: nil, sort: nil) ⇒ AgentExecutions
Returns a new instance of AgentExecutions.
62 63 64 65 66 67 68 69 |
# File 'app/queries/action_agent/agent_executions.rb', line 62 def initialize(agents:, owner: nil, window_minutes: nil, source: nil, status: nil, sort: nil) @agent_ids = Array(agents.respond_to?(:pluck) ? agents.pluck(:id) : agents.map(&:id)) @owner = owner @window_minutes = window_minutes @source = source.presence @status = status.presence @sort = SORTS.key?(sort.to_s) ? sort.to_s : DEFAULT_SORT end |
Class Method Details
.unclaimed_traces(agent_ids, since: nil, owner: nil) ⇒ Object
Traces attributed to these agents that no AgentRun already accounts for. Shared with AgentScorecard so every surface counts the same executions.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'app/queries/action_agent/agent_executions.rb', line 93 def self.unclaimed_traces(agent_ids, since: nil, owner: nil) traces = ActionAgent.trace_model runs_table = AgentRun.table_name traces_table = traces.table_name scope = traces.where(agent_id: agent_ids) scope = scope.for_account(owner) if owner scope = scope.where(timestamp: since..) if since scope .joins(<<~SQL.squish) LEFT JOIN #{runs_table} ON #{runs_table}.trace_id = #{traces_table}.trace_id AND #{runs_table}.agent_id = #{traces_table}.agent_id SQL .where(runs_table => { id: nil }) end |
Instance Method Details
#page(page: 1, per_page: 20) ⇒ Object
Ranked by the chosen dimension, descending. The two sources can only be ordered together in Ruby (no SQL union), which is also why this always ranks the whole window rather than the page.
74 75 76 77 78 |
# File 'app/queries/action_agent/agent_executions.rb', line 74 def page(page: 1, per_page: 20) all = sorted_rows offset = (page.to_i - 1) * per_page.to_i { rows: all[offset, per_page.to_i] || [], total: all.size } end |
#rows ⇒ Object
87 88 89 |
# File 'app/queries/action_agent/agent_executions.rb', line 87 def rows @rows ||= (include_dashboard? ? run_rows : []) + (include_reported? ? trace_rows : []) end |
#sorted_rows ⇒ Object
80 81 82 83 84 85 |
# File 'app/queries/action_agent/agent_executions.rb', line 80 def sorted_rows # Ties (and rows missing the sorted value entirely — an execution still # running has no duration) fall back to newest first, so the list never # reorders arbitrarily between requests. rows.sort_by { |row| [ -sort_value(row), -(row.occurred_at || Time.at(0)).to_f ] } end |