Behavioral observability for AI agents
Project description
Dunetrace SDK
Runtime observability for AI agents. Detects tool loops, context bloat, prompt injection, and 12 other failure patterns in real-time — with a Slack alert while the run is still live.
Zero external dependencies.
Install
pip install dunetrace # core SDK
pip install 'dunetrace[langchain]' # + LangChain / LangGraph
pip install 'dunetrace[otel]' # + OpenTelemetry exporter
Quickstart
LangChain / LangGraph
from dunetrace import Dunetrace
from dunetrace.integrations.langchain import DunetraceCallbackHandler
dt = Dunetrace()
callback = DunetraceCallbackHandler(dt, agent_id="my-agent")
result = agent.invoke(input, config={"callbacks": [callback]})
dt.shutdown()
Pure Python / custom agent
from dunetrace import Dunetrace
dt = Dunetrace()
dt.auto_instrument() # patches openai, anthropic, httpx, requests
@dt.agent("my-agent", model="gpt-4o")
def run_agent(query: str) -> str:
return openai_client.chat.completions.create(...).choices[0].message.content
FastAPI / Flask — one line each, see docs/integrations.md.
What it detects
| Detector | What it catches | Severity |
|---|---|---|
TOOL_LOOP |
Same tool called 3+ times in a 5-call window | HIGH |
TOOL_THRASHING |
Agent alternates between exactly two tools | HIGH |
RETRY_STORM |
Same tool fails 3+ times in a row | HIGH |
LLM_TRUNCATION_LOOP |
finish_reason=length fires 2+ times |
HIGH |
EMPTY_LLM_RESPONSE |
Zero-length output with finish_reason=stop |
HIGH |
CASCADING_TOOL_FAILURE |
3+ consecutive failures across 2+ distinct tools | HIGH |
SLOW_STEP |
Tool call >15s or LLM call >30s | MEDIUM/HIGH |
TOOL_AVOIDANCE |
Final answer without using available tools | MEDIUM |
GOAL_ABANDONMENT |
Tool use stops, then 4+ consecutive LLM calls with no exit | MEDIUM |
CONTEXT_BLOAT |
Prompt tokens grow 3× from first to last LLM call | MEDIUM |
STEP_COUNT_INFLATION |
Run used >2× the P75 step count for this agent | MEDIUM |
FIRST_STEP_FAILURE |
Error or empty output at step ≤2 | MEDIUM |
REASONING_STALL |
LLM:tool-call ratio ≥4× — reasoning without acting | MEDIUM |
RAG_EMPTY_RETRIEVAL |
Retrieval returned 0 results but agent answered anyway | MEDIUM |
PROMPT_INJECTION_SIGNAL |
Input matches known injection / jailbreak patterns | CRITICAL |
Output modes
| Mode | How to enable | Destination |
|---|---|---|
| HTTP ingest (default) | endpoint="http://…" |
Dunetrace backend → detection, alerts, dashboard |
| Loki NDJSON | emit_as_json=True |
stdout → Promtail / Grafana Alloy |
| OpenTelemetry | otel_exporter=DunetraceOTelExporter(provider) |
Tempo, Honeycomb, Datadog, Jaeger |
Backend
git clone https://github.com/dunetrace/dunetrace
cd dunetrace && cp .env.example .env && docker compose up -d
Dashboard → http://localhost:3000 · Ingest → http://localhost:8001
Tests
python -m unittest discover -s tests -v
52 tests, no network required.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dunetrace-0.3.5.tar.gz.
File metadata
- Download URL: dunetrace-0.3.5.tar.gz
- Upload date:
- Size: 39.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
824ce4e9dd711ff84ffec542a9c367da95a28bff4258bece7dfc49ef6b5a5e0e
|
|
| MD5 |
deb9bfd170b70864dacbe42b974c6d37
|
|
| BLAKE2b-256 |
b98362320cb5f49ea6f01abc2ab7c4cf69e4cda5bbfbe6e751ba302796c493c5
|
Provenance
The following attestation bundles were made for dunetrace-0.3.5.tar.gz:
Publisher:
publish.yml on dunetrace/dunetrace
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dunetrace-0.3.5.tar.gz -
Subject digest:
824ce4e9dd711ff84ffec542a9c367da95a28bff4258bece7dfc49ef6b5a5e0e - Sigstore transparency entry: 1280178057
- Sigstore integration time:
-
Permalink:
dunetrace/dunetrace@aedf63c68d151f454fe29932d54e0a275db2ba11 -
Branch / Tag:
refs/tags/v0.3.5 - Owner: https://github.com/dunetrace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aedf63c68d151f454fe29932d54e0a275db2ba11 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dunetrace-0.3.5-py3-none-any.whl.
File metadata
- Download URL: dunetrace-0.3.5-py3-none-any.whl
- Upload date:
- Size: 32.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7a2dae6c2d8d4c91dede770328901aa051690c444a8eb99f8db29e8d761c943
|
|
| MD5 |
d002f80abb217595e0132c8cab1192c5
|
|
| BLAKE2b-256 |
64b9e14c09b9ea38e95573391c13125b990b4212806150c068b72c35d672d227
|
Provenance
The following attestation bundles were made for dunetrace-0.3.5-py3-none-any.whl:
Publisher:
publish.yml on dunetrace/dunetrace
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dunetrace-0.3.5-py3-none-any.whl -
Subject digest:
b7a2dae6c2d8d4c91dede770328901aa051690c444a8eb99f8db29e8d761c943 - Sigstore transparency entry: 1280178061
- Sigstore integration time:
-
Permalink:
dunetrace/dunetrace@aedf63c68d151f454fe29932d54e0a275db2ba11 -
Branch / Tag:
refs/tags/v0.3.5 - Owner: https://github.com/dunetrace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aedf63c68d151f454fe29932d54e0a275db2ba11 -
Trigger Event:
push
-
Statement type: