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 ✓ Logs are clean
- ✗ Agent called the same tool 12 times, burned $10, and gave the user a wrong answer
Tracers answer "what happened?" — after you already know it broke. Dunetrace answers "is something breaking right now?" and fires an alert in 15 seconds, using zero-LLM structural checks that run in-path with sub-500μs overhead.
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 | 27 zero-LLM detectors, in-path, sub-500μs — the always-on first line |
| 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 |
Where tracers fit in: if you already run Langfuse, LangSmith, or Braintrust, Dunetrace pulls their evaluation results in alongside its own (pillar 3) rather than asking you to switch — see docs/integrations/external-evaluation.md. What no tracer does is pillar 4: none of them can stop a run mid-flight, because none of them run in-path.
| Dunetrace | A tracer (Langfuse / LangSmith / etc.) | |
|---|---|---|
| When it fires | Within 15s of run completion (structural); can also stop a run while it's happening (policies) | You query it after you notice a problem |
| What it watches | Structural patterns (always) + LLM-based semantic judgment (opt-in) | Raw trace data |
| Alert channel | Slack / webhook / Dashboard | Dashboard only |
| Fix path | Auto-apply a policy, one-click draft PR, or push to a connected prompt store | Manual |
| Your existing tracer | Pull its evaluations in, use alongside Dunetrace's own | — |
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, 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 } from "dunetrace";
import OpenAI from "openai";
const dt = new Dunetrace();
const openai = dt.wrapOpenAI(new OpenAI());
await dt.run("my-agent", { model: "gpt-4o" }, async (run) => {
await openai.chat.completions.create({ model: "gpt-4o", messages });
run.finalAnswer();
});Try the built-in failure scenarios
cd packages/sdk-py
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_RETRIEVALOpen the dashboard: http://localhost:3000
28 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 includes: what fired, why it matters, a concrete fix, and a rate context line (first occurrence / recurring / systemic).
→ docs/detectors.md for the full list of 28 detectors
Multi-agent systems — instrument each agent as its own dt.run() and Dunetrace auto-links them into a delegation graph (parent_run_id is threaded automatically for nested runs). Two detectors read that graph: DELEGATION_LOOP (agents cycling without converging) and HANDOFF_CONTEXT_LOSS (a handoff dropping the parent's context). → docs/multi-agent.md
Agent memory — instrument what an agent writes to and reads from its own memory (run.memory_written() / memory_read(), or automatically for LangGraph/CrewAI memory via dt.auto_instrument()), and MEMORY_POISONING flags adversarial content persisted into it. → docs/memory.md
Custom detectors — write a detector in plain English. Dunetrace translates it to a structured condition set, runs it in shadow mode against real traffic, and lets you review the fire rate before any alert fires. In the dashboard: Config → Custom detectors → Add detector.
Detector packs — opt-in detector bundles for a specific class of agent, activated per org. The voice pack adds 9 detectors for real-time voice agents (dt.enable_pack("voice")). Built-in detectors always run; packs only add to them and start in shadow mode.
→ detector packs · voice pack · wiring a voice framework
For failure modes no structural check can catch — did the agent hallucinate,
did it finish the task, did it solve the wrong task, is the user going in
circles. Post-hoc (never in your agent's request path), sampling-based,
disabled by default. Ships seven DeepEval-backed
evaluators — four run-level (hallucination, task completion, task-understanding
failure, off-topic drift) and three conversation-level (user frustration,
confusion loops, sycophancy) — plus false-positive management (confidence
floors, grouping, feedback loop, second-opinion for high-stakes findings). Each
calibrated before ship (see scripts/calibration/).
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 | CRITICALA weekly digest (Monday 9am UTC) summarises top failure types and systemic patterns. Enable with DIGEST_ENABLED=true.
Root-cause analysis is native — no third-party tracer required. Click Explain + on any alert and Dunetrace analyzes the run's own stored events and returns a specific cause and fix. Every fix is one of two kinds:
- Policy fixes (tool loops, retry storms, runaway step counts) → Dunetrace applies a runtime guardrail directly, no code change needed
- Prompt / code fixes → a diff you copy in, or a one-click draft PR on GitHub for code/infra changes
Fix effectiveness is tracked automatically.
Runtime guardrails that fire mid-run — before a failure propagates.
dt.add_policy(
name="cap tool calls",
condition={"trigger": "tool_call_count", "operator": "gt", "value": 5},
action={"type": "stop"},
)
dt.add_policy(
name="cost cap",
condition={"trigger": "cost_usd", "operator": "gt", "value": 0.50},
action={"type": "switch_model", "params": {"model": "gpt-4o-mini"}},
)Policies can also be created in the dashboard and fetched automatically by the SDK (60s TTL).
Human-in-the-loop approvals — gate a risky tool (wiring money, deleting data) behind human approval. A require_approval policy blocks the tool call until someone approves in Slack or the dashboard, or it times out (fail-closed: a timeout blocks the tool). No agent code changes — the gate fires on the existing tool-call hook.
dt.add_policy(
name="approve-wires",
condition={"trigger": "before_tool_call", "operator": "eq", "value": "wire_money"},
action={"type": "require_approval", "params": {"timeout_s": 300}},
)→ docs/policies.md · docs/approvals.md
Query agent signals directly from Claude Code, Cursor, or Codex — without leaving your editor.
pip install dunetrace-mcp29 tools for signals, runs, policies, and custom detectors. Ask your editor things like "what failed in the last 24 hours?" A representative 10:
| 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?" |
Claude Code: registered automatically in ~/.claude.json after pip install dunetrace-mcp. Restart Claude Code to load.
Cursor: add .cursor/mcp.json to your project root:
{
"mcpServers": {
"dunetrace": {
"command": "dunetrace-mcp",
"env": {
"DUNETRACE_API_URL": "http://localhost:8002",
"DUNETRACE_API_KEY": "dt_dev_test"
}
}
}
}Agent Code
└─► Dunetrace SDK (raw content → ingest events)
└─► Ingest API (POST /v1/ingest → Postgres)
├─► Detector (poll → 28 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
Evaluation & tracing
- 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)
Agent frameworks: LangChain, CrewAI, AutoGen, Haystack, LlamaIndex, TypeScript, and more
Fork, branch, change, make test, PR. For larger changes (new integrations, architecture changes), open an issue first.
New here? See CONTRIBUTING.md for setup and workflow, browse the good first issues (most are "add one detector"), and follow the step-by-step Adding a detector guide.
Requires Python 3.11+, Node.js 22+, Docker + Docker Compose.






