Skip to main content
This page explains the analytics model and the members accepted by the query endpoint.

Terms

Models

Grain says what one row represents. For agent_runs, each row is one agent run. Excluded sub-agents belong to that agent run and are not counted separately. Individual messages and tool calls inside a run are not rows either. Event clock is the timestamp that decides which range bucket a row falls into. agent_runs uses the moment the run was created, so date filters and the day dimension group runs by when they started. For agent_user_activity, each row is one attribution record. The person is named by a normalized email address or an E.164 phone number. Its occurredAt event clock uses the time of the attribution record. A person who joins an older run appears in the period when they joined, not when the run started.

Which channels produce attribution records

A channel produces an attribution record only when it supplies an address the API can group by. manual, outlook_email, front_email, front_mention, agent_email, phone_inbound, and text_message_inbound produce records. slack_mention produces an initiated record only, and only when the mention resolved to the author’s email address. Script-launched runs use the script trigger source and are automated, so they produce no person attribution records. Teams, Twilio, and self-serve webhook triggers likewise produce no attribution records at all, so runs from those channels are absent from agent_user_activity while still being counted in agent_runs.

Metrics

All metrics return numbers. Additive metrics can be summed across groups (for example, weekly totals from daily groups). Non-additive metrics cannot be summed; selecting one adds a non_additive_metric warning to the response. No metric or dimension is currently deprecated. See Versioning and deprecation.

agent_runs metrics

Notes:
  • The four status count metrics partition the same rows by outcome, so within one result completed_run_count + failed_run_count + cancelled_run_count + active_run_count equals run_count.
  • run_success_rate is computed per group after grouping. Do not average or sum it across groups; re-query the groups you need instead.

agent_user_activity metrics

Every count below is over the attribution records that the query’s range and filters selected. [email protected] starts one run and later sends three messages. attributed_run_count, initiated_run_count, and interacted_run_count are each 1. interaction_count is 3.

How associated_run_count is calculated

associated_run_count is arithmetic, not a stored category:
Both values come from the records selected by the query’s date range and filters. [email protected] starts a run on Monday and sends a message on Tuesday. A Tuesday-only query sees one attributed run and no initiated run, so associated_run_count is 1. A query covering both days returns 1 - 1 = 0. This metric is calculated from the selected records. It is not a count of rows whose activity_type is associated.

Dimensions

Dimensions group results. Selecting a dimension produces one row per distinct value inside the range. Filters accept these names too (see Filtering and ordering).

agent_runs dimensions

agent_user_activity dimensions

agent_id, user_identifier, and day are named the same as on agent_runs and carry the same companion fields, but day groups by occurredAt rather than by when the run started. There is no user_type dimension on this model. run_initiation_type classifies the run, not the person.

Companion fields

Companion fields enrich a dimension and are returned automatically whenever their dimension is selected. You cannot request them on their own. Each one appears immediately after its dimension in columns:
  • agent_name: current display name from the joined task-agent record. Soft-deleted agents remain joinable, but renaming an agent changes the name shown for historical runs.
  • user_name: lexicographically greatest non-null display name in the user_identifier group.
Companions are plain output columns: they cannot be filtered or ordered by name, and they do not count toward the eight-dimension limit.

Filtering and ordering

  • Filters apply to dimensions only. A filter on a metric or companion name is rejected as unknown_member.
  • Each filter is either "eq" with one value, or "in" with a values array of 1–50 non-empty strings. At most eight filters apply per query.
  • Use YYYY-MM-DD local dates in the range timezone for day filters. Filter strings are not independently date-validated; an unmatched value returns no rows.
  • Filter values are strings; there is no equality test for null. To see the unattributed group, do not filter on that dimension. It appears as null rows.
  • Up to eight unique order terms ({ member, direction }) may reference selected metrics or dimensions. Totals queries cannot specify ordering. Ordering by anything else is rejected as invalid_query.
  • Without an explicit order, results sort ascending by every selected dimension. Explicit terms apply first, then remaining dimensions ascend. Ascending sorts place null values last; descending sorts place them first.
  • Ordering by a metric produces a single-page top-N result and never returns a cursor. Dimension-ordered grouped queries paginate. See Pagination.

Versioning and deprecation

catalogVersion identifies the published metric and dimension set and its semantics. It is response metadata only: requests cannot pin a version, and a request body containing catalogVersion is rejected. When the catalog changes, the version changes too, and any outstanding pagination cursor stops working with invalid_cursor; restart the walk from a fresh request. Every metric and dimension carries a deprecated field; models and companion fields do not. It is currently null for every metric and dimension. When set, the object contains since (the catalog version that introduced the deprecation) and note (migration guidance). Deprecated members remain queryable and do not automatically add a query warning, so clients should inspect this metadata.

Example