Agent Trajectory Monitor
Alert on repeated tool calls, call counts, and step order with Monitors as Code.
Overview
Agent trajectory monitors check how often an agent's steps (spans) occur and how those steps relate. They can alert when a step happens too often or too rarely, a tool repeats consecutive calls with matching input and output, or steps occur in an unexpected order or combination. Unlike metric and evaluation monitors, they do not use alert_conditions; the rule belongs in a single agent_span_alert_condition, evaluated over a time_filter window.
Reference scopeThis page covers MaC YAML configuration. For how trajectory monitoring works, see Agent Trajectory Monitors.
MaC key: agent_trajectory. By default, conditions are checked within each agent run, also called a trace. Repeat and relationship conditions require this default TRACE scope. trajectory_scope: CONVERSATION supports only occurs conditions, including the negated "does not occur" form. Select a workflow, task, or span in the alert condition, not in agent_span_filters.
Author by export. Theagent_span_alert_conditiontree is intricate. The most reliable way to get its exact shape is to build the monitor in the Monte Carlo UI and export it withmontecarlo monitors export, then manage the exported YAML.
Quick Start
montecarlo:
agent_trajectory:
- name: retrieval_workflow_occurs
description: Alert when the retrieval workflow runs more than once
agent: my-otel-agent # the agent's service_name
agent_span_alert_condition:
operator: OR
conditions:
- type: SPAN_OCCURRENCE
span_field:
workflow:
literal: retrieval
predicate:
name: occurs
comparison_operator: MORE_THAN
count: 1
time_filter:
time_field:
field: ingest_ts
lookback_in_hrs: 1
schedule:
type: fixed
interval_minutes: 60
start_time: "2025-01-01T00:00:00+00:00"
domains:
- my-domainConfiguration
string · required
The agent whose spans the monitor reads. Agent monitors name an agent instead of a table; the warehouse source is derived from it. The value takes one of two forms, told apart by its shape:
- Warehouse platform agents (e.g. Snowflake Cortex, Databricks) — a
<database>:<schema>.<name>reference, where<name>is the agent's display name when it has one (otherwise its underlying identifier). Notrace_table. - OpenTelemetry agents — the agent's bare
service_name. By default the OpenTelemetry trace store is resolved automatically; settrace_tableonly when the spans live in a specific warehouse table.
agent: my-otel-agentstring · optional
<database>:<schema>.<table> naming the warehouse trace table that holds an OpenTelemetry agent's spans. Required when the spans live in your warehouse, or when the warehouse holds more than one OpenTelemetry trace table. Omit it for platform agents and for agents resolved from the default OpenTelemetry trace store.
trace_table: "ingest:opentelemetry.traces"object · required
Defines what to alert on. Set operator: OR to alert when any condition matches; AND is not supported. Each condition is one of:
SPAN_OCCURRENCE— counts calls usingpredicate.name: occurs, or the longest consecutive sequence of matching tool calls usingpredicate.name: repeats. Fields:span_field,predicate,comparison_operator,count.SPAN_RELATION— a span relates to one other span (related_span_fields, with exactly one entry).
span_field targets a span by workflow, task, and/or span_name (each a literal), following the workflow → task → span_name hierarchy.
| Predicate | Supported comparisons and minimum counts |
|---|---|
occurs | MORE_THAN and EXACTLY: count >= 0; LESS_THAN: count >= 1. |
repeats | MORE_THAN: count >= 1; EXACTLY: count >= 2. No LESS_THAN, negation, or related_span_fields. |
For repeats, MORE_THAN with count: 2 matches three or more consecutive calls. EXACTLY with count: 3 matches only when the longest matching sequence in the run has three calls; a longer sequence does not match. The first call counts toward the total.
agent_span_alert_condition:
operator: OR
conditions:
- type: SPAN_OCCURRENCE
span_field:
workflow:
literal: retrieval
predicate:
name: occurs
comparison_operator: MORE_THAN
count: 1object · required
The lookback window the condition is evaluated over. time_field must be the ingest_ts field; lookback_in_hrs must be at least 1. With a fixed schedule, the lookback must not exceed the schedule interval. The examples below check one hour of data once an hour.
time_filter:
time_field:
field: ingest_ts
lookback_in_hrs: 1object · optional
A predicate tree (FilterGroup) that further restricts which spans are considered, beyond the agent and the alert condition.
For repeats, a tool call excluded by filters cannot match but still breaks the sequence. This differs from agent_span_filters, which removes excluded calls before repeat counting.
array of objects · optional
For trajectory monitors only the agent dimension is meaningful here; span-level refinements (workflow/task/span_name) are rejected — express those in agent_span_alert_condition instead. The agent is already set by agent, so this is rarely needed.
object · required
type (fixed or manual), interval_minutes, start_time, timezone. Dynamic schedules are not supported for trajectory monitors.
schedule:
type: fixed
interval_minutes: 60
start_time: "2025-01-01T00:00:00+00:00"boolean · optional
Force auto-apply tuning on (true) or off (false) for this monitor, overriding the account or domain default. Omit to inherit. See Bayes monitor tuning.
auto_tuning: falseThe shared rule-monitor envelope:
namestring· optional — unique identifier (auto-generated if omitted); renaming creates a new monitor.descriptionstring· optional — max 512 characters.warehousestring· optional — UUID or name; overrides themontecarlo.ymldefault.connection_namestring· optional — query engine to use within the warehouse.timeoutinteger· optional — query timeout in seconds.notesstring· optional — shown in the UI, not in notifications.audiencesarray of strings or mappings· optional — notification channels. An entry can narrow an audience to specific triage priorities; see Routing alerts by triage priority.failure_audiencesarray of strings· optional — notification channels for run failures.priorityenum· optional —P1–P5.event_rollup_countinteger· optional — minimum 2; roll up repeated breaches into one incident.tagsarray of objects· optional —name(required) +value(optional).data_quality_dimensionenum· optional —ACCURACY·COMPLETENESS·CONSISTENCY·TIMELINESS·UNIQUENESS·VALIDITY.domainsarray of strings (exactly one entry)· required when creating a monitor — required on all accounts, regardless of when the account was created.
boolean · optional
Force auto-triage on (true) or off (false) for this monitor, overriding the account or domain default. Omit to inherit. See Bayes triage.
auto_triage: falseDeprecated fields
| Field | Use instead |
|---|---|
resource | warehouse |
domain_uuids | domains |
labels | audiences |
Examples
Repeated tool calls
This example alerts when lookup_order makes three or more consecutive calls with matching input and output in one run. Replace the agent, domain, workflow, task, and span names with values from your account. The workflow and task identify where the tool appears in the span tree; include both when selecting span_name.
montecarlo:
agent_trajectory:
- name: repeated_order_lookup
description: Alert when lookup_order repeats three or more times
agent: support-agent
auto_tuning: false
agent_span_alert_condition:
operator: OR
conditions:
- type: SPAN_OCCURRENCE
span_field:
workflow:
literal: support
task:
literal: order_status
span_name:
literal: lookup_order
predicate:
name: repeats
comparison_operator: MORE_THAN
count: 2
time_filter:
time_field:
field: ingest_ts
lookback_in_hrs: 1
schedule:
type: fixed
interval_minutes: 60
start_time: "2026-01-01T00:00:00+00:00"
domains:
- my-domainTo match a longest sequence of exactly three calls instead, change only:
comparison_operator: EXACTLY
count: 3Repeat detection supports Snowflake, including Cortex agents; Databricks, including Genie; and ClickHouse. Use the agent and optional trace_table formats described above for your source. For example, a native platform agent uses a <database>:<schema>.<name> reference, while an OpenTelemetry agent uses its service_name.
Another tool call or a change in input or output breaks the sequence. Reasoning and planning steps do not. Missing, redacted, cut-off, or oversized input/output values are excluded and break the sequence; the combined input and output limit is 16,384 characters. Intentional polling can match, so choose the tool and threshold based on its expected behavior. See Agent Trajectory Monitors for matching rules and source-specific limits.
The example explicitly disables automatic tuning. Keep repeat thresholds under manual control while repeat-aware tuning is unavailable.
OpenTelemetry agent — workflow occurrence
Alert when the retrieval workflow span occurs more than once in the last hour.
montecarlo:
agent_trajectory:
- name: retrieval_workflow_occurs
description: Alert when the retrieval workflow runs more than once
agent: my-otel-agent
agent_span_alert_condition:
operator: OR
conditions:
- type: SPAN_OCCURRENCE
span_field:
workflow:
literal: retrieval
predicate:
name: occurs
comparison_operator: MORE_THAN
count: 1
time_filter:
time_field:
field: ingest_ts
lookback_in_hrs: 1
schedule:
type: fixed
interval_minutes: 60
start_time: "2025-01-01T00:00:00+00:00"
domains:
- my-domainPlatform agent — trajectory on a Snowflake/Databricks agent
The same monitor against a warehouse platform agent, referenced by its <database>:<schema>.<name> identity (no trace_table).
montecarlo:
agent_trajectory:
- name: cortex_tool_call_frequency
description: Alert when the tool is called more than 10 times
agent: "ANALYTICS:AGENTS.support_cortex_agent"
agent_span_alert_condition:
operator: OR
conditions:
- type: SPAN_OCCURRENCE
span_field:
workflow:
literal: support
task:
literal: call_tool
predicate:
name: occurs
comparison_operator: MORE_THAN
count: 10
time_filter:
time_field:
field: ingest_ts
lookback_in_hrs: 1
schedule:
type: fixed
interval_minutes: 60
start_time: "2025-01-01T00:00:00+00:00"
domains:
- my-domainTroubleshooting
Agent source
- Omitting
agent. Every agent monitor requires anagent. A monitor without one fails validation. - Platform reference not found / ambiguous. A
<database>:<schema>.<name>reference must match exactly one registered agent in the target account and warehouse. A display name shared by two agents in a schema is ambiguous — use the underlying endpoint identity. Cross-account: register the agent first. - Setting
trace_tablefor a default-store agent. Redundant and rejected when the OpenTelemetry trace store resolves automatically. Omit it.
Trajectory specifics
- Using
alert_conditions. Trajectory monitors have noalert_conditionsfield — the logic goes inagent_span_alert_condition. - Span-level
agent_span_filters.workflow/task/span_namerefinements are rejected here; express them insideagent_span_alert_condition. time_filterfield other thaningest_ts. Thetime_fieldmust beingest_ts, andlookback_in_hrsmust be at least 1.- A dynamic schedule. Trajectory monitors don't support
schedule.type: dynamic. - Span-field hierarchy. When targeting a
span_name, itstaskandworkflowmust also be set; when targeting atask, itsworkflowmust be set. - An invalid repeat comparison. Use
MORE_THANwith a count of at least 1 orEXACTLYwith a count of at least 2. Repeats cannot be negated or used as a relation condition. - A repeat rule never matches. Confirm that the selected workflow or task contains tool calls, or that an individually selected span is a tool call. For each tool call, both input and output must be captured completely. Calls above the combined 16,384-character limit cannot match. A tool that changes its input or output on each call will not match either.
- Conversation scope with repeats or relationships. Omit
trajectory_scopeor useTRACE.CONVERSATIONsupports onlyoccursconditions, including the negated "does not occur" form. - A time window larger than the schedule interval. Shorten
lookback_in_hrsor increaseinterval_minutesso the fixed schedule interval covers the whole lookback.
Details and edge cases
How do filters and agent_span_filters affect repeats?
Calls excluded by the agent selection, agent_span_filters, or the time window are removed before repeat counting. The top-level filters key determines which of the remaining tool calls can match; a tool call excluded by filters still breaks the sequence. For example, lookup_order → send_email → lookup_order has no consecutive repeat of lookup_order when filters excludes send_email. The alert condition's span_field selects the workflow, task, or tool to check; it does not remove other tool calls as sequence breakers.
What do the sample rows and NULL counts mean?
Each sampled matching run appears once, even if it matches several conditions. Repeat-count columns identify the selected workflows, tasks, or spans. If a repeat-count cell shows NULL, that repeat condition did not match but another condition in the OR group did. NULL does not mean a repeat count of zero. A preview sample is not the total number of matching runs or a measure of alert frequency.
What limits apply to repeat queries?
Query work grows with the number of calls and the size of their input and output. ClickHouse repeat queries have a 512 MiB memory limit; large runs, long time windows, or multiple repeat conditions can exceed it. Use the tool and window you need, and check the monitor's results before widening its coverage. Custom ClickHouse read-only profiles must allow the query settings max_block_size, max_threads, and max_memory_usage; see the UI guide for details.
Updated 1 day ago
