agentic-ledger 0.2.0__tar.gz → 0.3.0a2__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.
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/.gitignore +4 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/PKG-INFO +116 -24
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/README.md +111 -19
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/__init__.py +1 -1
- agentic_ledger-0.3.0a2/agentledger/cli.py +177 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/__main__.py +6 -1
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/alerts.py +1 -1
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/app.py +340 -40
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/dashboard.py +12 -5
- agentic_ledger-0.3.0a2/agentledger/proxy/detect.py +123 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/export.py +4 -4
- agentic_ledger-0.3.0a2/agentledger/proxy/loops.py +355 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/mcp.py +65 -1
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/normalize.py +61 -7
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/otel.py +2 -2
- agentic_ledger-0.3.0a2/agentledger/proxy/otlp_ingest.py +170 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/pricing.py +58 -7
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/redact.py +4 -1
- agentic_ledger-0.3.0a2/agentledger/proxy/static/assets/index-D4Qv-Grl.js +40 -0
- agentic_ledger-0.3.0a2/agentledger/proxy/static/assets/index-zOG9lcmm.css +1 -0
- agentic_ledger-0.3.0a2/agentledger/proxy/static/index.html +13 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/store.py +332 -7
- agentic_ledger-0.3.0a2/agentledger/proxy/stream.py +254 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/pyproject.toml +21 -5
- agentic_ledger-0.2.0/agentledger/proxy/stream.py +0 -157
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/LICENSE +0 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/__init__.py +0 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/auth.py +0 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/mascot.jpg +0 -0
- {agentic_ledger-0.2.0 → agentic_ledger-0.3.0a2}/agentledger/proxy/ratelimit.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-ledger
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0a2
|
|
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/
|
|
6
|
-
Project-URL: Repository, https://github.com/ShekharBhardwaj/
|
|
7
|
-
Project-URL: Issues, https://github.com/ShekharBhardwaj/
|
|
5
|
+
Project-URL: Homepage, https://github.com/ShekharBhardwaj/AgenticLedger
|
|
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
|
|
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
|
-
#
|
|
43
|
+
# Agentic Ledger
|
|
44
44
|
|
|
45
|
-
[](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/ci.yml)
|
|
46
|
+
[](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/codeql.yml)
|
|
47
47
|
[](https://pypi.org/project/agentic-ledger/)
|
|
48
48
|
[](https://pypi.org/project/agentic-ledger/)
|
|
49
49
|
[](https://ghcr.io/shekharbhardwaj/agentledger)
|
|
@@ -51,16 +51,18 @@ 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
|
+
> **Alpha** — `v0.3.0-alpha.1` is an early release of the loop engine, Loop Lens web app, and framework integrations. Interfaces and schema may still change between alpha releases. Found something broken or missing? [Open an issue](https://github.com/ShekharBhardwaj/AgenticLedger/issues/new/choose) — alpha feedback directly shapes what ships next.
|
|
55
|
+
|
|
54
56
|
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
57
|
|
|
56
58
|
---
|
|
57
59
|
|
|
58
60
|
## How it works
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
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
63
|
|
|
62
64
|
```
|
|
63
|
-
Your Agent →
|
|
65
|
+
Your Agent → Agentic Ledger Proxy → OpenAI / Anthropic / LiteLLM / any LLM
|
|
64
66
|
↓
|
|
65
67
|
SQLite or Postgres
|
|
66
68
|
↓
|
|
@@ -149,10 +151,10 @@ client = anthropic.Anthropic(
|
|
|
149
151
|
|
|
150
152
|
**LiteLLM / OpenRouter / any gateway:**
|
|
151
153
|
```bash
|
|
152
|
-
# Point
|
|
154
|
+
# Point Agentic Ledger at your gateway
|
|
153
155
|
AGENTLEDGER_UPSTREAM_URL=http://localhost:4000 uv run python -m agentledger.proxy
|
|
154
156
|
|
|
155
|
-
# Then point your agent at
|
|
157
|
+
# Then point your agent at Agentic Ledger
|
|
156
158
|
client = OpenAI(base_url="http://localhost:8000/v1", ...)
|
|
157
159
|
```
|
|
158
160
|
|
|
@@ -161,10 +163,15 @@ client = OpenAI(base_url="http://localhost:8000/v1", ...)
|
|
|
161
163
|
**Step 3 — Open the dashboard**
|
|
162
164
|
|
|
163
165
|
```
|
|
164
|
-
http://localhost:8000
|
|
166
|
+
http://localhost:8000/app
|
|
165
167
|
```
|
|
166
168
|
|
|
167
|
-
The
|
|
169
|
+
The web app updates live via WebSocket as calls come in. No refresh needed.
|
|
170
|
+
|
|
171
|
+
- **Loop Lens** — every loop run with status (`running` / `flagged` / `complete`), a cost-per-iteration chart, and a per-iteration table (calls, tokens, cache reads, flags, errors)
|
|
172
|
+
- **Sessions** — every session with expandable call cards: response, thinking, tool calls, tool results, cache tokens, cost, loop flags
|
|
173
|
+
|
|
174
|
+
The classic single-file dashboard still lives at `http://localhost:8000`:
|
|
168
175
|
|
|
169
176
|
- **Calls tab** — every LLM call with full prompt, system prompt, tool calls, tool results, output, tokens, cost, latency, and errors
|
|
170
177
|
- **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 +180,69 @@ The dashboard updates live via WebSocket as calls come in. No refresh needed.
|
|
|
173
180
|
|
|
174
181
|
---
|
|
175
182
|
|
|
183
|
+
## Coding agents — Claude Code, Ralph loops & friends
|
|
184
|
+
|
|
185
|
+
Claude Code (and most coding agents) can be pointed at the proxy with a single
|
|
186
|
+
environment variable — no headers, no code changes:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com uv run python -m agentledger.proxy
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
export ANTHROPIC_BASE_URL=http://localhost:8000
|
|
194
|
+
claude
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Agentic Ledger fingerprints Claude Code traffic automatically: every call is
|
|
198
|
+
tagged `framework=claude-code`, and instead of one undifferentiated bucket,
|
|
199
|
+
each Claude Code session appears under its **real session UUID** (the same id
|
|
200
|
+
`claude --resume` shows), with prompt-cache reads/writes captured and priced
|
|
201
|
+
correctly — cache traffic is where most of a coding agent's real spend lives.
|
|
202
|
+
|
|
203
|
+
Running an overnight loop (Ralph-style `while :; do cat PROMPT.md | claude -p; done`)?
|
|
204
|
+
Use the built-in loop runner — it re-executes your command each iteration,
|
|
205
|
+
attributes every call to the run (via the base URL, no headers needed), and
|
|
206
|
+
stops on a completion promise, a budget ceiling, or the iteration cap:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com \
|
|
210
|
+
AGENTLEDGER_COMPLETION_PROMISE="ALL TASKS COMPLETE" \
|
|
211
|
+
uv run python -m agentledger.proxy
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
agentledger run --max-iterations 50 --budget 25 -- \
|
|
216
|
+
claude -p "$(cat PROMPT.md)" --dangerously-skip-permissions
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Each iteration shows up as *iteration N of the run* in `/api/runs`; when the
|
|
220
|
+
agent prints the completion promise in a response, run status flips to
|
|
221
|
+
`complete` and the loop exits with a cost/token summary. Any existing loop
|
|
222
|
+
script works too — poll `GET /api/runs/{run_id}` yourself, or let the proxy's
|
|
223
|
+
budgets (`AGENTLEDGER_BUDGET_DAILY=25.00`) hard-stop a runaway loop.
|
|
224
|
+
|
|
225
|
+
The same recipe works for any client with a base-URL override (Codex CLI,
|
|
226
|
+
opencode, OpenClaw, LiteLLM-based stacks) — set the OpenAI/Anthropic base URL
|
|
227
|
+
to the proxy and traffic is captured; add `x-agentledger-*` headers when you
|
|
228
|
+
want explicit attribution.
|
|
229
|
+
|
|
230
|
+
**OTel-native tools** (Gemini CLI, Codex `[otel]`, AutoGen/AG2, Pydantic AI,
|
|
231
|
+
Vercel AI SDK) don't need the proxy at all — point their OTLP exporter at the
|
|
232
|
+
ledger and GenAI spans are ingested directly:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8000
|
|
236
|
+
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Framework guides:** [BMAD-METHOD](docs/integrations/bmad.md) — persona
|
|
240
|
+
auto-detection (`bmad:sm`, `bmad:dev`, `bmad:qa`, …) and per-story budgets ·
|
|
241
|
+
[OpenClaw](docs/integrations/openclaw.md) — the hard spend cap OpenClaw
|
|
242
|
+
doesn't have, plus per-agent attribution.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
176
246
|
## What gets captured
|
|
177
247
|
|
|
178
248
|
Every LLM call is stored with:
|
|
@@ -192,11 +262,14 @@ Every LLM call is stored with:
|
|
|
192
262
|
| `content` | Model's text output |
|
|
193
263
|
| `stop_reason` | Why the model stopped |
|
|
194
264
|
| `tokens_in` / `tokens_out` | Token usage |
|
|
265
|
+
| `cache_read_tokens` / `cache_write_tokens` | Prompt-cache usage — reads and writes are priced correctly per provider |
|
|
266
|
+
| `thinking` | Extended-thinking output (Anthropic), captured separately from `content` |
|
|
195
267
|
| `cost_usd` | Estimated cost based on model pricing |
|
|
196
268
|
| `latency_ms` | End-to-end response time |
|
|
197
269
|
| `status_code` | HTTP status from upstream — errors are captured too |
|
|
198
270
|
| `error_detail` | Upstream error message for non-200 responses |
|
|
199
|
-
| `agent_name` | From `x-agentledger-agent-name` header |
|
|
271
|
+
| `agent_name` | From `x-agentledger-agent-name` header, or auto-detected (e.g. `claude-code`) |
|
|
272
|
+
| `framework` | From `x-agentledger-framework` header, or fingerprint-detected (e.g. `claude-code`, `litellm`) |
|
|
200
273
|
| `user_id` | From `x-agentledger-user-id` header |
|
|
201
274
|
| `app_id` | From `x-agentledger-app-id` header |
|
|
202
275
|
| `environment` | From `x-agentledger-environment` header |
|
|
@@ -217,13 +290,17 @@ Every LLM call is stored with:
|
|
|
217
290
|
| `GET` | `/` | Live dashboard |
|
|
218
291
|
| `WS` | `/ws` | WebSocket stream — powers live dashboard updates |
|
|
219
292
|
| `GET` | `/api/sessions` | List recent sessions with aggregated stats |
|
|
293
|
+
| `GET` | `/api/runs` | List loop runs (explicit or auto-inferred) with iterations, cost, status, and flagged-call counts |
|
|
294
|
+
| `GET` | `/api/runs/{run_id}` | One run's status (`running` / `flagged` / `complete`) — poll this from loop scripts |
|
|
295
|
+
| `GET` | `/api/sessions/{session_id}/tools` | Derived tool executions — each tool call paired with its result, latency, and error status |
|
|
220
296
|
| `DELETE` | `/api/sessions/{session_id}` | Delete a session and all its calls |
|
|
221
297
|
| `GET` | `/api/search?q=...` | Full-text search across all captured calls |
|
|
222
298
|
| `GET` | `/session/{session_id}` | All calls in a session, ordered by time |
|
|
223
299
|
| `GET` | `/explain/{action_id}` | Single call by action ID |
|
|
224
300
|
| `GET` | `/export/{session_id}` | JSON compliance export with SHA-256 integrity hash |
|
|
225
301
|
| `GET` | `/export/{session_id}/report` | Printable HTML audit report |
|
|
226
|
-
| `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search` |
|
|
302
|
+
| `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search`, `list_runs`, `get_run_status` |
|
|
303
|
+
| `POST` | `/v1/traces` | OTLP/HTTP JSON ingest — GenAI spans from OTel-native tools become ledger calls (`/v1/logs`, `/v1/metrics` acked) |
|
|
227
304
|
|
|
228
305
|
**Examples:**
|
|
229
306
|
```bash
|
|
@@ -244,7 +321,7 @@ open http://localhost:8000/export/run-1/report
|
|
|
244
321
|
|
|
245
322
|
## MCP server
|
|
246
323
|
|
|
247
|
-
|
|
324
|
+
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
325
|
|
|
249
326
|
**Tools available:**
|
|
250
327
|
|
|
@@ -254,6 +331,8 @@ AgentLedger exposes its captured data as an MCP (Model Context Protocol) tool se
|
|
|
254
331
|
| `explain(action_id)` | Full trace for a single LLM call — prompt, tool calls, output, tokens, cost |
|
|
255
332
|
| `get_session(session_id)` | All calls in a session in chronological order |
|
|
256
333
|
| `search(query)` | Full-text search across all captured calls |
|
|
334
|
+
| `list_runs` | Loop runs with iterations, cost, and status |
|
|
335
|
+
| `get_run_status(run_id)` | One run's status — lets an agent inspect its own loop and decide whether to continue |
|
|
257
336
|
|
|
258
337
|
**Configure in `claude_desktop_config.json`:**
|
|
259
338
|
```json
|
|
@@ -300,7 +379,7 @@ Once connected, you can ask your assistant things like:
|
|
|
300
379
|
| `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
380
|
| `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
381
|
| `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. |
|
|
382
|
+
| `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
383
|
| `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
384
|
| `AGENTLEDGER_CAPTURE_QUEUE_MAX` | No | `10000` | Max captures buffered in async mode before load is shed (drops are counted in `/metrics`). |
|
|
306
385
|
| `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 +406,16 @@ Once connected, you can ask your assistant things like:
|
|
|
327
406
|
| `AGENTLEDGER_RATE_LIMIT_AGENT_RPM` | _(none)_ | Max requests per minute per `agent_name`. |
|
|
328
407
|
| `AGENTLEDGER_RATE_LIMIT_USER_RPM` | _(none)_ | Max requests per minute per `user_id`. |
|
|
329
408
|
|
|
409
|
+
**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:
|
|
410
|
+
|
|
411
|
+
| Variable | Default | Description |
|
|
412
|
+
|---|---|---|
|
|
413
|
+
| `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. |
|
|
414
|
+
| `AGENTLEDGER_LOOP_REPEAT_THRESHOLD` | `3` | Consecutive identical tool calls (same tool, same arguments) before a thread is flagged stuck. |
|
|
415
|
+
| `AGENTLEDGER_LOOP_MAX_STEPS` | _(none)_ | Flag (and in block mode, stop) threads that exceed this many ReAct steps. |
|
|
416
|
+
| `AGENTLEDGER_LOOP_RUN_GAP_SECONDS` | `900` | Max gap between fresh-context spawns (same system prompt) that still count as iterations of one run. |
|
|
417
|
+
| `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. |
|
|
418
|
+
|
|
330
419
|
**Alerts** — POST to your webhook when a threshold is breached (does not block calls — see [Alerts](#alerts)):
|
|
331
420
|
|
|
332
421
|
| Variable | Default | Description |
|
|
@@ -417,7 +506,7 @@ curl -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens
|
|
|
417
506
|
curl -X DELETE -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens/<token_id>
|
|
418
507
|
```
|
|
419
508
|
|
|
420
|
-
> Auth is enforced only when `AGENTLEDGER_API_KEY` is set; the master key is the admin bootstrap for minting tokens.
|
|
509
|
+
> 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
510
|
|
|
422
511
|
---
|
|
423
512
|
|
|
@@ -435,6 +524,9 @@ Pass these from your agent on each LLM call. All optional. They enrich captured
|
|
|
435
524
|
| `x-agentledger-environment` | `development` | `production`, `staging`, or `development`. Shown in the dashboard. |
|
|
436
525
|
| `x-agentledger-handoff-from` | _(none)_ | Agent handing off control (e.g. `"orchestrator"`). Renders as a directed edge in the Flow DAG. |
|
|
437
526
|
| `x-agentledger-handoff-to` | _(none)_ | Agent receiving control (e.g. `"researcher"`). Renders as a directed edge in the Flow DAG. |
|
|
527
|
+
| `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). |
|
|
528
|
+
| `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. |
|
|
529
|
+
| `x-agentledger-iteration` | _(auto-inferred)_ | Iteration number within the run. |
|
|
438
530
|
|
|
439
531
|
**Single agent — fully annotated:**
|
|
440
532
|
```python
|
|
@@ -484,7 +576,7 @@ The Flow tab renders `orchestrator → researcher` as a DAG with cost and latenc
|
|
|
484
576
|
|
|
485
577
|
**OpenAI Agents SDK (`openai-agents`) — per-agent clients:**
|
|
486
578
|
|
|
487
|
-
The `openai-agents` SDK uses its own internal OpenAI client. To pass
|
|
579
|
+
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
580
|
|
|
489
581
|
```python
|
|
490
582
|
import uuid
|
|
@@ -498,7 +590,7 @@ BASE_URL = os.getenv("OPENAI_BASE_URL") # e.g. http://localhost:8000/v1
|
|
|
498
590
|
|
|
499
591
|
def al_model(agent_name: str, model: str = "gpt-4o-mini",
|
|
500
592
|
handoff_from: str | None = None, handoff_to: str | None = None):
|
|
501
|
-
"""Create a model instance that sends
|
|
593
|
+
"""Create a model instance that sends Agentic Ledger metadata headers."""
|
|
502
594
|
if not BASE_URL:
|
|
503
595
|
return model # proxy not configured — use default client
|
|
504
596
|
headers = {
|
|
@@ -527,7 +619,7 @@ Each agent's calls are tagged with its name and pipeline position. The Flow tab
|
|
|
527
619
|
|
|
528
620
|
## Alerts
|
|
529
621
|
|
|
530
|
-
|
|
622
|
+
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
623
|
|
|
532
624
|
**Payload format:**
|
|
533
625
|
```json
|
|
@@ -569,7 +661,7 @@ AgentLedger fires a `POST` to your webhook URL when a threshold is breached. You
|
|
|
569
661
|
|
|
570
662
|
## OpenTelemetry export
|
|
571
663
|
|
|
572
|
-
|
|
664
|
+
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
665
|
|
|
574
666
|
**Install the extra** (Docker image includes OTel — no extra step needed when using Docker):
|
|
575
667
|
```bash
|
|
@@ -663,7 +755,7 @@ This runs three jobs:
|
|
|
663
755
|
```
|
|
664
756
|
PyPI project name: agentic-ledger
|
|
665
757
|
Owner: ShekharBhardwaj
|
|
666
|
-
Repository:
|
|
758
|
+
Repository: AgenticLedger
|
|
667
759
|
Workflow name: release.yml
|
|
668
760
|
Environment name: pypi
|
|
669
761
|
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Agentic Ledger
|
|
2
2
|
|
|
3
|
-
[](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/ShekharBhardwaj/AgenticLedger/actions/workflows/codeql.yml)
|
|
5
5
|
[](https://pypi.org/project/agentic-ledger/)
|
|
6
6
|
[](https://pypi.org/project/agentic-ledger/)
|
|
7
7
|
[](https://ghcr.io/shekharbhardwaj/agentledger)
|
|
@@ -9,16 +9,18 @@
|
|
|
9
9
|
|
|
10
10
|
Runtime observability for AI agents — see exactly what your agent did, why it did it, and what it cost.
|
|
11
11
|
|
|
12
|
+
> **Alpha** — `v0.3.0-alpha.1` is an early release of the loop engine, Loop Lens web app, and framework integrations. Interfaces and schema may still change between alpha releases. Found something broken or missing? [Open an issue](https://github.com/ShekharBhardwaj/AgenticLedger/issues/new/choose) — alpha feedback directly shapes what ships next.
|
|
13
|
+
|
|
12
14
|
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.
|
|
13
15
|
|
|
14
16
|
---
|
|
15
17
|
|
|
16
18
|
## How it works
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
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.
|
|
19
21
|
|
|
20
22
|
```
|
|
21
|
-
Your Agent →
|
|
23
|
+
Your Agent → Agentic Ledger Proxy → OpenAI / Anthropic / LiteLLM / any LLM
|
|
22
24
|
↓
|
|
23
25
|
SQLite or Postgres
|
|
24
26
|
↓
|
|
@@ -107,10 +109,10 @@ client = anthropic.Anthropic(
|
|
|
107
109
|
|
|
108
110
|
**LiteLLM / OpenRouter / any gateway:**
|
|
109
111
|
```bash
|
|
110
|
-
# Point
|
|
112
|
+
# Point Agentic Ledger at your gateway
|
|
111
113
|
AGENTLEDGER_UPSTREAM_URL=http://localhost:4000 uv run python -m agentledger.proxy
|
|
112
114
|
|
|
113
|
-
# Then point your agent at
|
|
115
|
+
# Then point your agent at Agentic Ledger
|
|
114
116
|
client = OpenAI(base_url="http://localhost:8000/v1", ...)
|
|
115
117
|
```
|
|
116
118
|
|
|
@@ -119,10 +121,15 @@ client = OpenAI(base_url="http://localhost:8000/v1", ...)
|
|
|
119
121
|
**Step 3 — Open the dashboard**
|
|
120
122
|
|
|
121
123
|
```
|
|
122
|
-
http://localhost:8000
|
|
124
|
+
http://localhost:8000/app
|
|
123
125
|
```
|
|
124
126
|
|
|
125
|
-
The
|
|
127
|
+
The web app updates live via WebSocket as calls come in. No refresh needed.
|
|
128
|
+
|
|
129
|
+
- **Loop Lens** — every loop run with status (`running` / `flagged` / `complete`), a cost-per-iteration chart, and a per-iteration table (calls, tokens, cache reads, flags, errors)
|
|
130
|
+
- **Sessions** — every session with expandable call cards: response, thinking, tool calls, tool results, cache tokens, cost, loop flags
|
|
131
|
+
|
|
132
|
+
The classic single-file dashboard still lives at `http://localhost:8000`:
|
|
126
133
|
|
|
127
134
|
- **Calls tab** — every LLM call with full prompt, system prompt, tool calls, tool results, output, tokens, cost, latency, and errors
|
|
128
135
|
- **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.
|
|
@@ -131,6 +138,69 @@ The dashboard updates live via WebSocket as calls come in. No refresh needed.
|
|
|
131
138
|
|
|
132
139
|
---
|
|
133
140
|
|
|
141
|
+
## Coding agents — Claude Code, Ralph loops & friends
|
|
142
|
+
|
|
143
|
+
Claude Code (and most coding agents) can be pointed at the proxy with a single
|
|
144
|
+
environment variable — no headers, no code changes:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com uv run python -m agentledger.proxy
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
export ANTHROPIC_BASE_URL=http://localhost:8000
|
|
152
|
+
claude
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Agentic Ledger fingerprints Claude Code traffic automatically: every call is
|
|
156
|
+
tagged `framework=claude-code`, and instead of one undifferentiated bucket,
|
|
157
|
+
each Claude Code session appears under its **real session UUID** (the same id
|
|
158
|
+
`claude --resume` shows), with prompt-cache reads/writes captured and priced
|
|
159
|
+
correctly — cache traffic is where most of a coding agent's real spend lives.
|
|
160
|
+
|
|
161
|
+
Running an overnight loop (Ralph-style `while :; do cat PROMPT.md | claude -p; done`)?
|
|
162
|
+
Use the built-in loop runner — it re-executes your command each iteration,
|
|
163
|
+
attributes every call to the run (via the base URL, no headers needed), and
|
|
164
|
+
stops on a completion promise, a budget ceiling, or the iteration cap:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
AGENTLEDGER_UPSTREAM_URL=https://api.anthropic.com \
|
|
168
|
+
AGENTLEDGER_COMPLETION_PROMISE="ALL TASKS COMPLETE" \
|
|
169
|
+
uv run python -m agentledger.proxy
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
agentledger run --max-iterations 50 --budget 25 -- \
|
|
174
|
+
claude -p "$(cat PROMPT.md)" --dangerously-skip-permissions
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Each iteration shows up as *iteration N of the run* in `/api/runs`; when the
|
|
178
|
+
agent prints the completion promise in a response, run status flips to
|
|
179
|
+
`complete` and the loop exits with a cost/token summary. Any existing loop
|
|
180
|
+
script works too — poll `GET /api/runs/{run_id}` yourself, or let the proxy's
|
|
181
|
+
budgets (`AGENTLEDGER_BUDGET_DAILY=25.00`) hard-stop a runaway loop.
|
|
182
|
+
|
|
183
|
+
The same recipe works for any client with a base-URL override (Codex CLI,
|
|
184
|
+
opencode, OpenClaw, LiteLLM-based stacks) — set the OpenAI/Anthropic base URL
|
|
185
|
+
to the proxy and traffic is captured; add `x-agentledger-*` headers when you
|
|
186
|
+
want explicit attribution.
|
|
187
|
+
|
|
188
|
+
**OTel-native tools** (Gemini CLI, Codex `[otel]`, AutoGen/AG2, Pydantic AI,
|
|
189
|
+
Vercel AI SDK) don't need the proxy at all — point their OTLP exporter at the
|
|
190
|
+
ledger and GenAI spans are ingested directly:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8000
|
|
194
|
+
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Framework guides:** [BMAD-METHOD](docs/integrations/bmad.md) — persona
|
|
198
|
+
auto-detection (`bmad:sm`, `bmad:dev`, `bmad:qa`, …) and per-story budgets ·
|
|
199
|
+
[OpenClaw](docs/integrations/openclaw.md) — the hard spend cap OpenClaw
|
|
200
|
+
doesn't have, plus per-agent attribution.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
134
204
|
## What gets captured
|
|
135
205
|
|
|
136
206
|
Every LLM call is stored with:
|
|
@@ -150,11 +220,14 @@ Every LLM call is stored with:
|
|
|
150
220
|
| `content` | Model's text output |
|
|
151
221
|
| `stop_reason` | Why the model stopped |
|
|
152
222
|
| `tokens_in` / `tokens_out` | Token usage |
|
|
223
|
+
| `cache_read_tokens` / `cache_write_tokens` | Prompt-cache usage — reads and writes are priced correctly per provider |
|
|
224
|
+
| `thinking` | Extended-thinking output (Anthropic), captured separately from `content` |
|
|
153
225
|
| `cost_usd` | Estimated cost based on model pricing |
|
|
154
226
|
| `latency_ms` | End-to-end response time |
|
|
155
227
|
| `status_code` | HTTP status from upstream — errors are captured too |
|
|
156
228
|
| `error_detail` | Upstream error message for non-200 responses |
|
|
157
|
-
| `agent_name` | From `x-agentledger-agent-name` header |
|
|
229
|
+
| `agent_name` | From `x-agentledger-agent-name` header, or auto-detected (e.g. `claude-code`) |
|
|
230
|
+
| `framework` | From `x-agentledger-framework` header, or fingerprint-detected (e.g. `claude-code`, `litellm`) |
|
|
158
231
|
| `user_id` | From `x-agentledger-user-id` header |
|
|
159
232
|
| `app_id` | From `x-agentledger-app-id` header |
|
|
160
233
|
| `environment` | From `x-agentledger-environment` header |
|
|
@@ -175,13 +248,17 @@ Every LLM call is stored with:
|
|
|
175
248
|
| `GET` | `/` | Live dashboard |
|
|
176
249
|
| `WS` | `/ws` | WebSocket stream — powers live dashboard updates |
|
|
177
250
|
| `GET` | `/api/sessions` | List recent sessions with aggregated stats |
|
|
251
|
+
| `GET` | `/api/runs` | List loop runs (explicit or auto-inferred) with iterations, cost, status, and flagged-call counts |
|
|
252
|
+
| `GET` | `/api/runs/{run_id}` | One run's status (`running` / `flagged` / `complete`) — poll this from loop scripts |
|
|
253
|
+
| `GET` | `/api/sessions/{session_id}/tools` | Derived tool executions — each tool call paired with its result, latency, and error status |
|
|
178
254
|
| `DELETE` | `/api/sessions/{session_id}` | Delete a session and all its calls |
|
|
179
255
|
| `GET` | `/api/search?q=...` | Full-text search across all captured calls |
|
|
180
256
|
| `GET` | `/session/{session_id}` | All calls in a session, ordered by time |
|
|
181
257
|
| `GET` | `/explain/{action_id}` | Single call by action ID |
|
|
182
258
|
| `GET` | `/export/{session_id}` | JSON compliance export with SHA-256 integrity hash |
|
|
183
259
|
| `GET` | `/export/{session_id}/report` | Printable HTML audit report |
|
|
184
|
-
| `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search` |
|
|
260
|
+
| `POST` | `/mcp` | MCP tool server — `list_sessions`, `explain`, `get_session`, `search`, `list_runs`, `get_run_status` |
|
|
261
|
+
| `POST` | `/v1/traces` | OTLP/HTTP JSON ingest — GenAI spans from OTel-native tools become ledger calls (`/v1/logs`, `/v1/metrics` acked) |
|
|
185
262
|
|
|
186
263
|
**Examples:**
|
|
187
264
|
```bash
|
|
@@ -202,7 +279,7 @@ open http://localhost:8000/export/run-1/report
|
|
|
202
279
|
|
|
203
280
|
## MCP server
|
|
204
281
|
|
|
205
|
-
|
|
282
|
+
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.
|
|
206
283
|
|
|
207
284
|
**Tools available:**
|
|
208
285
|
|
|
@@ -212,6 +289,8 @@ AgentLedger exposes its captured data as an MCP (Model Context Protocol) tool se
|
|
|
212
289
|
| `explain(action_id)` | Full trace for a single LLM call — prompt, tool calls, output, tokens, cost |
|
|
213
290
|
| `get_session(session_id)` | All calls in a session in chronological order |
|
|
214
291
|
| `search(query)` | Full-text search across all captured calls |
|
|
292
|
+
| `list_runs` | Loop runs with iterations, cost, and status |
|
|
293
|
+
| `get_run_status(run_id)` | One run's status — lets an agent inspect its own loop and decide whether to continue |
|
|
215
294
|
|
|
216
295
|
**Configure in `claude_desktop_config.json`:**
|
|
217
296
|
```json
|
|
@@ -258,7 +337,7 @@ Once connected, you can ask your assistant things like:
|
|
|
258
337
|
| `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. |
|
|
259
338
|
| `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. |
|
|
260
339
|
| `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. |
|
|
261
|
-
| `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. |
|
|
340
|
+
| `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. |
|
|
262
341
|
| `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. |
|
|
263
342
|
| `AGENTLEDGER_CAPTURE_QUEUE_MAX` | No | `10000` | Max captures buffered in async mode before load is shed (drops are counted in `/metrics`). |
|
|
264
343
|
| `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. |
|
|
@@ -285,6 +364,16 @@ Once connected, you can ask your assistant things like:
|
|
|
285
364
|
| `AGENTLEDGER_RATE_LIMIT_AGENT_RPM` | _(none)_ | Max requests per minute per `agent_name`. |
|
|
286
365
|
| `AGENTLEDGER_RATE_LIMIT_USER_RPM` | _(none)_ | Max requests per minute per `user_id`. |
|
|
287
366
|
|
|
367
|
+
**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:
|
|
368
|
+
|
|
369
|
+
| Variable | Default | Description |
|
|
370
|
+
|---|---|---|
|
|
371
|
+
| `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. |
|
|
372
|
+
| `AGENTLEDGER_LOOP_REPEAT_THRESHOLD` | `3` | Consecutive identical tool calls (same tool, same arguments) before a thread is flagged stuck. |
|
|
373
|
+
| `AGENTLEDGER_LOOP_MAX_STEPS` | _(none)_ | Flag (and in block mode, stop) threads that exceed this many ReAct steps. |
|
|
374
|
+
| `AGENTLEDGER_LOOP_RUN_GAP_SECONDS` | `900` | Max gap between fresh-context spawns (same system prompt) that still count as iterations of one run. |
|
|
375
|
+
| `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. |
|
|
376
|
+
|
|
288
377
|
**Alerts** — POST to your webhook when a threshold is breached (does not block calls — see [Alerts](#alerts)):
|
|
289
378
|
|
|
290
379
|
| Variable | Default | Description |
|
|
@@ -375,7 +464,7 @@ curl -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens
|
|
|
375
464
|
curl -X DELETE -H "x-agentledger-api-key: my-secret" http://localhost:8000/api/tokens/<token_id>
|
|
376
465
|
```
|
|
377
466
|
|
|
378
|
-
> Auth is enforced only when `AGENTLEDGER_API_KEY` is set; the master key is the admin bootstrap for minting tokens.
|
|
467
|
+
> 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.
|
|
379
468
|
|
|
380
469
|
---
|
|
381
470
|
|
|
@@ -393,6 +482,9 @@ Pass these from your agent on each LLM call. All optional. They enrich captured
|
|
|
393
482
|
| `x-agentledger-environment` | `development` | `production`, `staging`, or `development`. Shown in the dashboard. |
|
|
394
483
|
| `x-agentledger-handoff-from` | _(none)_ | Agent handing off control (e.g. `"orchestrator"`). Renders as a directed edge in the Flow DAG. |
|
|
395
484
|
| `x-agentledger-handoff-to` | _(none)_ | Agent receiving control (e.g. `"researcher"`). Renders as a directed edge in the Flow DAG. |
|
|
485
|
+
| `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). |
|
|
486
|
+
| `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. |
|
|
487
|
+
| `x-agentledger-iteration` | _(auto-inferred)_ | Iteration number within the run. |
|
|
396
488
|
|
|
397
489
|
**Single agent — fully annotated:**
|
|
398
490
|
```python
|
|
@@ -442,7 +534,7 @@ The Flow tab renders `orchestrator → researcher` as a DAG with cost and latenc
|
|
|
442
534
|
|
|
443
535
|
**OpenAI Agents SDK (`openai-agents`) — per-agent clients:**
|
|
444
536
|
|
|
445
|
-
The `openai-agents` SDK uses its own internal OpenAI client. To pass
|
|
537
|
+
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`.
|
|
446
538
|
|
|
447
539
|
```python
|
|
448
540
|
import uuid
|
|
@@ -456,7 +548,7 @@ BASE_URL = os.getenv("OPENAI_BASE_URL") # e.g. http://localhost:8000/v1
|
|
|
456
548
|
|
|
457
549
|
def al_model(agent_name: str, model: str = "gpt-4o-mini",
|
|
458
550
|
handoff_from: str | None = None, handoff_to: str | None = None):
|
|
459
|
-
"""Create a model instance that sends
|
|
551
|
+
"""Create a model instance that sends Agentic Ledger metadata headers."""
|
|
460
552
|
if not BASE_URL:
|
|
461
553
|
return model # proxy not configured — use default client
|
|
462
554
|
headers = {
|
|
@@ -485,7 +577,7 @@ Each agent's calls are tagged with its name and pipeline position. The Flow tab
|
|
|
485
577
|
|
|
486
578
|
## Alerts
|
|
487
579
|
|
|
488
|
-
|
|
580
|
+
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.
|
|
489
581
|
|
|
490
582
|
**Payload format:**
|
|
491
583
|
```json
|
|
@@ -527,7 +619,7 @@ AgentLedger fires a `POST` to your webhook URL when a threshold is breached. You
|
|
|
527
619
|
|
|
528
620
|
## OpenTelemetry export
|
|
529
621
|
|
|
530
|
-
|
|
622
|
+
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.
|
|
531
623
|
|
|
532
624
|
**Install the extra** (Docker image includes OTel — no extra step needed when using Docker):
|
|
533
625
|
```bash
|
|
@@ -621,7 +713,7 @@ This runs three jobs:
|
|
|
621
713
|
```
|
|
622
714
|
PyPI project name: agentic-ledger
|
|
623
715
|
Owner: ShekharBhardwaj
|
|
624
|
-
Repository:
|
|
716
|
+
Repository: AgenticLedger
|
|
625
717
|
Workflow name: release.yml
|
|
626
718
|
Environment name: pypi
|
|
627
719
|
```
|