Skip to main content
Your agents run thousands of turns a day and the interesting ones — the jailbreak attempt, the loop, the frustrated user — are buried in logs you never read. Tracing sends each turn to Morph as an OpenTelemetry span, so Reflexes can label every turn and you can pull the raw turns back to build training sets. One call instruments the major AI SDKs (OpenAI, Anthropic, LangChain, and more) through OpenLLMetry / Traceloop and exports the spans to Morph. No collector to run.

Open the Traces dashboard

Browse traced conversations and run Reflexes over them.

Instrument your app

Install the SDK with the OpenTelemetry extra, then initialize once at startup. After that, calls to the instrumented SDKs are traced automatically.
# pip install 'morphsdk[otel]'
from morphsdk.tracing import morph_tracing

morph = morph_tracing({"api_key": "sk-..."})  # or set MORPH_API_KEY

# OpenAI / Anthropic / LangChain / etc. calls are now traced automatically.

# Wrap a turn to give it an event id, input, and tool spans:
turn = morph.begin({"user_id": "u1", "convo_id": "c1", "event": "chat"})
turn.set_input("what's the weather in SF?")
answer = turn.with_tool({"name": "get_weather"}, lambda: get_weather("SF"))
turn.finish({"output": answer})

event_id = turn.get_event_id()  # the turn's stable id
begin opens an interaction you can enrich — set_input, set_property, and with_tool / with_span to nest tool calls — and finish closes it. The event_id it mints is the join key the Reflex labels attach to.

Configuration

Pass these to morph_tracing / morphTracing. Every field is optional.
Field (py / ts)TypeDefaultDescription
api_key / apiKeystringMORPH_API_KEYSent as Authorization: Bearer <key> to the ingest endpoint.
base_url / baseUrlstringMORPH_TRACES_URLhttps://api.morphllm.comIngest base. Traces POST to {base_url}/v1/traces.
app_name / appNamestringService name stamped on every span.
disabledbooleanfalseTurn tracing off without removing the call.
trace_content / traceContentbooleantrueSet false to drop prompt/response content (zero data retention).
instrument_modules / instrumentModulessetall detectedLimit which SDKs are instrumented.
disable_batching / disableBatchingbooleanfalseExport spans one at a time (useful in serverless).
use_external_otel / useExternalOtelbooleanfalseReuse an OpenTelemetry setup you already configured.
headersobjectExtra headers on the export request.
debugbooleanfalseLog exporter activity.

Ingest directly

If you already emit OpenTelemetry spans, skip the SDK and POST OTLP/JSON straight to Morph. This is the same endpoint the SDK exports to.
POST /v1/traces
BodyOTLP/JSON (OpenTelemetry traces).
AuthAuthorization: Bearer sk-...
Max body8 MiB (413 over the limit).
Success202 with an empty body.
The account is resolved server-side from your API key and stamped onto every span — any client-supplied morph.account.* attributes are stripped. For zero-data-retention keys (or when you set trace_content: false), prompt/response content is dropped before storage.
cURL
curl -X POST "https://api.morphllm.com/v1/traces" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @spans.otlp.json

List traced turns

Browse the turns you’ve ingested — the same data behind the Traces dashboard.
GET /v1/reflex/traces?limit=&offset=&convo_id=
Returns LLM turns that carry text, newest first. Tool-only and content-stripped spans are omitted.
Query paramTypeDescription
limitintegerRows per page. Default 100, max 1000.
offsetintegerPagination offset.
convo_idstringFilter to one conversation.
// → 200
{
  "object": "reflex.trace.list",
  "data": [
    {
      "convo_id": "c1",
      "event_id": "evt-...",
      "span_kind": "llm",
      "model": "gpt-4o",
      "input_text": "what's the weather in SF?",
      "output_text": "It's 64°F and clear.",
      "start_time": "2026-06-21T17:00:00Z"
    }
  ],
  "has_more": false,
  "offset": 0
}

Reflexes overview

Label every traced turn — jailbreaks, loops, frustration, and more.

Classify a backlog

Run Reflexes over past traces with the async batch API.