agentic-ledger 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/.gitignore +4 -0
  2. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/PKG-INFO +150 -23
  3. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/README.md +145 -18
  4. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/__init__.py +1 -1
  5. agentic_ledger-0.3.0/agentledger/cli.py +177 -0
  6. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/__main__.py +6 -1
  7. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/alerts.py +1 -1
  8. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/app.py +405 -41
  9. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/dashboard.py +12 -5
  10. agentic_ledger-0.3.0/agentledger/proxy/detect.py +123 -0
  11. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/export.py +4 -4
  12. agentic_ledger-0.3.0/agentledger/proxy/loops.py +402 -0
  13. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/mcp.py +65 -1
  14. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/normalize.py +61 -7
  15. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/otel.py +2 -2
  16. agentic_ledger-0.3.0/agentledger/proxy/otlp_ingest.py +223 -0
  17. agentic_ledger-0.3.0/agentledger/proxy/pricing.py +192 -0
  18. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/redact.py +4 -1
  19. agentic_ledger-0.3.0/agentledger/proxy/static/assets/index-DxRfHpqq.js +44 -0
  20. agentic_ledger-0.3.0/agentledger/proxy/static/assets/index-smCzfG8T.css +1 -0
  21. agentic_ledger-0.3.0/agentledger/proxy/static/index.html +14 -0
  22. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/store.py +376 -7
  23. agentic_ledger-0.3.0/agentledger/proxy/stream.py +254 -0
  24. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/pyproject.toml +21 -5
  25. agentic_ledger-0.2.0/agentledger/proxy/pricing.py +0 -117
  26. agentic_ledger-0.2.0/agentledger/proxy/stream.py +0 -157
  27. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/LICENSE +0 -0
  28. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/__init__.py +0 -0
  29. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/auth.py +0 -0
  30. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/mascot.jpg +0 -0
  31. {agentic_ledger-0.2.0 → agentic_ledger-0.3.0}/agentledger/proxy/ratelimit.py +0 -0
@@ -41,3 +41,7 @@ coverage.xml
41
41
 
42
42
  # Jupyter
43
43
  .ipynb_checkpoints/
44
+
45
+ # Web app (dashboard-app builds into agentledger/proxy/static/)
46
+ dashboard-app/node_modules/
47
+ agentledger/proxy/static/
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-ledger
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Runtime observability for AI agents — see exactly what your agent did, why it did it, and what it cost.
5
- Project-URL: Homepage, https://github.com/ShekharBhardwaj/AgentLedger
6
- Project-URL: Repository, https://github.com/ShekharBhardwaj/AgentLedger
7
- Project-URL: Issues, https://github.com/ShekharBhardwaj/AgentLedger/issues
5
+ Project-URL: Homepage, https://agentic-ledger.dev
6
+ Project-URL: Repository, https://github.com/ShekharBhardwaj/AgenticLedger
7
+ Project-URL: Issues, https://github.com/ShekharBhardwaj/AgenticLedger/issues
8
8
  Author: Shekhar Bhardwaj
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
@@ -21,7 +21,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Requires-Python: >=3.10
22
22
  Requires-Dist: aiosqlite>=0.19
23
23
  Requires-Dist: fastapi>=0.110
24
- Requires-Dist: httpx>=0.27
24
+ Requires-Dist: httpx<1.0.dev0,>=0.27
25
25
  Requires-Dist: uvicorn[standard]>=0.29
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: aiosqlite>=0.19; extra == 'dev'
@@ -40,10 +40,10 @@ Provides-Extra: postgres
40
40
  Requires-Dist: asyncpg>=0.29; extra == 'postgres'
41
41
  Description-Content-Type: text/markdown
42
42
 
43
- # AgentLedger
43
+ # Agentic Ledger
44
44
 
45
- [![CI](https://github.com/ShekharBhardwaj/AgentLedger/actions/workflows/ci.yml/badge.svg)](https://github.com/ShekharBhardwaj/AgentLedger/actions/workflows/ci.yml)
46
- [![CodeQL](https://github.com/ShekharBhardwaj/AgentLedger/actions/workflows/codeql.yml/badge.svg)](https://github.com/ShekharBhardwaj/AgentLedger/actions/workflows/codeql.yml)
45
+ [![CI](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/ci.yml/badge.svg)](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/ci.yml)
46
+ [![CodeQL](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/codeql.yml/badge.svg)](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/codeql.yml)
47
47
  [![PyPI](https://img.shields.io/pypi/v/agentic-ledger)](https://pypi.org/project/agentic-ledger/)
48
48
  [![Python versions](https://img.shields.io/pypi/pyversions/agentic-ledger)](https://pypi.org/project/agentic-ledger/)
49
49
  [![Docker](https://img.shields.io/badge/docker-ghcr.io-blue)](https://ghcr.io/shekharbhardwaj/agentledger)
@@ -51,16 +51,20 @@ Description-Content-Type: text/markdown
51
51
 
52
52
  Runtime observability for AI agents — see exactly what your agent did, why it did it, and what it cost.
53
53
 
54
+ **Website:** [agentic-ledger.dev](https://agentic-ledger.dev)
55
+
56
+ > The numbers are meant to match your provider bill. If they don't, [that's a bug we want](https://github.com/ShekharBhardwaj/AgenticLedger/issues/new/choose).
57
+
54
58
  Works with **any agent framework**, **any LLM provider**, **any model gateway**. Zero code changes required. Point your agent at the proxy and everything is captured automatically.
55
59
 
56
60
  ---
57
61
 
58
62
  ## How it works
59
63
 
60
- AgentLedger runs as a transparent proxy between your agent and the LLM provider. It intercepts every request and response, assigns it an `action_id`, stores it, and returns the upstream response unmodified. Your agent never knows the proxy is there.
64
+ Agentic Ledger runs as a transparent proxy between your agent and the LLM provider. It intercepts every request and response, assigns it an `action_id`, stores it, and returns the upstream response unmodified. Your agent never knows the proxy is there.
61
65
 
62
66
  ```
63
- Your Agent → AgentLedger Proxy → OpenAI / Anthropic / LiteLLM / any LLM
67
+ Your Agent → Agentic Ledger Proxy → OpenAI / Anthropic / LiteLLM / any LLM
64
68
 
65
69
  SQLite or Postgres
66
70
 
@@ -149,10 +153,10 @@ client = anthropic.Anthropic(
149
153
 
150
154
  **LiteLLM / OpenRouter / any gateway:**
151
155
  ```bash
152
- # Point AgentLedger at your gateway
156
+ # Point Agentic Ledger at your gateway
153
157
  AGENTLEDGER_UPSTREAM_URL=http://localhost:4000 uv run python -m agentledger.proxy
154
158
 
155
- # Then point your agent at AgentLedger
159
+ # Then point your agent at Agentic Ledger
156
160
  client = OpenAI(base_url="http://localhost:8000/v1", ...)
157
161
  ```
158
162
 
@@ -164,7 +168,13 @@ client = OpenAI(base_url="http://localhost:8000/v1", ...)
164
168
  http://localhost:8000
165
169
  ```
166
170
 
167
- The dashboard updates live via WebSocket as calls come in. No refresh needed.
171
+ The web app updates live via WebSocket as calls come in. No refresh needed.
172
+
173
+ - **Loop Lens** — every loop run with status (`running` / `flagged` / `complete`), a cost-per-iteration chart, per-iteration breakdowns, and plain-English explanations of every flag
174
+ - **Sessions** — every session with three views: expandable call cards (response, thinking, tool calls, cache tokens, interaction badges), a **Flow** DAG of agent handoffs, and a **Trace** waterfall with real parent links from the loop engine
175
+ - **Search** — full-text across prompts, outputs, and agents
176
+
177
+ The classic single-file dashboard remains at `http://localhost:8000/classic`:
168
178
 
169
179
  - **Calls tab** — every LLM call with full prompt, system prompt, tool calls, tool results, output, tokens, cost, latency, and errors
170
180
  - **Flow tab** — visual DAG of your multi-agent system. Each agent is a node with aggregated cost, latency, and call count. Edges represent handoffs. Click a node to highlight its calls.
@@ -173,6 +183,70 @@ The dashboard updates live via WebSocket as calls come in. No refresh needed.
173
183
 
174
184
  ---
175
185
 
186
+ ## Coding agents — Claude Code, Ralph loops & friends
187
+
188
+ Claude Code (and most coding agents) can be pointed at the proxy with a single
189
+ environment variable — no headers, no code changes:
190
+
191
+ ```bash
192
+ AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com uv run python -m agentledger.proxy
193
+ ```
194
+
195
+ ```bash
196
+ export ANTHROPIC_BASE_URL=http://localhost:8000
197
+ claude
198
+ ```
199
+
200
+ Agentic Ledger fingerprints Claude Code traffic automatically: every call is
201
+ tagged `framework=claude-code`, and instead of one undifferentiated bucket,
202
+ each Claude Code session appears under its **real session UUID** (the same id
203
+ `claude --resume` shows), with prompt-cache reads/writes captured and priced
204
+ correctly — cache traffic is where most of a coding agent's real spend lives.
205
+
206
+ Running an overnight loop (Ralph-style `while :; do cat PROMPT.md | claude -p; done`)?
207
+ Use the built-in loop runner — it re-executes your command each iteration,
208
+ attributes every call to the run (via the base URL, no headers needed), and
209
+ stops on a completion promise, a budget ceiling, or the iteration cap:
210
+
211
+ ```bash
212
+ AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com \
213
+ AGENTLEDGER_COMPLETION_PROMISE="ALL TASKS COMPLETE" \
214
+ uv run python -m agentledger.proxy
215
+ ```
216
+
217
+ ```bash
218
+ agentledger run --max-iterations 50 --budget 25 -- \
219
+ claude -p "$(cat PROMPT.md)" --dangerously-skip-permissions
220
+ ```
221
+
222
+ Each iteration shows up as *iteration N of the run* in `/api/runs`; when the
223
+ agent prints the completion promise in a response, run status flips to
224
+ `complete` and the loop exits with a cost/token summary. Any existing loop
225
+ script works too — poll `GET /api/runs/{run_id}` yourself, or let the proxy's
226
+ budgets (`AGENTLEDGER_BUDGET_DAILY=25.00`) hard-stop a runaway loop.
227
+
228
+ The same recipe works for any client with a base-URL override (Codex CLI,
229
+ opencode, OpenClaw, LiteLLM-based stacks) — set the OpenAI/Anthropic base URL
230
+ to the proxy and traffic is captured; add `x-agentledger-*` headers when you
231
+ want explicit attribution.
232
+
233
+ **OTel-native tools** (Gemini CLI, Codex `[otel]`, AutoGen/AG2, Pydantic AI,
234
+ Vercel AI SDK) don't need the proxy at all — point their OTLP exporter at the
235
+ ledger and GenAI spans are ingested directly:
236
+
237
+ ```bash
238
+ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8000
239
+ export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
240
+ ```
241
+
242
+ **Framework guides** — one per integration in
243
+ [docs/integrations](docs/integrations/README.md): Claude Code, Codex CLI,
244
+ opencode, OpenClaw, BMAD-METHOD, LangGraph/LangChain, CrewAI, OpenAI Agents
245
+ SDK, Gemini CLI, AutoGen/AG2, Pydantic AI, Vercel AI SDK, LiteLLM, and
246
+ OpenRouter.
247
+
248
+ ---
249
+
176
250
  ## What gets captured
177
251
 
178
252
  Every LLM call is stored with:
@@ -192,11 +266,14 @@ Every LLM call is stored with:
192
266
  | `content` | Model's text output |
193
267
  | `stop_reason` | Why the model stopped |
194
268
  | `tokens_in` / `tokens_out` | Token usage |
269
+ | `cache_read_tokens` / `cache_write_tokens` | Prompt-cache usage — reads and writes are priced correctly per provider |
270
+ | `thinking` | Extended-thinking output (Anthropic), captured separately from `content` |
195
271
  | `cost_usd` | Estimated cost based on model pricing |
196
272
  | `latency_ms` | End-to-end response time |
197
273
  | `status_code` | HTTP status from upstream — errors are captured too |
198
274
  | `error_detail` | Upstream error message for non-200 responses |
199
- | `agent_name` | From `x-agentledger-agent-name` header |
275
+ | `agent_name` | From `x-agentledger-agent-name` header, or auto-detected (e.g. `claude-code`) |
276
+ | `framework` | From `x-agentledger-framework` header, or fingerprint-detected (e.g. `claude-code`, `litellm`) |
200
277
  | `user_id` | From `x-agentledger-user-id` header |
201
278
  | `app_id` | From `x-agentledger-app-id` header |
202
279
  | `environment` | From `x-agentledger-environment` header |
@@ -217,13 +294,17 @@ Every LLM call is stored with:
217
294
  | `GET` | `/` | Live dashboard |
218
295
  | `WS` | `/ws` | WebSocket stream — powers live dashboard updates |
219
296
  | `GET` | `/api/sessions` | List recent sessions with aggregated stats |
297
+ | `GET` | `/api/runs` | List loop runs (explicit or auto-inferred) with iterations, cost, status, and flagged-call counts |
298
+ | `GET` | `/api/runs/{run_id}` | One run's status (`running` / `flagged` / `complete`) — poll this from loop scripts |
299
+ | `GET` | `/api/sessions/{session_id}/tools` | Derived tool executions — each tool call paired with its result, latency, and error status |
220
300
  | `DELETE` | `/api/sessions/{session_id}` | Delete a session and all its calls |
221
301
  | `GET` | `/api/search?q=...` | Full-text search across all captured calls |
222
302
  | `GET` | `/session/{session_id}` | All calls in a session, ordered by time |
223
303
  | `GET` | `/explain/{action_id}` | Single call by action ID |
224
304
  | `GET` | `/export/{session_id}` | JSON compliance export with SHA-256 integrity hash |
225
305
  | `GET` | `/export/{session_id}/report` | Printable HTML audit report |
226
- | `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search` |
306
+ | `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search`, `list_runs`, `get_run_status` |
307
+ | `POST` | `/v1/traces` | OTLP/HTTP JSON ingest — GenAI spans from OTel-native tools become ledger calls (`/v1/logs`, `/v1/metrics` acked) |
227
308
 
228
309
  **Examples:**
229
310
  ```bash
@@ -244,7 +325,7 @@ open http://localhost:8000/export/run-1/report
244
325
 
245
326
  ## MCP server
246
327
 
247
- AgentLedger exposes its captured data as an MCP (Model Context Protocol) tool server at `POST /mcp`. Point Claude Desktop, Cursor, or any MCP-compatible client at it to query traces directly from your AI assistant.
328
+ Agentic Ledger exposes its captured data as an MCP (Model Context Protocol) tool server at `POST /mcp`. Point Claude Desktop, Cursor, or any MCP-compatible client at it to query traces directly from your AI assistant.
248
329
 
249
330
  **Tools available:**
250
331
 
@@ -254,6 +335,8 @@ AgentLedger exposes its captured data as an MCP (Model Context Protocol) tool se
254
335
  | `explain(action_id)` | Full trace for a single LLM call — prompt, tool calls, output, tokens, cost |
255
336
  | `get_session(session_id)` | All calls in a session in chronological order |
256
337
  | `search(query)` | Full-text search across all captured calls |
338
+ | `list_runs` | Loop runs with iterations, cost, and status |
339
+ | `get_run_status(run_id)` | One run's status — lets an agent inspect its own loop and decide whether to continue |
257
340
 
258
341
  **Configure in `claude_desktop_config.json`:**
259
342
  ```json
@@ -300,7 +383,7 @@ Once connected, you can ask your assistant things like:
300
383
  | `AGENTLEDGER_API_KEY` | No | _(none)_ | Master admin key. When set, the dashboard, read, and management endpoints require authentication; the key grants the `admin` role and bootstraps API tokens (below). Skip for local dev; set when the proxy is on a server — you choose the value. |
301
384
  | `AGENTLEDGER_INGEST_KEY` | No | _(none)_ | When set, the proxy forwards a request only if it carries a matching `x-agentledger-ingest-key` header — closing the open relay. Off by default; a loud startup warning fires when unset. |
302
385
  | `AGENTLEDGER_EXPORT_HMAC_KEY` | No | _(none)_ | When set, compliance exports carry a tamper-evident keyed `hmac-sha256` integrity tag instead of a plain `sha256` checksum. |
303
- | `AGENTLEDGER_EXTRA_PATHS` | No | _(none)_ | Comma-separated additional request paths to capture, e.g. `v1/responses,v1/custom`. Built-in paths (`v1/chat/completions`, `v1/messages`, `v1/responses`) are always captured. |
386
+ | `AGENTLEDGER_EXTRA_PATHS` | No | _(none)_ | Comma-separated additional request paths to capture, e.g. `v1/responses,v1/custom`. Built-in paths (`v1/chat/completions`, `v1/messages`, `v1/responses`, plus `v1/messages/count_tokens` recorded as a free call) are always captured. |
304
387
  | `AGENTLEDGER_ASYNC_CAPTURE` | No | `off` | Persist captures on a background worker so storage never adds latency to the agent's call. Trade-off: reads become **eventually consistent** (a just-captured call may not be queryable for a brief moment). Recommended for high throughput. |
305
388
  | `AGENTLEDGER_CAPTURE_QUEUE_MAX` | No | `10000` | Max captures buffered in async mode before load is shed (drops are counted in `/metrics`). |
306
389
  | `AGENTLEDGER_CAPTURE_LEVEL` | No | `full` | `full` stores everything; `metadata` stores only metrics/metadata (model, tokens, cost, latency, agent, status) and drops prompts, responses, and tools. |
@@ -327,6 +410,16 @@ Once connected, you can ask your assistant things like:
327
410
  | `AGENTLEDGER_RATE_LIMIT_AGENT_RPM` | _(none)_ | Max requests per minute per `agent_name`. |
328
411
  | `AGENTLEDGER_RATE_LIMIT_USER_RPM` | _(none)_ | Max requests per minute per `user_id`. |
329
412
 
413
+ **Loop engine** — every call is stitched into ReAct threads (`thread_id`, `step_index`, `prev_action_id`) and fresh-context loop iterations are grouped into runs, with stuck-loop detection:
414
+
415
+ | Variable | Default | Description |
416
+ |---|---|---|
417
+ | `AGENTLEDGER_LOOP_ACTION` | `warn` | `warn` records `loop_flags` and fires a `loop_flag` webhook alert; `block` additionally returns HTTP 429 (`loop_detected`) for a session that tripped a guard; `off` disables inference. |
418
+ | `AGENTLEDGER_LOOP_REPEAT_THRESHOLD` | `3` | Consecutive identical tool calls (same tool, same arguments) before a thread is flagged stuck. |
419
+ | `AGENTLEDGER_LOOP_MAX_STEPS` | _(none)_ | Flag (and in block mode, stop) threads that exceed this many ReAct steps. |
420
+ | `AGENTLEDGER_LOOP_RUN_GAP_SECONDS` | `900` | Max gap between fresh-context spawns (same system prompt) that still count as iterations of one run. |
421
+ | `AGENTLEDGER_COMPLETION_PROMISE` | _(none)_ | Regex matched against response text. On match the call is flagged `completion_promise` and the run's status becomes `complete` — loop runners poll `GET /api/runs/{run_id}` and stop. |
422
+
330
423
  **Alerts** — POST to your webhook when a threshold is breached (does not block calls — see [Alerts](#alerts)):
331
424
 
332
425
  | Variable | Default | Description |
@@ -417,7 +510,7 @@ curl -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens
417
510
  curl -X DELETE -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens/<token_id>
418
511
  ```
419
512
 
420
- > Auth is enforced only when `AGENTLEDGER_API_KEY` is set; the master key is the admin bootstrap for minting tokens. (Dashboard credential propagation over the live `/ws` feed is tracked as follow-upsee `ROADMAP.md`.)
513
+ > Auth is enforced only when `AGENTLEDGER_API_KEY` is set; the master key is the admin bootstrap for minting tokens. The live `/ws` feed accepts the same credentials (`?api_key=`, `?token=`, `Authorization: Bearer`, or `x-agentledger-token`) and rejects unauthenticated connects with close code 1008 the dashboard forwards its page credential to the socket automatically.
421
514
 
422
515
  ---
423
516
 
@@ -435,6 +528,9 @@ Pass these from your agent on each LLM call. All optional. They enrich captured
435
528
  | `x-agentledger-environment` | `development` | `production`, `staging`, or `development`. Shown in the dashboard. |
436
529
  | `x-agentledger-handoff-from` | _(none)_ | Agent handing off control (e.g. `"orchestrator"`). Renders as a directed edge in the Flow DAG. |
437
530
  | `x-agentledger-handoff-to` | _(none)_ | Agent receiving control (e.g. `"researcher"`). Renders as a directed edge in the Flow DAG. |
531
+ | `x-agentledger-framework` | _(auto-detected)_ | Framework/tool making the call (e.g. `"langgraph"`, `"bmad"`). When absent, well-known clients are fingerprinted automatically (Claude Code, LiteLLM). |
532
+ | `x-agentledger-run-id` | _(auto-inferred)_ | Groups sessions into a loop run (e.g. a Ralph overnight run). When absent, fresh-context sessions sharing a system prompt within `AGENTLEDGER_LOOP_RUN_GAP_SECONDS` are grouped automatically. |
533
+ | `x-agentledger-iteration` | _(auto-inferred)_ | Iteration number within the run. |
438
534
 
439
535
  **Single agent — fully annotated:**
440
536
  ```python
@@ -484,7 +580,7 @@ The Flow tab renders `orchestrator → researcher` as a DAG with cost and latenc
484
580
 
485
581
  **OpenAI Agents SDK (`openai-agents`) — per-agent clients:**
486
582
 
487
- The `openai-agents` SDK uses its own internal OpenAI client. To pass AgentLedger headers you need to create a client per agent using `OpenAIResponsesModel` and set it as the agent's `model`.
583
+ The `openai-agents` SDK uses its own internal OpenAI client. To pass Agentic Ledger headers you need to create a client per agent using `OpenAIResponsesModel` and set it as the agent's `model`.
488
584
 
489
585
  ```python
490
586
  import uuid
@@ -498,7 +594,7 @@ BASE_URL = os.getenv("OPENAI_BASE_URL") # e.g. http://localhost:8000/v1
498
594
 
499
595
  def al_model(agent_name: str, model: str = "gpt-4o-mini",
500
596
  handoff_from: str | None = None, handoff_to: str | None = None):
501
- """Create a model instance that sends AgentLedger metadata headers."""
597
+ """Create a model instance that sends Agentic Ledger metadata headers."""
502
598
  if not BASE_URL:
503
599
  return model # proxy not configured — use default client
504
600
  headers = {
@@ -527,7 +623,7 @@ Each agent's calls are tagged with its name and pipeline position. The Flow tab
527
623
 
528
624
  ## Alerts
529
625
 
530
- AgentLedger fires a `POST` to your webhook URL when a threshold is breached. You connect it to whatever you already use — Slack, PagerDuty, Discord, email, or a custom endpoint. AgentLedger sends the payload; the integration is on your side.
626
+ Agentic Ledger fires a `POST` to your webhook URL when a threshold is breached. You connect it to whatever you already use — Slack, PagerDuty, Discord, email, or a custom endpoint. Agentic Ledger sends the payload; the integration is on your side.
531
627
 
532
628
  **Payload format:**
533
629
  ```json
@@ -552,6 +648,8 @@ AgentLedger fires a `POST` to your webhook URL when a threshold is breached. You
552
648
  | `high_error_rate` | Session error rate exceeds `AGENTLEDGER_ALERT_ERROR_RATE` |
553
649
  | `daily_spend` | Daily total spend crosses `AGENTLEDGER_ALERT_DAILY_SPEND` |
554
650
  | `budget_exceeded` | A budget limit is hit and `AGENTLEDGER_BUDGET_ACTION` is `warn` or `both` |
651
+ | `loop_flag` | The loop engine raised flags on a call (`repeat_tool_call`, `step_budget_exceeded`, `completion_promise`) |
652
+ | `run_complete` | A run's completion promise was seen — the payload carries the full run summary (iterations, cost, tokens, flagged calls) |
555
653
 
556
654
  **Budgets vs alerts:**
557
655
  - **Budgets** (`AGENTLEDGER_BUDGET_*`) — block the call before it reaches the LLM. Agent gets HTTP 429.
@@ -569,7 +667,7 @@ AgentLedger fires a `POST` to your webhook URL when a threshold is breached. You
569
667
 
570
668
  ## OpenTelemetry export
571
669
 
572
- AgentLedger can emit every intercepted LLM call as an OTel span to any OTLP-compatible collector: Grafana Tempo, Jaeger, Honeycomb, Datadog, Dynatrace, or any vendor that supports OTLP/HTTP.
670
+ Agentic Ledger can emit every intercepted LLM call as an OTel span to any OTLP-compatible collector: Grafana Tempo, Jaeger, Honeycomb, Datadog, Dynatrace, or any vendor that supports OTLP/HTTP.
573
671
 
574
672
  **Install the extra** (Docker image includes OTel — no extra step needed when using Docker):
575
673
  ```bash
@@ -663,7 +761,7 @@ This runs three jobs:
663
761
  ```
664
762
  PyPI project name: agentic-ledger
665
763
  Owner: ShekharBhardwaj
666
- Repository: AgentLedger
764
+ Repository: AgenticLedger
667
765
  Workflow name: release.yml
668
766
  Environment name: pypi
669
767
  ```
@@ -672,6 +770,35 @@ This runs three jobs:
672
770
 
673
771
  ---
674
772
 
773
+ ## Troubleshooting
774
+
775
+ **`incompatible architecture (have 'arm64', need 'x86_64')`** on macOS — your
776
+ terminal is running under Rosetta, so Python picks its x86_64 slice while pip
777
+ installed arm64 native wheels. Check with `arch` (should print `arm64` on
778
+ Apple Silicon). Quick fix: prefix the command with `arch -arm64`. Permanent
779
+ fix: uncheck "Open using Rosetta" on your terminal app, use an Apple Silicon
780
+ build of your editor, and restart any long-lived `tmux` server.
781
+
782
+ **`module 'httpx' has no attribute 'AsyncClient'`** — fixed in
783
+ `0.3.0-alpha.2`; upgrade with `pip install --upgrade agentic-ledger`.
784
+
785
+ **Port 8000 already in use** — another proxy instance (or app) is running;
786
+ stop it or set `AGENTLEDGER_PORT`.
787
+
788
+ **`401 OAuth access token has expired` from Claude Code** — the proxy passed
789
+ Anthropic's answer through unmodified; re-authenticate with `claude` →
790
+ `/login`. Errored calls are still captured, so you'll see the 401 in the
791
+ dashboard.
792
+
793
+ **`/` shows the classic dashboard instead of the web app** — you're running
794
+ from a source checkout without the web-app build. `cd dashboard-app && npm ci
795
+ && npm run build` and restart. PyPI and Docker installs always include the app.
796
+
797
+ ---
798
+
675
799
  ## License
676
800
 
677
801
  MIT
802
+
803
+ <!-- MCP registry ownership verification -->
804
+ `mcp-name: io.github.shekharbhardwaj/agentic-ledger`