<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: entradox</title>
    <description>The latest articles on DEV Community by entradox (@entradox).</description>
    <link>https://dev.to/entradox</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4124817%2Fe3c58261-684d-498e-9cc2-19ed5c2a1e45.png</url>
      <title>DEV Community: entradox</title>
      <link>https://dev.to/entradox</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/entradox"/>
    <language>en</language>
    <item>
      <title>Per-agent cost attribution: how I put a hard spending cap on every AI agent I run</title>
      <dc:creator>entradox</dc:creator>
      <pubDate>Mon, 14 Sep 2026 15:55:54 +0000</pubDate>
      <link>https://dev.to/entradox/per-agent-cost-attribution-how-i-put-a-hard-spending-cap-on-every-ai-agent-i-run-4g18</link>
      <guid>https://dev.to/entradox/per-agent-cost-attribution-how-i-put-a-hard-spending-cap-on-every-ai-agent-i-run-4g18</guid>
      <description>&lt;p&gt;If you run more than a couple of AI agents, the token bill arrives and you can't answer the one question that actually matters: which agent burned the money? Trace viewers (Langfuse, LangSmith,Helicone) show you every request after the fact.&lt;/p&gt;

&lt;p&gt;Some of them do have enforcement. Helicone has cost-based rate limits and can return a 429 before the request goes out. Portkey's gateway has per-key Budget Limits that expire the key when a USD or token ceiling is reached, and returns a 412 Budget exhausted. MLflow's AI Gateway has budget policies that c a block a request. So "observability can't stop anything" would be too strong, and I'm not going to pretend otherwise.&lt;/p&gt;

&lt;p&gt;What I wanted was narrower: a spending limit per agent, enforced before the provider is contacted, where the cap is the primary object rather than a rate-limit side effect. Not an alert. A refusal.&lt;/p&gt;

&lt;p&gt;The design&lt;/p&gt;

&lt;p&gt;The unit of accounting is the agent id, not the trace. Every LLM call gets metered against that agent's ledger.&lt;/p&gt;

&lt;p&gt;Meter. Record the model, the input tokens and the output tokens per call. Cost is computed from the provider's own reported usage with cache-aware pricing. Anthropic bills input at four different rates depending on cache state, so a flat rate gets it badly wrong. On one Claude Code session I priced the same tokens two ways. Every input token at the flat list rate came to $112.85. Priced against Anthropic's actual tiers (fresh input at 1x, 5-minute cache write at&lt;/p&gt;

&lt;p&gt;1.25x, 1-hour cache write at 2x, cache read at 0.1x), the same session is $15.22. Same tokens,&lt;/p&gt;

&lt;p&gt;7.4x, and the entire difference is the cost model. The price table ships with a source URL and&lt;/p&gt;

&lt;p&gt;an as-of date per model, so you can check the arithmetic rather than trust mine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/v1/pricing" rel="noopener noreferrer"&gt;https://aiagentscity.com/v1/pricing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check. Before the call goes to the provider, estimate its maximum cost and compare it against the agent's remaining budget.&lt;/p&gt;

&lt;p&gt;Refuse. If it would cross the cap, return 402 Payment Required and never contact the provider.&lt;/p&gt;

&lt;p&gt;Through the proxy or the wrapper, the money is not spent.&lt;/p&gt;

&lt;p&gt;The honest caveat&lt;/p&gt;

&lt;p&gt;This only works if the traffic actually flows through the enforcement point. That is a proxy (your client points at a different base URL) or a one-line Python wrapper. The wrapper is the extra on the Python package. It repoints an SDK you already use, adds two headers, and subclasses nothing. Anthropic's client works the same way.&lt;/p&gt;

&lt;p&gt;Traffic that bypasses the proxy is outside anyone's reach. That is true of every gateway-based approach, not just this one. AgentLedger holds no provider key. The credential rides in the request headers, is forwarded, and is never written to disk. Nothing here claims a bypass is impossible.&lt;/p&gt;

&lt;p&gt;What a blocked call looks like&lt;br&gt;
You point a client at the proxy, and it gets a 402 Payment Required back. The body is a typed error envelope where the error type is the HTTP-level class ("budget_error") and the code is the specific reason ("budget_exceeded"). The message names the model, the estimated maximum cost of the call in cents, the agent, and the cap it would have crossed. It ends with the only sentence that matters: nothing was sent upstream. The provider never saw the request.&lt;/p&gt;

&lt;p&gt;The error envelope is shared by every REST and MCP error response, so both surfaces agree on shape. The full contract, in prose:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/llms.txt" rel="noopener noreferrer"&gt;https://aiagentscity.com/llms.txt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The OpenAPI 3 schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/openapi.json" rel="noopener noreferrer"&gt;https://aiagentscity.com/openapi.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alerts and reports&lt;br&gt;
Caps alone aren't enough. You want to know before the block.&lt;/p&gt;

&lt;p&gt;A webhook fires at 80% of budget, on cap cross, and on spending anomalies. You register the destination in the API, and the delivery-receipts endpoint returns successes and failures, so a dropped alert is visible rather than silent.&lt;/p&gt;

&lt;p&gt;Per-agent P&amp;amp;L: totals, by rail, by service, budget status, anomalies.&lt;/p&gt;

&lt;p&gt;Read-only report links, HMAC-signed and expiring (7 days by default, 90 at most), and revocable in bulk by bumping the agent's share epoch. Anyone holding the URL can read that one agent's report until it expires. It can't write, and it can't read any other agent.&lt;/p&gt;

&lt;p&gt;Webhook payloads carry cost metadata only: an agent id, a number, a model name. Never a secret,a prompt, or a response.&lt;/p&gt;

&lt;p&gt;Two things that surprise people&lt;br&gt;
A dollar cap does not protect a token-metered agent. If an agent runs on a flat-rate or subscription arrangement, there is no per-call dollar amount to record, so a dollar cap measures&lt;/p&gt;

&lt;p&gt;zero on every call and never fires. Not a misconfiguration. The quantity it measures is zero.&lt;/p&gt;

&lt;p&gt;Dollar caps cover the non-token rails; token caps cover token rows. They are independent, and a token-metered agent needs its own token cap.&lt;/p&gt;

&lt;p&gt;Collapsing tokens into a dollar estimate reintroduces the problem it was meant to solve: a cheap model looping burns tokens at roughly zero dollars, and an expensive model burns dollars at a perfectly sane token count. The two runaway modes hide each other. Convert one into the other early and you can see neither.&lt;/p&gt;

&lt;p&gt;An unpriced model is never blocked. The call passes through and an alert fires instead, because a silent zero would read as "this agent spends nothing."&lt;/p&gt;

&lt;p&gt;An agent can open its own ledger&lt;br&gt;
The workspace path needs no signup, no login, and no card. One press mints a workspace key, and an agent can do it with no handoff. A small mechanical fact with a real consequence: the thing that spends the money can be the thing that accounts for it. An accounting tool that assumes a person in the loop at setup time cannot be adopted by the party doing the spending.&lt;/p&gt;

&lt;p&gt;What it does not do&lt;/p&gt;

&lt;p&gt;Two enforcement mechanisms, and the difference matters.&lt;/p&gt;

&lt;p&gt;Through the proxy or the wrapper, the call is refused before the provider is contacted, so the spend genuinely does not happen.&lt;/p&gt;

&lt;p&gt;Through the plain API (the track endpoint, which is what the CLI track command and a direct HTTP call produce), the ledger write that would cross the cap is rejected. Recording stops. The charge, if your agent already made it, does not.&lt;/p&gt;

&lt;p&gt;The boundary, in the product's own words.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/security" rel="noopener noreferrer"&gt;https://aiagentscity.com/security&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Where to find it&lt;br&gt;
Every line below is a real destination, and each URL is the last thing on its line.&lt;/p&gt;

&lt;p&gt;START HERE&lt;/p&gt;

&lt;p&gt;The product front door&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com" rel="noopener noreferrer"&gt;https://aiagentscity.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get a workspace, no signup, no login, no card&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/start" rel="noopener noreferrer"&gt;https://aiagentscity.com/start&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The three ways in&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/quickstart" rel="noopener noreferrer"&gt;https://aiagentscity.com/quickstart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste a workspace key, see every agent on one page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/dashboard" rel="noopener noreferrer"&gt;https://aiagentscity.com/dashboard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;INSTALL AND SOURCE&lt;/p&gt;

&lt;p&gt;Python package, with the wrapper extra&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/aiagentscity-ledger/" rel="noopener noreferrer"&gt;https://pypi.org/project/aiagentscity-ledger/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Node package, no clone&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/aiagentscity-ledger" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/aiagentscity-ledger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source code&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/entradox/agent-ledger" rel="noopener noreferrer"&gt;https://github.com/entradox/agent-ledger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FOR AGENTS&lt;/p&gt;

&lt;p&gt;The full API contract in prose. Start here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/llms.txt" rel="noopener noreferrer"&gt;https://aiagentscity.com/llms.txt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenAPI 3 schema&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/openapi.json" rel="noopener noreferrer"&gt;https://aiagentscity.com/openapi.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MCP manifest&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/server.json" rel="noopener noreferrer"&gt;https://aiagentscity.com/server.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Capability, auth and pricing manifest&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/.well-known/agent.json" rel="noopener noreferrer"&gt;https://aiagentscity.com/.well-known/agent.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MCP streamable-HTTP endpoint, nine tools: track, set budget, report, alerts, list agents, API docs, examples, rotate secret, revoke secret&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/mcp/" rel="noopener noreferrer"&gt;https://aiagentscity.com/mcp/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MORE&lt;/p&gt;

&lt;p&gt;The enforcement boundary&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/security" rel="noopener noreferrer"&gt;https://aiagentscity.com/security&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comparison&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/compare" rel="noopener noreferrer"&gt;https://aiagentscity.com/compare&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Who operates it&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/about" rel="noopener noreferrer"&gt;https://aiagentscity.com/about&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Live uptime and version&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/status" rel="noopener noreferrer"&gt;https://aiagentscity.com/status&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Live counters&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/st" rel="noopener noreferrer"&gt;https://aiagentscity.com/st&lt;/a&gt; ats&lt;/p&gt;

&lt;p&gt;Terms&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/terms" rel="noopener noreferrer"&gt;https://aiagentscity.com/terms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Privacy&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/privacy" rel="noopener noreferrer"&gt;https://aiagentscity.com/privacy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it&lt;br&gt;
Free tier covers 3 agents per workspace with every feature, no signup and no card. Past 3 agents,&lt;/p&gt;

&lt;p&gt;Pro is $19/mo for unlimited tracked agents, same workspace and same key. Upgrading from a workspace you already hold goes through the checkout endpoint, which returns a payment link bound to your workspace rather than a b are link that would charge you and leave you capped.&lt;/p&gt;

&lt;p&gt;Current version 0.4.1, active in the official MCP registry as io.github.entradox/agent-ledger, with nine tools. If you only read one thing, read this. An agent can understand the credential model and start tracking without a human reading a line of documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiagentscity.com/llms.txt" rel="noopener noreferrer"&gt;https://aiagentscity.com/llms.txt&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
