Platform

Four things happen
to every run.

A run enters the collector as a stream of spans and leaves as something you can search, alert on, bill against, and re-execute. No sampling gaps in between, and no vendor lock-in on the way out — every span is OpenTelemetry underneath.

SDK / OTelCollector Span storeRules engineReplay in-process, 1.4 msredact + batch columnar, 30d hotevaluated on writeoffline re-run your processour region, your residencyon demand protobufgzip batchindexquery
  1. SDK / OTelin-process, 1.4 ms
  2. Collectorredact + batch
  3. Span storecolumnar, 30d hot
  4. Rules engineevaluated on write
  5. Replayoffline re-run
How it works

Pick a stage.

Captured span tree · checkout-agentcomplete
agent.run checkout-agent8.12s
llm.chat claude-sonnet1.79s
tool.inventory.check0.71s
http.get /v1/stock0.48s
tool.payments.charge2.51s
http.post retry 1 · 5020.62s
http.post retry 2 · 2001.44s
llm.chat confirm2.44s

The two http.post children were produced by the payments SDK's internal retry logic. Nobody instrumented them; the patched transport reported them.

Rule · runaway_tool_loopfired 3× today
when span.kind == "tool" and count(span.name) over run > 5 and distinct(span.input_hash) over run == 1 then page("refunds-oncall") with sample_trace
Last firing
run_9f3c2a41 refunds.create ×638s in
run_2ba71c search_docs ×91m 04s
run_c40e18 sql.query ×752s
Evaluated on
ingest path
Median detection
38 s
False positives / 30d
2
Destinations
PagerDuty · Slack · webhook
Spend by model · September$6,293.57
gpt-4oclaude-sonnet-4.5gpt-4o-minillama-3.3-70b $2,958.12$1,944.30$952.44$438.71
TenantRuns$ / runMargin
acme-eu41,208$0.072+68%
northwind28,640$0.062+71%
lumen-health12,904$0.071+12%
hexa-freight8,116$0.067−4%

hexa-freight runs an agent that retries three times on average. It costs more to serve than they pay. That is a trace query, not a spreadsheet exercise.

Replay · run_9f3c2a41 → prompt v12dry run
Source trace
run_9f3c2a41 · failed
Tool responses
served from recording
Model
gpt-4o → claude-sonnet-4.5
Replay cost
$0.0181
Prompt diff
-Retry failed tool calls until they succeed.
+Retry a failed tool at most twice, then stop and
+call escalate_to_human with the last error.
+Never resend a prior failure transcript verbatim.
Outcome
refunds.create 429 ×2 then stop1.9s
escalate_to_human ticket opened0.3s
Cost of the same run, patched $0.0139  (−66%)
Overhead, measuredpython 3.12 · c7g.large
Operationp50p99Bytes
Span start + end1.4 ms3.9 ms640 B
LLM call wrap2.1 ms5.2 ms2.8 KB
Redaction pass0.6 ms1.8 ms
Batch export (256 spans)18 ms44 ms12 KB

Export happens on a background thread with a bounded queue. If the queue fills, spans are dropped and counted — your agent is never blocked by our availability.

What leaves your networkconfigurable
Span names, timings, status, token counts
Tool arguments, hashed
Prompt and completion bodies
Raw tool responses

Bodies are off by default. With them off you still get the waterfall, the costs, and every rule except semantic ones. Turn them on per service, per environment, or per tenant — the toggle lives in the SDK config, so the data never reaches us in the first place.

Regulated workloads can run the collector inside their own VPC and forward only aggregates. Same UI, same rules, docker compose up.

Works with

If it emits a span, we keep it.

OpenAI SDK Anthropic SDK LangGraph LlamaIndex Vercel AI SDK CrewAI Temporal OpenTelemetry

No integration on the list? The ingest endpoint speaks OTLP over HTTP. Point any collector at ingest.nocturne.dev/v1/traces and the agent-specific views light up as soon as spans carry a gen_ai.* attribute.

Instrument one agent today.

Free under 50,000 spans a month — roughly 3,500 agent runs. Enough to watch a real service for a week before you decide.

developed by simple flow