Runtime reliability for AI agents. Structural and semantic detection, runtime prevention, native root cause, and one-click fixes.
If Dunetrace helps you, consider giving it a ⭐ on top right, it helps others find the project.
AI agents fail silently:
- ✓ API returns 200 ✓ Latency is normal ✓ Cost looks normal
- ✗ The upstream API returned an error body. The agent invented the numbers and reported success.
- ✗ Two agents delegated in a circle. Eight runs, all green, no progress.
- ✗ A document your agent read last week wrote an instruction into its memory. It fired today.
Tracers answer "what happened?" — after you already know it broke. Dunetrace answers "is something breaking right now?" with deterministic, zero-LLM checks on every run, and in the request path, where a policy can block the action before it executes.
Dunetrace covers the full agent reliability lifecycle, not just one slice of it:
| Pillar | What it does | |
|---|---|---|
| 1 | Sessions & Events | Every run, every tool call, every LLM exchange — the raw data everything else is built on |
| 2 | Structural Detection | 34 zero-LLM detectors (31 of them in-path, sub-500μs per hook) — the always-on first line → docs/detectors.md |
| 3 | Semantic Evaluation | LLM-based judgment (hallucination, task completion, cross-turn frustration) — post-hoc, sampling-based, opt-in → docs/semantic-evaluation.md |
| 4 | Runtime Prevention | Policies that stop, redirect, or downgrade a run while it's happening — the differentiator no tracer offers → docs/policies.md |
| 5 | Root Cause & Fix | Native root-cause analysis, auto-applied policy fixes, or a one-click draft PR → Diagnose & fix |
See the examples index for ready‑to‑run examples.
1. Start the backend
git clone https://github.com/dunetrace/dunetrace
cd dunetrace && cp .env.example .env
docker compose -f docker-compose.ghcr.yml up -d
pip install -r requirements.txt2. Install the SDK
pip install dunetrace # Python
npm install dunetrace # Node.js / TypeScript3. Instrument your agent
Python
from dunetrace import Dunetrace
import openai
dt = Dunetrace()
dt.init(agent_id="support-agent") # auto-instruments installed clients (OpenAI, Anthropic, Mistral, Bedrock, LangChain, CrewAI, httpx, requests)
@dt.agent("support-agent", model="gpt-4o")
def my_agent(question: str) -> str:
resp = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": question}],
)
return resp.choices[0].message.content # LLM + tool calls tracked automatically, no manual hooksTypeScript / Node.js
import { Dunetrace, autoInstrument } from "dunetrace";
import OpenAI from "openai";
const dt = new Dunetrace();
autoInstrument({ openai: OpenAI }); // patches OpenAI + outbound fetch; add `anthropic:` / `mistral:` too, or wrap one client with dt.wrapOpenAI()
const openai = new OpenAI(); // constructed after the patch — still tracked
await dt.run("support-agent", { model: "gpt-4o" }, async (run) => {
await openai.chat.completions.create({ model: "gpt-4o", messages });
run.finalAnswer(); // LLM + tool calls tracked automatically, streaming included
});→ TypeScript auto-instrumentation
Try the built-in failure scenarios
cd packages/sdk-py # Python
python examples/basic_agent.py # No LLM calls
SCENARIO=tool_loop python examples/langchain_agent.py # TOOL_LOOP via LangChain
SCENARIO=failures python examples/decorator_agent.py # TOOL_LOOP, RETRY_STORM, RAG_EMPTY_RETRIEVAL
cd ../sdk-ts && npm install && ollama pull llama3.2 # TypeScript — Vercel AI SDK on local Ollama, no API key
npm run example:vercel-ai # Happy path
npm run example:vercel-ai:loop # TOOL_LOOP → detect → explain, end to endOpen the dashboard: http://localhost:3000
34 detectors run on every completed run — no configuration, no LLM. A few of the main ones:
| Signal | What it catches |
|---|---|
TOOL_LOOP |
Same tool called repeatedly with identical args |
RETRY_STORM |
Tool failing, agent retrying it repeatedly |
COST_SPIKE |
Total token consumption unusually high vs per-agent baseline |
PROMPT_INJECTION_SIGNAL |
Input matched adversarial injection patterns |
MEMORY_POISONING |
An injection directive was written into the agent's own memory, re-steering it when read back |
DELEGATION_LOOP |
Agents delegate to each other in a cycle that never converges |
RUNAWAY_ITERATION |
Step or cost ceiling crossed with no completion signal |
SILENT_TRUNCATION |
A response was truncated and the agent used it without retrying |
MODEL_FALLBACK_DRIFT |
The run silently switched to a weaker model (e.g. under rate limiting) |
Each alert carries what fired, why it matters, a concrete fix, and rate context (first occurrence / recurring / systemic). → docs/detectors.md for all 34
- Multi-agent — nested
dt.run()calls auto-link into a delegation graph thatDELEGATION_LOOPandHANDOFF_CONTEXT_LOSSread → docs/multi-agent.md - Agent memory — instrument memory writes/reads and
MEMORY_POISONINGflags adversarial content persisted into them → docs/memory.md - Custom detectors — describe one in plain English; it runs in shadow mode until you approve the fire rate → docs/detectors.md
- Detector packs — opt-in bundles per org; the voice pack adds 9 detectors → detector packs · voice pack
Opt-in LLM judgment for what structural checks can't see — seven DeepEval-backed evaluators (hallucination, task completion, task-understanding failure, off-topic drift, user frustration, confusion loops, sycophancy). Post-hoc and sampling-based, never in your agent's request path. Its own container, off by default:
SEMANTIC_WORKER_ENABLED=trueLive at http://localhost:3000. Auto-refreshes every 15s.
Slack and generic webhook (PagerDuty, Linear, custom).
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
SLACK_MIN_SEVERITY=LOW # LOW | MEDIUM | HIGH | CRITICAL
DIGEST_ENABLED=true # weekly digest of top failure types, Monday 9am UTCClick Explain + on any alert: Dunetrace analyzes the run's own stored events (no third-party tracer) and returns a cause plus a fix — either a runtime policy it applies itself (tool loops, retry storms, runaway step counts) or a prompt/code diff you copy in or open as a draft PR. Fix effectiveness is tracked automatically.
Runtime guardrails that fire mid-run — before a failure propagates. Defined in code or in the dashboard (the SDK refetches every 60s).
dt.add_policy( # stop, switch_model, escalate, inject, ...
name="cap tool calls",
condition={"trigger": "tool_call_count", "operator": "gt", "value": 5},
action={"type": "stop"},
)
dt.add_policy( # human-in-the-loop: blocks the call until
name="approve-wires", # someone approves in Slack or the dashboard,
condition={"trigger": "before_tool_call", "operator": "eq", "value": "wire_money"},
action={"type": "require_approval", "params": {"timeout_s": 300}}, # fail-closed on timeout
)→ docs/policies.md · docs/approvals.md
Query agent signals from Claude Code, Cursor, or Codex — "what failed in the last 24 hours?" — without leaving your editor.
pip install dunetrace-mcp31 tools covering agents, runs, signals, fixes, issues, policies, custom detectors and voice calls. Claude Code registers the server automatically in ~/.claude.json (restart to load); Cursor and Codex need one config block.
A representative 10 of the 31 tools
| Tool | What you can ask |
|---|---|
list_agents |
"Which agents are monitored and how healthy are they?" |
get_agent_signals |
"What failures did my agent have today?" |
get_agent_health |
"Show me the health score breakdown for my agent." |
get_signal_detail |
"Show me signal #42 with full evidence and fix code." |
get_agent_patterns |
"Is this failure systemic or a one-off?" |
get_run_detail |
"Walk me through run abc123 step by step." |
get_agent_runs |
"List recent runs for my agent with their status." |
search_signals |
"Show me all CRITICAL signals in the last 24 hours." |
summarize_agent |
"Give me a one-shot diagnosis of my agent." |
get_agent_token_stats |
"How much is my agent wasting on failed runs?" |
Agent Code
└─► Dunetrace SDK (raw content → ingest events)
└─► Ingest API (POST /v1/ingest → Postgres)
├─► Detector (poll → 34 detectors → signals)
├─► Semantic Worker (optional — poll → DeepEval → signals)
├─► Integrations (optional — pull Langfuse/LangSmith/Braintrust)
├─► Alerts (poll → explain → Slack / webhook)
└─► Customer API (runs, signals, explanations → dashboard)
→ docs/architecture.md for the full service breakdown · operations guide (retention, rate limiting, quotas)
Model providers — OpenAI, Anthropic, Mistral and AWS Bedrock, auto-instrumented with no call-site changes.
- Auto-instrumentation (what's patched, streaming, agent_id resolution)
- Mistral (hyperscaler-hosted clients, EU-resident evaluation)
Evaluation & tracing
- OpenTelemetry export (Datadog, Grafana, Honeycomb, Signoz, any OTLP backend)
- OpenTelemetry ingestion (send your existing OTel traces to Dunetrace: OpenLIT, Traceloop, OTel contrib)
- External evaluation (Langfuse, LangSmith, Braintrust, generic push)
- Semantic evaluation (Dunetrace's own DeepEval-backed layer)
Fix & workflow
- GitHub App (automated draft PRs)
- Slack & Linear alerts
- Coding agents — Claude Code, Cursor, Codex (MCP)
Voice
- ElevenLabs (correlate TTS cost and voice choices with agent behavior)
- Wiring a voice framework
- Voice metrics (call-level view of a voice agent)
- Voice detector pack (9 detectors)
Agent frameworks: LangChain, CrewAI, AutoGen, Haystack, LlamaIndex, TypeScript, and more
Fork, branch, change, make test, PR — open an issue first for new integrations or architecture changes. Requires Python 3.11+, Node.js 22+, Docker + Docker Compose.
→ CONTRIBUTING.md (setup and workflow) · good first issues · adding a detector
Dunetrace UG (haftungsbeschränkt) · Kolonnenstr. 8, 10827 Berlin, Germany · vikas@dunetrace.com







