- Score the behaviors that hurt in production. Online evaluators run judge criteria (faithfulness, tool accuracy, goal completion) against sampled live traces and whole sessions; patterns catch the deterministic failures (errors, empty responses, PII, latency) at zero LLM cost.
- Tune the sample rate to your volume. Every judged trace is a real LLM call - start at
sample_rate=1.0while traffic is small and you’re validating criteria, then dial down as volume grows. Deterministic patterns stay at 100%: they’re free. - Let users vote. End-user feedback (
client.feedback.report) is the cheapest evaluation signal you’ll ever get - a downvote raises a signal directly, and real-world outcomes measure how often your judges agreed with reality. - Feed findings back into offline tests. Low-scoring traces (and suspiciously perfect ones) become dataset cases - the online/offline loop is what makes both sides better.
client.monitor.signals.
A pattern is a detection rule with a real id, the same way a dataset or an evaluation config has one. Build a pattern once with client.monitor.patterns.builder(...).publish(), then reference it by id, or rely on the built-in checks and any patterns your workspace has defined in the dashboard.
This works the same way for an agent built natively in AgentX and for an external agent traced entirely through the Python SDK.
Two ways to trigger it
They can be combined; neither requires changes to how you already calltracer.trace(...) beyond the flags described below.
Trace-time: monitor and pattern_ids
Pass monitor=True on tracer.trace(...) to check that specific trace immediately, with no dashboard setup at all. pattern_ids restricts detection to exactly those patterns; omit it to run the full default sweep (built-in checks plus every active pattern) instead.
monitor=False is the opposite: it opts that trace out of every ingest-time check - patterns, online evaluators, topic classification. Use it for traces produced inside evaluation runs, where the dataset’s own judge already scores each case and a second judging pass would only double the bill. Leaving monitor unset keeps the engine’s normal behavior.
pattern_ids fully defines what’s checked when provided: only those named
patterns run, the built-in checks are skipped. This mirrors how
evaluation_settings_id fully defines an evaluation’s grading config rather
than layering on top of a default. Omit pattern_ids (keep just
monitor=True) to run the full default sweep instead.Dashboard toggle: automatic, every trace from an agent
Enable monitoring once per agent in the dashboard, and every subsequent trace from that agent is checked automatically, with nomonitor=True needed on any individual call.
- Send at least one trace. The first call to
tracer.trace(...)for a given agent name auto-creates a reference agent in your workspace. See Tracing if you haven’t wired this up yet. - Open Governance > Observe > Agents. Your SDK-traced agent appears in the agent list with an External badge, alongside any native agents.
- Turn on monitoring. Enable the agent’s monitoring profile and choose a coverage mode: sample a percentage of traffic, or check every trace.
What gets checked
Three separate streams classify a monitored trace: Operational outcomes - facts the trace itself recorded, always on, never configurable, and never raising triage signals (they feed the KPI failure metrics and Top failing instead):
Latency is a distribution metric (Overview’s p95 card, straight from the traces), not a failure
classification.
Scorers - judgments you opt in to from the Scorers page, all off by default. Six built-in
template scorers ship with the engine, all zero-LLM-cost; your own template patterns, LLM judge
scorers, and custom endpoint scorers layer on top:
Human feedback - your users’ votes via
client.feedback.report(trace_id, "down"), raising a
Negative user feedback signal directly (see User Feedback).
Metric semantics: operational outcomes and template/pattern hits classify the RUN (they move
failureRate and the run-outcome breakdown); judge, code, and external scorer verdicts are
evaluator events - they raise signals and keep per-scorer histories without reclassifying the
run. See what moves which metric.Scorer administration as code
Everything the Scorers page does is scriptable viaclient.monitor.scorers - enable the
shipped templates, deploy code/external scorers, and read their check history:
client.projects.create(name) returns an
isolated project with its own apiKey (the per-run isolation pattern integration suites use),
and client.traces.get(trace_id) / client.traces.list(cursor=...) read what the tracer wrote.
Pattern scorers you author are rules matched against the response text or the trace: keyword/contains, regex, or an LLM-judged semantic rubric. Build them via the dashboard (Scorers → New scorer → Pattern scorer - see Patterns for the condition builder, AND/OR/NOR combination, and match targets) or with client.monitor.patterns.builder(...), shown below.
The “Tool/action failure” check reads the
success: false a recorded tool
call carries. The easiest way to produce that is
tracer.trace_tool_call(...), which captures an escaping exception as a
failed call automatically - see Tracing.client.monitor.patterns
builder() parameters
publish() returns a pattern with .id, which you pass in pattern_ids at trace time.
On the hosted platform, creating a pattern requires a Business or Enterprise
plan (the same entitlement gate as the dashboard’s Patterns UI). Self-host has
no plan gates.
Where signals show up
Matches are deduped by pattern and (usually) by agent, so a recurring issue accumulates occurrences on one signal instead of creating a new row every time. Each signal links back to the trace and tool calls that produced it, so a reviewer can open the exact exchange from the dashboard (Governance > Observe), or read it straight from the SDK.client.monitor.signals
Read-only: a signal is the system’s output from checking traces against patterns, not something you create directly.
list() parameters
list()/get() both return a signal with .id, .type, .severity, .polarity, .status, .summary, .pattern_key, .occurrence_count, .occurrences, .recommended_actions, .root_cause, and more, matching the fields shown in the dashboard’s triage queue.
client.monitor.profile
Get/update one agent’s Monitor coverage settings: coverage mode, sample rate, retention, redaction, and approval policy. Legacy threshold_overrides fields still round-trip for wire compatibility, but latency is a KPI metric now (Overview’s p95 card, straight from the traces) rather than a detection threshold.
get() returns None when the agent has never been configured (still on platform defaults). update() upserts and only changes the fields you pass:
Self-host extras
A self-hosted instance adds two Monitor surfaces the hosted platform doesn’t have yet, both reachable from this same SDK:- Online evaluators (
client.monitor.online_evaluators) - a real LLM judge scoring a sample of live traffic continuously, per trace or per whole session (scope="session", judged automatically once the conversation goes idle). See Online evaluators. - Outcome reports and user feedback (
client.outcomes.report(...)/client.feedback.report(...)) - record what actually happened after the fact (a reopened ticket, an end user’s thumbs-down) against a trace; negative feedback raises a signal directly, and both streams feed the dashboard’s Judge Calibration card. See Outcomes & Judge Calibration.
Tracing
Send the traces this feature monitors
Patterns
The condition builder, match targets, and where signals go

