AgentDbg stores every agent run as two plain files under ~/.agentdbg/runs/<run_id>/. These files are the public trace format (spec_version: "0.1") — a stable contract you can rely on for building tooling, writing scripts, or integrating with other systems. Nothing is sent to any server; everything lives on your machine as human-readable JSON.
All AgentDbg releases that share spec_version "0.1" use the same format. Additive changes (new optional fields, new event types) may be introduced without bumping the spec version. Breaking changes (removed fields, changed types) always result in a new spec_version.
Files per run
Each run lives in its own directory:
~/.agentdbg/
└── runs/
└── <run_id>/
├── run.json # Run metadata — created at start, updated at end
└── events.jsonl # Append-only event log — one JSON object per line
You can override the base directory with the AGENTDBG_DATA_DIR environment variable.
run.json
run.json is created when the run starts and updated when it finishes. It gives you a quick summary of the run without reading the full event log.
Required fields:
| Field | Type | Description |
|---|
spec_version | string | Always "0.1" |
run_id | string | UUIDv4 — unique identifier for this run |
run_name | string | null | Optional human-readable label |
status | string | "running" while active · "ok" on success · "error" on failure |
started_at | string | UTC ISO8601 timestamp with milliseconds, e.g. "2026-04-12T10:30:00.000Z" |
ended_at | string | null | Set when the run finishes; null while still running |
duration_ms | integer | null | Total run duration in milliseconds; null while running |
counts | object | Cumulative event counts (see below) |
last_event_ts | string | null | Timestamp of the last event; set when the run finalizes |
counts object:
{
"llm_calls": 0,
"tool_calls": 0,
"errors": 0,
"loop_warnings": 0
}
Full example:
{
"spec_version": "0.1",
"run_id": "a1b2c3d4-1234-5678-90ab-cdef12345678",
"run_name": "customer-support-agent",
"status": "ok",
"started_at": "2026-04-12T10:30:00.000Z",
"ended_at": "2026-04-12T10:30:04.210Z",
"duration_ms": 4210,
"counts": {
"llm_calls": 3,
"tool_calls": 5,
"errors": 0,
"loop_warnings": 0
},
"last_event_ts": "2026-04-12T10:30:04.205Z"
}
events.jsonl
events.jsonl is an append-only log where each line is a complete JSON event object. Events are written in the order they occur; when timestamps are identical, the file order is authoritative. AgentDbg flushes after every write so that crashes do not lose the final event.
Event envelope
Every event — regardless of type — has these top-level fields:
| Field | Type | Description |
|---|
spec_version | string | "0.1" |
event_id | string | UUIDv4 — unique per event |
run_id | string | UUIDv4 — run this event belongs to |
parent_id | string | null | UUIDv4 of a parent event, or null |
event_type | string | One of the event types listed below |
ts | string | UTC ISO8601 with milliseconds and trailing Z |
duration_ms | integer | null | Duration in milliseconds if applicable; otherwise null |
name | string | Label — tool name, model name, run name, etc. |
payload | object | Event-type-specific data (see schemas below) |
meta | object | Freeform metadata — tags, user-defined fields |
Event types
| Type | Description |
|---|
RUN_START | Emitted when the traced function begins |
RUN_END | Emitted when the traced function finishes (ok or error) |
LLM_CALL | One LLM invocation — model, prompt, response, usage |
TOOL_CALL | One tool invocation — name, args, result, status |
STATE_UPDATE | State snapshot or diff captured between agent steps |
ERROR | An exception was captured |
LOOP_WARNING | A repeated pattern was detected in recent events |
Payload schemas
RUN_START
{
"run_name": "customer-support-agent",
"python_version": "3.11.7",
"platform": "linux",
"cwd": "/home/user/projects/my-agent",
"argv": ["run_agent.py", "--env", "staging"]
}
run_name comes from AGENTDBG_RUN_NAME, the @trace("name") argument, or a default path:function - YYYY-MM-DD HH:MM label.
argv values matching configured redact keys are replaced with __REDACTED__ before being written.
RUN_END
{
"status": "ok",
"summary": {
"llm_calls": 3,
"tool_calls": 5,
"errors": 0,
"duration_ms": 4210
}
}
status is either "ok" or "error".
LLM_CALL
{
"model": "gpt-4",
"prompt": "Summarize the search results.",
"response": "There are 42 active users.",
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
},
"provider": "openai",
"temperature": 0.7,
"stop_reason": "stop",
"status": "ok",
"error": null
}
prompt and response may be strings or objects. They may be redacted (__REDACTED__) or truncated (__TRUNCATED__) based on your configuration.
usage fields may be null if the provider did not return token counts.
- When
status is "error", the error field contains an object with error_type, message, and optionally stack and details.
provider is one of "openai", "anthropic", "local", or "unknown".
{
"tool_name": "search_db",
"args": { "query": "active users" },
"result": { "count": 42 },
"status": "ok",
"error": null
}
args and result may be objects, strings, or null.
- When
status is "error", error has the same shape as in LLM_CALL.
STATE_UPDATE
{
"state": { "step": 2, "context_length": 512 },
"diff": { "step": 2 }
}
state is the full snapshot; diff captures only what changed. diff may be null or omitted if not computed.
ERROR
{
"error_type": "ValueError",
"message": "Invalid response format from tool.",
"stack": "Traceback (most recent call last):\n ...",
"details": null
}
error_type is the Python exception class name.
stack may be null if no traceback was available.
- Guardrail aborts produce an
ERROR event with additional fields:
{
"error_type": "AgentDbgGuardrailExceeded",
"message": "max_llm_calls exceeded",
"stack": null,
"guardrail": "max_llm_calls",
"threshold": 10,
"actual": 11
}
LOOP_WARNING
{
"pattern": "search_db → summarize → search_db",
"repetitions": 3,
"window_size": 6,
"evidence_event_ids": [
"uuid-of-event-1",
"uuid-of-event-2"
]
}
- Each distinct pattern triggers at most one
LOOP_WARNING per run (deduplicated).
- When
stop_on_loop is enabled, LOOP_WARNING is written first, followed by an ERROR event and RUN_END(status="error").
Redaction and truncation
Before any payload is written to disk, AgentDbg applies redaction and truncation:
- Redaction: Field values whose key matches a configured pattern (default:
api_key, token, authorization, cookie, secret, password) are replaced with the string __REDACTED__. Redaction applies to RUN_START.argv option values and to all event payloads and meta objects.
- Truncation: Fields that exceed the configured
max_field_bytes limit (default 20000 bytes) are replaced with __TRUNCATED__.
Redaction is on by default. You can adjust which keys are redacted or disable redaction entirely via environment variables or config YAML. See the configuration reference.
When you run agentdbg export, the output file wraps the same data in a single JSON object:
{
"spec_version": "0.1",
"run": { "...same fields as run.json..." },
"events": [ "...array of event objects from events.jsonl..." ]
}
This makes it easy to load a run into any JSON-capable tool, share it with a teammate, or write scripts that process specific event types.