Skip to Content
RiusMCPTool reference

Tool reference

Every tool the Rius MCP server exposes, with arguments and example invocations. All tools return Markdown, which your client renders as tables and summaries. Everything is read-only with one exception, create_api_key, which is admin-gated.

Two conventions apply across the trace tools:

  • workspace is optional everywhere: pass a workspace name or ID, or omit it to use your default workspace. Discover workspaces with list_workspaces.
  • hours is a lookback window ending now (default 24). “This week” is hours: 168.

You rarely invoke tools by hand. Ask your client a question, and it picks the tools and arguments itself. The examples show what the client sends, which helps when a question is not picking the tool you expect.

ack_alert

Acknowledge an alert: record that a human has seen it, so it stops notifying.

Acknowledging is NOT resolving. The alert stays open and keeps counting occurrences; only the detector resolves it, once the condition clears. Nothing in Rius can force an alert closed.

Only available on an interactive (OAuth) connection: the acknowledgement records which user saw the alert, and an API key is not a user.

ArgumentTypeDefaultDescription
alert_idstringrequiredthe alert’s id, from list_alerts.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

I’ve seen that alert, stop pinging me about it.

{ "name": "ack_alert", "arguments": { "alert_id": "2f9c…" } }

agent_error_groups

Group a window’s errored spans by failure class — exception type and a normalised message — so a page of failures reads as its handful of causes. One row per group with its count, distinct traces, last occurrence, the instances it hit and sample trace ids for get_agent_trace.

This is the same read the Rius console’s Agent page draws its Exceptions figure from. The unit is errored SPANS with this span’s own identity: count is not agent_traces_summary’s failed_traces (runs whose ROOT span errored) and the two are labelled, never reconciled or added. The grouping reads span events, so the window is capped like any other unindexed query; a window the server refuses comes back saying so.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
agentstring""optional exact agent name — this SPAN’s agent identity, the same value agent= filters on for list_spans. Read a name off list_agents or off root_agent on list_agent_traces rather than guessing one.
instancestring""optional exact instance id, narrowing to one running copy of agent.
limitinteger20groups per page (default 20, server max 100). The reply says how many errored spans the whole window holds, so a full page is visible as one.

What is failing for the planner agent today?

{ "name": "agent_error_groups", "arguments": { "agent": "planner" } }

Group this week’s failures across every agent.

{ "name": "agent_error_groups", "arguments": { "hours": 168, "limit": 50 } }

Is one copy of planner producing the errors?

{ "name": "agent_error_groups", "arguments": { "agent": "planner", "instance": "inst-planner-01" } }

agent_lifecycle_events

The lifecycle log of a workspace’s agent instances — when each copy started, finished, was lost or recovered — newest first, timed when it happened rather than when a page was loaded.

This is the same read the Rius console’s Agent page draws its timeline from. The kinds are the server’s: started (first heartbeat), finished (clean-shutdown ping), lost (silent past the gone threshold, timed at the sweep tick that noticed and carrying last_seen_at for the last ping before the silence) and recovered (a ping after lost). stale is a read-time status on list_agents, never an event. open_trace_count and open_traces say what was in flight at a lost or recovered moment.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
agentstring""optional exact agent name; omit for every agent in the workspace.
instancestring""optional exact instance id; composes with agent.
limitinteger50max rows (default 50, server max 200).
cursorstring""opaque page token from a previous call’s next-page hint, to fetch the page after it.

When did the planner agent’s copies die today?

{ "name": "agent_lifecycle_events", "arguments": { "agent": "planner" } }

Everything that happened to inst-planner-01 this week.

{ "name": "agent_lifecycle_events", "arguments": { "hours": 168, "instance": "inst-planner-01" } }

agent_traces_summary

Summary KPIs for agent traces over a time window, for the whole workspace or for ONE agent: trace count, LLM calls, error rate, failed vs errored traces, sessions, total/average cost, token usage, and latency and TTFT percentiles. With group_by="bucket" it also answers the same figures per time bucket, the read behind the console’s Drift figure, so “is this agent getting slower or more expensive over the week” is one call.

Scope it with agent to get that agent’s own numbers. This is the same read, with the same arguments, that the Rius console’s agent page makes, so a number you report here and a number a human reads there are the same number — not two measurements that happen to agree.

Read the Failed traces and Errored traces lines as the two different questions they are, and do not add them together or report one as “errors”: a run whose ROOT span errored FAILED, while a run that errored somewhere and then recovered did not. The error rate is errored traces over traces.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
servicestring""optional service-name filter (traces that involve this service).
agentstring""optional exact agent-name filter, matched against the trace’s root span — the same value the root_agent column reports on list_agent_traces, so read a name off a listing rather than guessing one. Agent identity is its own field, not the service name: a run that declares no agent falls back to its service name, so equal root_agent and service are that fallback, not two facts.
instancestring""optional exact agent-instance filter, narrowing to one running copy of agent.
filtersanynulloptional list of {"field": ..., "op": ..., "values": [...]} clauses, ANDed together and composable with the named parameters above — the same grammar and the same field registry as list_agent_traces, so a slice you listed and the summary of that slice cannot disagree. Call describe_search_catalog before guessing a key; a rejected clause comes back naming itself.
group_bystring""optional; "bucket" adds one row per time bucket under the whole-window figures, with the same definitions and composable with every scope argument above. A trace counts once, whole, in the bucket its first span opened in, so the rows sum to the whole-window figures. Rows are sparse: a bucket no trace opened in has NO row, so never read an absent bucket as zero traces, zero cost or a 0% error rate.
bucketstring""optional grain for group_by="bucket": "minute", "hour" or "day". Omit it and the server picks from the window (minute up to 2h, hour up to 48h, day beyond; day buckets open at UTC midnight, so the first may be partial). A grain that cuts the window into more than 1000 buckets is refused with the count in the message.

How did my agents do over the last 24 hours?

{ "name": "agent_traces_summary", "arguments": { "hours": 24 } }

How is the planner agent doing this week?

{ "name": "agent_traces_summary", "arguments": { "hours": 168, "agent": "planner" } }

Is one copy of planner worse than the others?

{ "name": "agent_traces_summary", "arguments": { "agent": "planner", "instance": "inst-planner-01" } }

Summarize the checkout-agent service this week.

{ "name": "agent_traces_summary", "arguments": { "hours": 168, "service": "checkout-agent" } }

What do planner’s gpt-4o runs cost?

{ "name": "agent_traces_summary", "arguments": { "agent": "planner", "filters": [{ "field": "model", "op": "eq", "values": ["gpt-4o"] }] } }

Is planner getting slower or more expensive over the week?

{ "name": "agent_traces_summary", "arguments": { "hours": 168, "agent": "planner", "group_by": "bucket" } }

Summarize traces between two specific dates.

{ "name": "agent_traces_summary", "arguments": { "start": "2026-08-01T00:00:00Z", "end": "2026-08-08T00:00:00Z" } }

agent_versions

The versions ONE agent ran in a time window, on two dimensions that are kept apart and must not be read as synonyms: agent is the agent definition — prompt, tools, policy — as rius.main_agent.version stamps it, and service is the build that ran it, as service.version stamps it. A prompt edit ships without a deploy and a deploy without touching the agent, so the two move independently. Each row carries its traces, failed traces, failed rate and when it was first and last seen within the window.

This is the same read the Rius console’s Agent page draws its Versions figure from, and every row is ROOT-scoped like the registry fields, so a row’s numbers equal agent_traces_summary with filters=[{"field": "agent_version" | "service_version", "op": "eq", "values": [version]}]. Use it to learn which two values to hand compare_agent_versions, or to see when a version appeared. Rows are newest-seen first within a dimension and capped at 50 per dimension; the totals count past the cap.

ArgumentTypeDefaultDescription
agentstringrequiredthe exact agent name (required: versions are per agent). Read a name off list_agents or off root_agent on list_agent_traces rather than guessing one.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
instancestring""optional exact instance id, narrowing to one running copy of agent.

Which versions of planner ran this week?

{ "name": "agent_versions", "arguments": { "agent": "planner", "hours": 168 } }

When did planner’s new prompt version first show up?

{ "name": "agent_versions", "arguments": { "agent": "planner", "hours": 720 } }

compare_agent_versions

Two versions of ONE agent side by side over the same window — traces, failed rate, cost per trace, latency p50, TTFT p50 and tokens per trace — with the change between them, so “did v8 make it worse” is one call.

It is agent_traces_summary twice, each scoped through the registry filter for one version, and the same six rows and delta rules as the Rius console’s compare tiles, so an agent and a human read one change. The change is in percentage points for the failed rate (“+1.0 pp”, never “+50%”) and a percent of the base otherwise; a dash means a side is unknown or the base is zero, never “no change”. Below 20 traces on either side the reply says the differences can be noise; it never claims significance either way.

Refuses, rather than answering, where this deployment’s filter registry does not advertise the version field: an older core would ignore the filter and return the whole agent’s numbers on both sides, which would read as a confident “no change”.

ArgumentTypeDefaultDescription
agentstringrequiredthe exact agent name (required). Read it off list_agents or off root_agent on list_agent_traces.
dimensionstringrequiredwhich version identity to compare — agent (the agent definition, rius.main_agent.version) or service (the build, service.version; build is accepted as a synonym). The two are not interchangeable: read the values off agent_versions, which labels each.
basestringrequiredthe older version’s exact value, as agent_versions lists it.
headstringrequiredthe newer version’s exact value; the change is head against base.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
instancestring""optional exact instance id, narrowing both sides to one running copy of agent.

Did planner’s version 8 make things worse than 7 this week?

{ "name": "compare_agent_versions", "arguments": { "agent": "planner", "dimension": "agent", "base": "7", "head": "8", "hours": 168 } }

Compare the last two builds of planner.

{ "name": "compare_agent_versions", "arguments": { "agent": "planner", "dimension": "service", "base": "2.3.1", "head": "2.4.0" } }

create_alert_channel

Create a place for alerts to be delivered: a webhook, an email list, or Slack.

This provisions a real outbound effect. Once a rule points at this channel, alert content leaves the platform to wherever you named — for a webhook, an HTTP POST to that URL. The payload carries the alert title (which is a span’s error message, so it can contain model output), its labels, counts, and a sample of trace ids.

Needs the channels:manage capability.

ArgumentTypeDefaultDescription
namestringrequireda label for the channel, 1 to 120 characters.
channel_typestringrequiredwebhook, email, or slack.
urlstring""for a webhook — the https URL to POST to.
recipientsanynullfor email — 1 to 20 addresses.
slack_channel_idstring""for Slack — a channel id from the connected Slack workspace. Slack must be connected in the console first.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).
enabledbooleantruewhether it starts receiving deliveries. Defaults to true.

Send my alerts to this webhook.

{ "name": "create_alert_channel", "arguments": { "name": "ops webhook", "channel_type": "webhook", "url": "https://hooks.example.com/rius" } }

create_alert_rule

Create a custom alert rule. Call describe_alert_catalog first.

The rule fires when every threshold in rules holds at once, over the same rolling window, for the traffic left after every filter in filters. There is no OR: for alternatives, create a second rule.

Predefined rules cannot be created — they already exist per workspace. Use update_alert_rule to configure one.

ArgumentTypeDefaultDescription
namestringrequiredwhat to call the rule, 1 to 120 characters.
rulesarrayrequiredthe thresholds, each {"metric":…, "aggregation":…, "operator":…, "value":…}. At least one, at most 10, and each (metric, aggregation) pair only once. Operators: lt, lte, gt, gte, eq.
window_minutesinteger15the rolling window every threshold is measured over, 5 to 1440.
filtersanynulloptional narrowing, each {"field":…, "operator":…, "values":[…]}. ANDed. Omit to watch the whole workspace. eq and ne take exactly one value; in and not_in take one or more. Which operators a field admits is per field — describe_alert_catalog lists them. Values bind verbatim, so pass them exactly as the data spells them: span_kind is the raw OpenInference LLM, not llm, and a lowercased value creates a rule that saves and then never fires.
channel_idsanynullwhere firings are delivered, from list_alert_channels. Supplying this needs the channels:manage capability, because choosing a destination is a destination decision. Omitting it leaves the rule on the region’s default webhook.
enabledbooleantruewhether detection starts immediately. Defaults to true.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Alert me when the checkout agent starts erroring.

{ "name": "create_alert_rule", "arguments": { "name": "checkout errors", "filters": [{"field": "service", "operator": "eq", "values": ["checkout"]}], "rules": [{"metric": "errors", "aggregation": "count", "operator": "gte", "value": 5}] } }

Tell me if p95 cost per trace goes over two dollars.

{ "name": "create_alert_rule", "arguments": { "name": "cost spike", "window_minutes": 60, "rules": [{"metric": "cost", "aggregation": "p95", "operator": "gt", "value": 2.0}] } }

create_api_key

Create a new API key in one of your workspaces. Requires admin access in that workspace. The plaintext key is shown exactly once in the response. It is never retrievable again after this call, so save it immediately.

Not available when this MCP connection is itself authenticated with an API key (headless mode): a leaked agent key must not be able to mint more keys. Mint keys from an interactive (OAuth) session or the console instead.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, workspace name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
namestringglassflow-connect-agenta label for the key, shown in the workspace’s key list later.
scopesanynullkey capabilities: [“ingest”] (default) to send telemetry, add “read” ([“ingest”, “read”] or [“read”]) for a key that can also be used as the Authorization bearer for headless MCP connections. The alert-management capabilities (alerts:manage, channels:manage) are deliberately NOT mintable here — an admin issues those in the console, because a key minted by an agent never expires by default and would be an unbounded credential to leak.

Create an API key so this agent can send traces.

{ "name": "create_api_key", "arguments": { "name": "my-agent" } }

Give it a key that can also read traces over MCP.

{ "name": "create_api_key", "arguments": { "scopes": ["ingest", "read"] } }

delete_alert_channel

Delete a notification channel. Irreversible.

Takes two calls, like delete_alert_rule: once to preview, once with the phrase.

Any rule still pointing at this channel loses that destination silently and falls back to the region’s default webhook — it does not start failing loudly. Consider update_alert_channel with enabled false instead, which is reversible.

Needs the channels:manage capability.

ArgumentTypeDefaultDescription
channel_idstringrequiredthe channel’s id, from list_alert_channels.
confirmstring""the phrase from the first call’s output.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Remove the old ops webhook.

{ "name": "delete_alert_channel", "arguments": { "channel_id": "8a1…" } }

delete_alert_rule

Delete a custom alert rule AND its entire firing history. Irreversible.

Takes two calls. Call it without confirm to see what would be destroyed and get the phrase to pass back; call it again with that phrase to go ahead.

Prefer update_alert_rule with enabled false: that stops detection and keeps the history, and can be undone. Predefined rules cannot be deleted at all.

ArgumentTypeDefaultDescription
refstringrequiredthe custom rule’s uuid, from list_alert_rules.
confirmstring""the phrase from the first call’s output.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Delete the cost spike alert.

{ "name": "delete_alert_rule", "arguments": { "ref": "9c2…" } }

describe_alert_catalog

Describe what you can alert on: the fields, metrics and limits for a custom rule.

Read this before calling create_alert_rule. It returns the filter fields, the metrics with the aggregations each one actually supports, the comparison operators, and the allowed window — plus the constraints the catalog itself does not advertise.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).
fieldstring""optionally a filter field id (for example “service”), to list the values actually seen in this workspace over the last 24h.

What can I alert on?

{ "name": "describe_alert_catalog", "arguments": {} }

Which services could I filter an alert to?

{ "name": "describe_alert_catalog", "arguments": { "field": "service" } }

describe_search_catalog

Describe what you can filter traces and spans on, before you guess a key.

Returns the filter grammar — every field, its type, the operators it admits, and what a filter on it means for a TRACE — merged with the keys this workspace has actually produced. Read it before composing filters for list_agent_traces or list_spans; a guessed key is a rejected call.

Cost model, in the order worth trying: promoted columns (source: column) are cheap over any window; attr.<key> and resource.<key> reach the customer’s own attributes, cost roughly 10x more, and are accepted only over windows of 31 days or less — so narrow with a column first, then add one.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name (defaults to your default).
fieldstring""optionally a key, to list the values seen in this workspace. Accepts either spelling — “tool.name” or “attr.tool.name”.
prefixstring""optionally narrow the key list, e.g. “tool.” to find a customer’s own tool attributes.
hoursinteger24lookback for the key and value lists (default 24).

What can I filter traces on?

{ "name": "describe_search_catalog", "arguments": {} }

What tool attributes does this workspace set?

{ "name": "describe_search_catalog", "arguments": { "prefix": "tool." } }

Which models could I filter to?

{ "name": "describe_search_catalog", "arguments": { "field": "model" } }

get_agent_trace

Get one agent trace’s span waterfall (spans in time order, indented by depth).

The header names the root span’s agent and each row carries its own, so a multi-agent run shows which agent owned which span; pass either name back to list_agent_traces or list_spans as agent to see that agent’s other work. The header also names who sent the trace — the sending ingest key’s own email, which a console-made key usually carries too (it falls back to its creator’s own email). Blank only when the key could not be resolved or the trace predates attribution.

The header also names the root span’s session; pass it to list_spans(session_id=...) for the rest of that conversation. A session equal to the trace id means the run carried no session of its own. A trace whose spans carry more than one session gets a per-span session column.

Captured content is subject to the workspace’s privacy controls: spans exported with capture_content=False or a mask have nothing extra to show.

ArgumentTypeDefaultDescription
trace_idstringrequiredthe trace id (from list_agent_traces).
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
include_contentbooleanfalsewhen true, also return each span’s captured content: LLM input/output messages, agent/tool input/output values, status messages and events. Off by default because full message content can be very large; pass true when you need to see what an LLM, agent, or tool span actually said, received, or returned (e.g. to inspect prompts, completions, or tool I/O).

Break down trace 4bf92f3577b34da6a3ce929d0e0e4736 for me.

{ "name": "get_agent_trace", "arguments": { "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" } }

What did the LLM actually say in that failed span?

{ "name": "get_agent_trace", "arguments": { "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "include_content": true } }

get_alert

Read one fired alert in full, with its root-cause finding when one exists.

Use this after list_alerts to understand a single alert: its labels, the sample trace ids behind it, and — if root-cause analysis ran for it — the investigation’s written finding.

ArgumentTypeDefaultDescription
alert_idstringrequiredthe alert’s id, from list_alerts.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Why did that alert fire?

{ "name": "get_alert", "arguments": { "alert_id": "2f9c…" } }

get_me

Get your own identity and access context.

Returns your user (id, external id, email), every organization you belong to with your role in each (“admin” or “member”), and the workspaces you can access — an interactive (OAuth) connection spans every one of those orgs, so workspaces are grouped by org when you belong to more than one. If you have not yet joined an organization (for example, a pending invite that has not been accepted), the organizations are reported as “none”. On a connection authenticated with an API key rather than a login, only the one workspace the key is bound to is reported — a key has no user or organization of its own.

No arguments.

Who am I in Rius?

{ "name": "get_me", "arguments": {} }

list_agent_traces

List recent agent traces (one row per trace) newest-first, as a Markdown table.

The trace_id column feeds get_agent_trace. When more traces match than limit, the reply carries a next-page cursor: pass it back as cursor to fetch the next page, rather than raising limit past what a chat can usefully display.

The session column is the ROOT span’s session id; pass it to list_spans(session_id=...) to see every span of that conversation across the traces it touched. A span with no session of its own is stamped with its trace id, so a session equal to the row’s trace_id means “no session”, not a one-trace conversation. Blank where this deployment does not report it yet.

The sent_by column names the developer whose ingest key sent the trace (their stable email — a console-made key falls back to its creator’s own email, so it usually carries one too). Blank only when the key could not be resolved (unknown, another workspace’s, or a failed lookup), or the trace predates attribution.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound; overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
servicestring""optional service-name filter (traces that involve this service).
statusstring""optional trace status filter, “Ok”, “Error”, or “Incomplete”. Note a trace reads Error when ANY of its spans errored, so a run that retried a failing step and then succeeded is in here too — read root_status to tell those apart.
root_statusstring""optional filter on the ROOT span’s own verdict, “Ok”, “Error”, or “Incomplete”. Composes with status rather than replacing it: status=“Error” with root_status=“Ok” is the recovered slice (children errored, the run itself finished clean), and root_status=“Error” alone is the genuine failures. A trace whose root_status column is blank matches neither — the server made no claim about its root.
agentstring""optional exact agent-name filter, matched against the trace’s root span — the same value the root_agent column reports, so read a name off a listing rather than guessing one, and pass it back to get every other run of that agent. Agent identity is its own field, not the service name: a run that declares no agent falls back to its service name, so equal root_agent and service columns are that fallback, not two facts.
instancestring""optional exact agent-instance filter, narrowing to one running copy of agent.
user_idstring""optional end-user scope — the exact id, as the user_id column reports it. The END USER is the person your agents served (the user.id your SDK stamps), not a console login. Matched against ANY span of the trace, so a run counts if the user scope was open anywhere inside it. The column, though, is the ROOT span’s user, so the two need not agree: a trace whose scope opened after its root matches the filter and still shows a BLANK cell. That gap is the any-span rule working as specified, not a filter that missed — read the trace’s spans to see where the scope opened.
anonymousbooleanfalselist the traffic carrying NO end user on any span, instead of one user’s. A real subject rather than an error case: it is where un-instrumented traffic goes, and its error rate is worth knowing. The console’s ?user=anonymous. Pass either user_id or anonymous, never both — they are disjoint by construction.
filtersanynulloptional list of {"field": ..., "op": ..., "values": [...]} clauses, ANDed together and composable with the named parameters above. Cheapest first: status, agent, service, model, span_kind, operation, session_id are promoted columns and cost the same over any window. attr.<key> and resource.<key> reach a customer’s own attributes and are ~10x dearer, so narrow with a column first; they are accepted only over windows of 31 days or less. Ops: eq, ne, in, not_in, gt, gte, lt, lte, exists, not_exists. Substring on an attribute value is refused — use error_text or search instead. Call describe_search_catalog before guessing a key; a rejected clause comes back naming itself.
searchstring""optional case-insensitive contains match on span name, span id, trace id, or session id. A session id alone — e.g. a coding-agent session’s — finds every trace of that session in one call; on a core that predates session-id search it matches nothing, so fall back to filters=[{"field": "session_id", "op": "eq", "values": [...]}].
error_textstring""optional free text over the failure itself — the status message and any recorded exception. This is how you find a failure by what it said (“rate limit”, “connection reset”) rather than by where it was.
limitinteger20max rows (default 20).
cursorstring""opaque page token from a previous call’s next-page cursor, to fetch the page after it.

Why did checkout-agent start failing at 14:00?

{ "name": "list_agent_traces", "arguments": { "agent": "checkout-agent", "status": "Error", "root_status": "Error", "start": "2026-09-16T14:00:00Z", "end": "2026-09-16T15:00:00Z", "error_text": "rate limit" } }

Failed runs that used gpt-4o and called the send_email tool.

{ "name": "list_agent_traces", "arguments": { "status": "Error", "filters": [ {"field": "model", "op": "eq", "values": ["gpt-4o"]}, {"field": "attr.tool.name", "op": "eq", "values": ["send_email"]} ] } }

Show me the failed runs from the last two days.

{ "name": "list_agent_traces", "arguments": { "hours": 48, "status": "Error" } }

Which runs actually failed, ignoring the ones that retried and recovered?

{ "name": "list_agent_traces", "arguments": { "hours": 48, "root_status": "Error" } }

Show me the runs that hit errors but finished cleanly anyway.

{ "name": "list_agent_traces", "arguments": { "hours": 48, "status": "Error", "root_status": "Ok" } }

checkout-agent’s traces between two dates.

{ "name": "list_agent_traces", "arguments": { "agent": "checkout-agent", "start": "2026-08-01T00:00:00Z", "end": "2026-08-08T00:00:00Z" } }

list_agents

List a workspace’s agent instances with their live status — which agents exist, how many copies of each are running, and which copies are stale, gone or stopped. One row per instance, straight from the heartbeat store.

This is the same read the Rius console’s Agents page makes, with the server’s own status words: running, ready, stale, gone, stopped. The status is computed on the server from the last heartbeat; do not re-derive it from last_seen_at. open_trace_count is the true number of open traces and the running/ready signal; first_seen_at and stopped_at appear when the core serves them, and a blank first_seen_at means the start is unknown, not that it started now.

Every row here is a live instance; a trace-only agent (one that sends traces but no heartbeat) does not appear. If an agent you expect is missing, the reply says why that happens.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
agentstring""optional exact agent name, to list only that agent’s instances. The server has no filter for it, so this narrows the reply here and names the agents that do have instances when nothing matches.

Which of my agents are running right now?

{ "name": "list_agents", "arguments": {} }

Are any copies of planner lost?

{ "name": "list_agents", "arguments": { "agent": "planner" } }

list_alert_channels

List where this workspace’s alerts can be delivered.

Use it to find a channel id for create_alert_rule or update_alert_rule. Needs the channels:manage capability rather than plain read, because the target column shows the actual destination — a webhook URL, an email recipient list, a Slack channel.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Where do my alerts go?

{ "name": "list_alert_channels", "arguments": {} }

list_alert_rules

List every alert rule in the workspace — predefined and custom together.

Predefined rules are the built-in detectors, one per kind, which you can configure and toggle but not create or delete. Custom rules are ones someone built from the metric catalog; there can be many.

The ref column is what update_alert_rule and delete_alert_rule take: a kind name for a predefined rule, a uuid for a custom one.

A predefined rule only appears once alert-manager has reached this workspace, so an empty list can simply mean detection has not started yet.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

What alerts are configured?

{ "name": "list_alert_rules", "arguments": {} }

list_alerts

List alerts that have fired, newest first.

This is the “what is broken” tool. An alert is opened by a detector and stays open, accumulating occurrences, until the detector resolves it — so an open alert with a recent last_seen is still happening.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).
statusstring""open or resolved; omit for both.
kindstring""narrow to one detector — consistent_error_pattern, silent_failure, tool_loop, or custom. Every custom rule shares the kind “custom”, so use rule_id to isolate one custom rule.
rule_idstring""narrow to the firings of one specific rule (from list_alert_rules).
servicestring""exact service name.
stepstring""exact step (span) name.
searchstring""case-insensitive match on the alert title.
acknowledgedstring""true or false; omit for both.
hoursinteger24how far back to look, on last_seen. Defaults to 24. The server itself is unbounded if no window is given, which would scan all history.
limitinteger50rows to return, at most 200.

What alerts are open right now?

{ "name": "list_alerts", "arguments": { "status": "open" } }

Show me the errors alert for the checkout service this week.

{ "name": "list_alerts", "arguments": { "service": "checkout", "hours": 168 } }

list_metrics_catalog

List every metric the platform knows how to compute, with its unit, nullability, which read serves it, and its companions (the extra response keys it contributes: coverage keys for scalars, row/point value keys for breakdowns and series). Use it to discover exact field names instead of guessing them.

ArgumentTypeDefaultDescription
workspacestring""optional workspace name or id (the catalog is identical for every caller; this only fills the request path).
groupstring""optional group filter, e.g. “cost”, “volume”, “tokens”, “latency”, “ttft”, “reliability”.
kindstring""optional kind filter: “scalar”, “series”, or “breakdown”.

What latency metrics exist?

{ "name": "list_metrics_catalog", "arguments": { "group": "latency" } }

list_spans

List spans across every trace in the workspace (not grouped by trace), as a Markdown table — the cross-trace complement to get_agent_trace’s single-trace waterfall. Use it to find spans by kind/session/agent regardless of which trace they landed in, e.g. “every failed tool call this week” or “this session’s spans across however many traces it touched”.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound; overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
kindstring""optional derived semantic span kind: “llm”, “tool”, “chain”, “retriever”, “agent”, “embedding”, or “other”. Distinct from each row’s own kind column, which is the raw OTLP span kind (SERVER/CLIENT/INTERNAL/…).
statusstring""optional span status filter, “Ok”, “Error”, or “Incomplete”.
session_idstring""optional exact match on the span’s session id, across every trace in that session. Read one off the session column (reported here, on list_agent_traces and by get_agent_trace) rather than guessing. A span with no session of its own reports its trace id there, so passing a trace id selects that one trace’s session-less spans.
agentstring""optional exact agent-name filter — the span’s own agent, not a trace-level rollup. Reported back in the agent column, so a listing names the agents it can filter by; a span whose run declared no agent carries its service name there instead.
instancestring""optional exact agent-instance filter, narrowing to one running copy of agent.
user_idstring""optional end-user scope — the exact id, as the user_id column reports it. Here the column is the SPAN’s own end user rather than a trace-level rollup, so every row of a scoped listing shows the id it matched on. (On list_agent_traces the same column name is the ROOT span’s, which is why a trace row there can match and still read blank. When that happens, this tool is how you find the spans that did carry the user.)
anonymousbooleanfalselist the spans carrying no end user instead of one user’s. Pass either user_id or anonymous, never both.
searchstring""optional case-insensitive contains match on span name, span id, trace id, or session id.
error_textstring""optional free text over the failure itself — the status message and any recorded exception. Finds a failing span by what it said.
filtersanynulloptional list of {"field": ..., "op": ..., "values": [...]} clauses, ANDed and composable with the named parameters. Promoted columns (status, agent, service, model, span_kind, operation, session_id) are cheap over any window; attr.<key> and resource.<key> reach a customer’s own attributes, cost ~10x more, and are accepted only over 31 days or less — narrow with a column first. Ops: eq, ne, in, not_in, gt, gte, lt, lte, exists, not_exists. Call describe_search_catalog before guessing a key.
sort_fieldstring""optional sort column: “start_time” (default), “duration_ms”, “tokens”, or “cost”.
sort_dirstring""optional sort direction, “asc” or “desc” (default “desc”).
limitinteger50max rows (default 50).
cursorstring""opaque page token from a previous call’s next-page cursor, to fetch the page after it.

Show me every errored tool call in the last day.

{ "name": "list_spans", "arguments": { "kind": "tool", "status": "Error" } }

All spans in session user-42-chat-7.

{ "name": "list_spans", "arguments": { "session_id": "user-42-chat-7" } }

list_users

The window’s END USERS as a ranked register: who your agents served.

The end user is the person on the other side of the agent — the user.id your SDK stamps — not a console login and not an org member. The words are worth keeping straight: an ORG is the Rius customer, a WORKSPACE is one of their own clients, and an end user is that client’s user.

Read a user_id off this register and pass it to user_activity_summary for that person’s KPIs, or to list_agent_traces(user_id=...) for their runs. This is the same read the console’s Users page makes.

TOP-N by design, not by accident: a B2C workspace can hold millions of end users, so the server ranks and caps. When it reports more, q reaches PAST the cap by exact id — it is an equality probe, never a substring search, so a fragment finds nothing rather than scanning millions of ids.

Three figures that are easy to misread, so each travels with its caveat: anonymous traffic is always reported and is a real subject rather than an error case; coverage is counted in TRACES because one trace can belong to two end users under the any-span rule; and a null cost means nothing in the window was priced, which is not the same as free.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given. The register is an unindexed group-by, so the window is capped at 31 days and a wider one is refused.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
sortstringtraces”traces” (default), “failed_traces”, or “cost” — all descending. A value outside that set is refused rather than quietly defaulted, since a wrong ranking under a right-looking header cannot be caught later.
limitinteger20users per page (default 20, server max 100).
qstring""an EXACT end-user id. Returns that user’s row even when they fall outside the top-N, or an empty register when the window holds nothing for them.

Who are my busiest end users this week?

{ "name": "list_users", "arguments": { "hours": 168 } }

Which end users are seeing the most failures?

{ "name": "list_users", "arguments": { "hours": 168, "sort": "failed_traces" } }

Is u_8f2 in the last 30 days at all?

{ "name": "list_users", "arguments": { "hours": 720, "q": "u_8f2" } }

list_workspaces

List the workspaces you have access to (id and name).

On an interactive (OAuth) login this spans every organization you belong to, grouped under each org’s name; an API-key connection sees the single workspace its key is bound to.

Use it to find the right value for the workspace argument of the trace, metrics and alert tools. That argument takes a workspace id, a workspace name, or — when the same name occurs in two of your orgs — the org-qualified org-name/workspace-name form.

No arguments.

Which Rius workspaces do I have?

{ "name": "list_workspaces", "arguments": {} }

update_alert_channel

Change a notification channel: rename it, re-point it, or enable/disable it.

Only what you pass changes; a channel’s secrets are left alone if you do not resubmit them. A channel’s type cannot be changed — create a new one instead.

A channel that has failed to deliver several times in a row is disabled automatically; pass enabled true to bring it back once you have fixed it.

Needs the channels:manage capability.

ArgumentTypeDefaultDescription
channel_idstringrequiredthe channel’s id, from list_alert_channels.
namestring""a new label.
urlstring""for a webhook — a new https URL to POST to.
recipientsanynullfor email — the full replacement list of addresses.
enabledanynullturn delivery on or off.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Disable the ops webhook for now.

{ "name": "update_alert_channel", "arguments": { "channel_id": "8a1…", "enabled": false } }

update_alert_rule

Reconfigure or toggle one alert rule, predefined or custom.

ref decides which: a kind name (consistent_error_pattern, silent_failure, tool_loop) addresses the predefined rule of that kind; a uuid addresses a custom rule. Get either from list_alert_rules.

Only what you pass changes. Turning a rule off stops detection, not just notification — gaps in history are permanent and nothing backfills them.

The two rule shapes take DIFFERENT settings, and mixing them is refused with a message naming the right one:

  • a predefined rule has named integer knobs -> pass config
  • a custom rule has metric thresholds -> pass rules (+ window_minutes)
ArgumentTypeDefaultDescription
refstringrequiredthe rule’s kind or uuid.
enabledanynullturn detection on or off.
rca_enabledanynullturn root-cause analysis on or off for this rule.
namestring""rename a custom rule (predefined rules take their name from their kind).
configanynullfor a PREDEFINED rule only — its named knobs, e.g. {"min_errored_spans": 10}. consistent_error_pattern takes window_minutes, min_errored_spans, min_distinct_traces; silent_failure takes window_minutes; tool_loop takes window_minutes, min_identical_calls. Call describe_alert_catalog for the bounds.
rulesanynullfor a CUSTOM rule only — replace its thresholds. Replaces the whole list, so pass window_minutes with it.
window_minutesinteger0the window. For a custom rule it is part of the replaced config, so pass rules too; for a predefined rule put it in config.
filtersanynullfor a CUSTOM rule only — replace its filters. Replaces the whole list. Same shape and the same verbatim-value rule as create_alert_rule.
channel_idsanynullchange where the rule delivers. Needs channels:manage. An empty list does NOT silence the rule — it re-points it at the region’s default webhook. To stop notifications, set enabled to false.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default).

Turn off the tool loop alert.

{ "name": "update_alert_rule", "arguments": { "ref": "tool_loop", "enabled": false } }

Make the error pattern alert less noisy — 10 errors, not 3.

{ "name": "update_alert_rule", "arguments": { "ref": "consistent_error_pattern", "config": { "min_errored_spans": 10 } } }

user_activity_summary

Summary KPIs for ONE end user’s activity over a time window: trace count, LLM calls, error rate, failed vs errored traces, sessions, total/average cost, token usage, and latency and TTFT percentiles.

An “end user” here is the person your agents serve — the user.id your SDK stamps via rius.user(...) / withUser(...) — not a Rius account. Use it when someone arrives with a complaint and an identifier: “what did user u_8f2 experience this week” is one call, and the answer is a rollup rather than a trace list you have to fold yourself.

Same read, same window and the same figures the Rius console’s user page shows for that id, so a number you report and a number a human reads there are the same number. Field names match agent_traces_summary wherever they mean the same thing.

Read the Failed traces and Errored traces lines as the two different questions they are, and do not add them together or report one as “errors”: a run whose ROOT span errored FAILED, while a run that errored somewhere and then recovered did not.

ArgumentTypeDefaultDescription
user_idstring""the end user’s exact id, as list_agent_traces reports it in the user_id column — read one off a listing rather than guessing. Matched against any span of the trace, so a trace counts for this user if the user scope was open anywhere inside it, not only at the root.
anonymousbooleanfalsesummarise the traffic that carries NO end user instead. This is a real subject, not an error case: it answers “what is happening to the runs nobody attributed”, and a high error rate there is worth knowing. It is the console’s ?user=anonymous. Pass either user_id or anonymous, not both.
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursinteger24lookback window in hours (default 24), used for whichever of start/end is not given.
startstring""optional absolute RFC3339 lower bound (e.g. “2026-08-01T00:00:00Z”); overrides the hours-derived value when given.
endstring""optional absolute RFC3339 upper bound; overrides the hours-derived value when given.
filtersanynulloptional further {"field": ..., "op": ..., "values": [...]} clauses, ANDed with the user scope — the same grammar and registry as list_agent_traces. Call describe_search_catalog before guessing a key.

What did user u_8f2 experience in the last 24 hours?

{ "name": "user_activity_summary", "arguments": { "user_id": "u_8f2" } }

How has that user’s week been?

{ "name": "user_activity_summary", "arguments": { "user_id": "u_8f2", "hours": 168 } }

How much of our traffic has no user attached, and is it failing?

{ "name": "user_activity_summary", "arguments": { "anonymous": true } }

What did that user’s gpt-4o runs cost?

{ "name": "user_activity_summary", "arguments": { "user_id": "u_8f2", "filters": [{ "field": "model", "op": "eq", "values": ["gpt-4o"] }] } }

workspace_metrics_overview

Aggregated health of a whole workspace over a time window: the numbers behind the dashboard’s overview: volume (traces/spans/LLM calls), cost, tokens, latency percentiles, TTFT, error rates, each with its previous-window baseline and delta, plus ranked breakdowns (per model, top agents, calls by kind, top exceptions, slowest spans).

Use this to answer “how is my workspace doing” before drilling into individual traces with list_agent_traces / get_agent_trace.

Values are milliseconds for latency/TTFT; — means not measured (null), which is never the same as a measured 0. Metrics listed as degraded failed to compute and are absent rather than zero.

ArgumentTypeDefaultDescription
workspacestring""optional workspace id, name, or org-name/workspace-name when the same name occurs in two of your orgs (defaults to your default; use list_workspaces to discover them).
hoursnumber24lookback window in hours (default 24). Bucket grain is server-decided from the window length: ≤2h → minute, ≤48h → hour, else day. minute and hour buckets are window-relative (bucket k starts at from + k×step); day buckets are UTC calendar days, so the first and last cover only the part of their day inside the window and a low value there is that clip, not a drop. The rendered series states which of its edges are clipped.
minutesinteger0lookback in minutes instead of hours, for short “last 10 minutes” windows (ignored when 0).
breakdownsbooleantrueinclude the ranked per-model / per-agent / per-kind tables (default true).
seriesbooleanfalseinclude the per-bucket sparkline values (default false; they are verbose).

How is my workspace doing today?

{ "name": "workspace_metrics_overview", "arguments": {} }

Anything wrong in the last 10 minutes?

{ "name": "workspace_metrics_overview", "arguments": { "minutes": 10 } }

Next steps

Last updated on