Open the Traces dashboard
Where labeled turns land. Browse conversations, run Reflexes by hand, and export the raw turns.
How the pieces fit
| Piece | What it does | Where it lives |
|---|---|---|
| Tracing SDK | One morph_tracing() call instruments OpenAI / Anthropic / LangChain and exports spans to Morph. | Your app, at startup. |
begin() / finish() | Wraps a turn so it gets a stable event_id — the join key labels attach to. | Around each turn you want classified. |
evals | Names which Reflexes run on which role (user / assistant). Morph classifies after the span lands. | On begin(), or as a default. |
| Read-back | The dashboard and GET /v1/reflex/traces return each turn with its reflex_results. | Dashboard + API. |
begin(). Auto-instrumented LLM calls outside an interaction still get traced, but they have no event_id, so no label can attach.
Wire it up
Instrument your app
Install the SDK with the OpenTelemetry extra and initialize once at startup. After this, calls to instrumented SDKs are traced with no further changes.
Wrap the turns you want classified
Open an interaction with Keep
begin(), set the input, nest any tool calls, and close it with finish(). The event_id it mints is what every label links back to.convo_id stable across a conversation so the dashboard threads turns together, and user_id consistent so you can slice labels by user later.Turn on automatic classification
Pass Set a default for every turn by passing
evals on the turn. You choose which role each Reflex reads: user for the incoming message, assistant for the agent’s output. Morph classifies each role after the span lands, off your request path.evals to morph_tracing / morphTracing; a per-begin value overrides it. Omit both and nothing runs.Read the labels back
Open the Traces dashboard to browse turns with their labels, or pull them with the API. A freshly-traced turn shows “Classifying…” for a moment, then carries its
reflex_results.Python
GET /v1/reflex/traces returns LLM turns that carry text, newest first, each with the labels attached whether they ran from the SDK or by hand in the dashboard. Filter to one conversation with convo_id, page with limit / offset. See the field reference.Which Reflex on which role
Most safety and intent classifiers read the user’s message; response-quality ones read the agent’s output. A sensible starting set for a chat or coding agent:| Reflex | Role | Catches |
|---|---|---|
jailbreak | user | Prompt-injection and jailbreak attempts before they shape the response. |
guardrail | user | Harassment or NSFW content in the incoming message. |
user-frustrated | user | The user losing patience — the signal that your agent is failing in a way tests won’t show. |
incomplete-thought | user | Truncated or underspecified prompts, so you can tell “bad answer” from “bad question.” |
leaked-thinking | assistant | The agent spilling internal reasoning or system instructions into its reply. |
stuck-in-a-loop | assistant | The agent repeating itself instead of trying something new. |
evals arrays by name.
Worked example: a chat agent
End to end — instrument once, then label jailbreaks and frustration on the user side and leaked thinking on the assistant side for every turn.What to do with the labels
A label is only worth collecting if you act on it.- Alert. Poll
GET /v1/reflex/traces(or wire the dashboard) and page on-call whenjailbreakorguardrailfires, or whenuser-frustratedcrosses a rate you set for a conversation. - Build training sets. Filter traces by label to pull the exact turns you want — every
stuck-in-a-loopturn, every frustrated exchange — and feed them into evals or fine-tuning. The list endpoint returnsinput_textandoutput_textdirectly. - Track trends. Watch a label’s rate over time to know whether a prompt change actually reduced frustration or just moved it.
Classification rides the trace export, so it adds nothing to your latency, and it’s billed per event ($0.001/event realtime, stepping down past 1M/month). You pay only for the turns you put in
evals, not every traced span. See Reflex pricing.Backfill traces you already have
Turning onevals only labels turns going forward. To classify a backlog — every conversation from last month, scanned for jailbreaks and loops — run it from the Traces dashboard: select conversations, pick the Reflexes, and the labels land back on each trace. Under the hood that’s an asynchronous batch over the text of each turn, billed at the discounted batch rate. No code required.
Next steps
Tracing reference
Every config field, direct OTLP ingest, and the
/v1/reflex/traces schema.Reflexes overview
The nine default classifiers, response shape, and realtime
/predict.Train a Custom Reflex
When the defaults don’t match your failure modes, train one in ~30s and drop it into
evals.Batch classification
Label a backlog of up to 10,000 rows offline at the discounted rate.