Blog

How to track AI agent costs per run (with LangGraph and n8n examples)

7 min readLeanroute Team

Ask a team running AI agents what one task costs and you usually get a monthly total and a shrug. The provider bill says how much you spent on each model. It doesn't say that the research agent's Tuesday run cost $4.10 because it called the same failing tool 31 times.

Agents make that question hard. A single task can be five model calls or fifty, across two or three models, with tool calls in between. Per-request logs are too fine to read, and per-model totals are too coarse to act on. The unit you want is the run: everything an agent did to finish one task.

This post shows how to get cost per run in practice, with LangGraph and n8n examples, and what to do with the numbers once you have them.

What a run is

A run is every model call that belongs to one task. The simplest way to define it is with an id: the agent picks one when the task starts and sends it with every call until the task is done. Anything with the same id is the same run.

That id needs to travel with each request to wherever the cost is recorded. You can do this in your own code (wrap every model call, look up prices, sum them per id), in a tracing tool through callbacks, or at the gateway that every request already passes through. This post uses the gateway approach, because it works the same way for every framework and language, and the same place can also enforce limits. The ideas carry over if you build it yourself.

Step 1: name the agent and give each run an id

Leanroute reads two headers:

Header What it means If you leave it out
X-Agent-Name Which agent sent the request, for example support-bot The API key's name is used
X-Agent-Session-Id Which run the request belongs to. One id per run; a UUID works The request isn't part of any run
X-Agent-Id Optional: a subagent within the run Not recorded

Every request with the same X-Agent-Session-Id becomes one run, with its total cost, the models it used, how long it took, how many requests failed and every tool that was called. There's no "start run" or "end run" call: a run begins with its first request and ends with its last.

Two rules save you trouble later:

  • One id per task, not per user or per day. If every request from a user shares an id, you've built a per-user total, not a run.
  • No personal data in names or ids. They show up in dashboards. Use support-bot and a UUID, not someone's email address.

Step 2: LangGraph

In LangGraph the model object carries the headers, so create one chat model per run. The langchain-leanroute package (PyPI) does this for you: ChatLeanroute is LangChain's ChatOpenAI with the Leanroute base URL built in and two extra arguments for the agent name and run id.

pip install langchain-leanroute langgraph
export LEANROUTE_API_KEY=gw_live_...
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
from langchain_leanroute import ChatLeanroute, new_run_id


@tool
def lookup_order(order_id: str) -> str:
    """Return the status of an order."""
    return f"Order {order_id}: shipped"


def handle_ticket(question: str) -> str:
    llm = ChatLeanroute(
        model="deepseek/deepseek-v4-1-flash",
        agent_name="support-bot",
        session_id=new_run_id(),  # one id per task
    )
    agent = create_react_agent(llm, tools=[lookup_order])
    result = agent.invoke({"messages": [("user", question)]})
    return result["messages"][-1].content


print(handle_ticket("Where is order 1042?"))

Prefer plain ChatOpenAI? It works the same: set base_url="https://api.leanroute.dev/v1" and pass X-Agent-Name and X-Agent-Session-Id in default_headers.

Every call the agent makes while handling that ticket, including the ones after each tool result, carries the same run id. The lookup_order call shows up on the run too: the gateway records the tools the model asked your agent to run (names only, never arguments or results).

If a graph has several specialised nodes, give them the same X-Agent-Session-Id and a different X-Agent-Id each (the agent_id argument in ChatLeanroute, for example planner and writer), so you can see which part of the run spent the money.

Step 3: n8n

In n8n there's nothing to code. The Leanroute Chat Model node (community package n8n-nodes-leanroute, version 0.1.7 or later) treats each workflow execution as a run and names it after the workflow. Add it as the chat model for an AI Agent node and every execution shows up as its own run.

The node's options let you override that:

  • Agent Name to use a fixed name instead of the workflow name.
  • Run ID to group calls differently, for example by an id from the trigger.
  • Disable Agent Run Tracking to turn it off for a workflow.

This is useful for the most common n8n question: which workflow costs the most. Each execution is a run, and the agent name is the workflow name.

Step 4: read the cost

Once requests carry the headers, there are three places to see cost.

The Agent runs page in the dashboard lists runs per agent with cost, models, duration and top tools. Each run opens into every request and tool call it made.

The API, with an admin key (gw_admin_*), for reports or your own dashboards:

curl "https://api.leanroute.dev/platform/v1/runs?agent=support-bot" \
  -H "Authorization: Bearer $LEANROUTE_ADMIN_KEY"

Each run in the response looks like this:

{
  "session_id": "7f3c9a2e-0b1d-4c55-9e1a-3a8f2d6b4c10",
  "agent_names": ["support-bot"],
  "started_at": "2026-11-06T03:12:08.000Z",
  "last_seen_at": "2026-11-06T03:12:41.000Z",
  "requests": 6,
  "errors": 0,
  "cost_usd": "0.004120",
  "input_tokens": 18240,
  "output_tokens": 1630,
  "models": ["deepseek/deepseek-v4-1-flash"],
  "tool_calls": 3
}

GET /platform/v1/runs/{session_id} returns one run with every request and a per-tool rollup. The list takes from, to, agent, limit and before for paging, up to 90 days at a time.

Each response, for live checks inside the agent: on non-streaming calls, the x-gateway-cost-usd header carries the cost of that one call, so an agent can keep a running total for its own run.

Step 5: act on it

Cost per run is only worth having if it changes something. Here's what to look for.

Sort runs by cost. Agent spend is rarely even. Typically a small share of runs accounts for a large share of the cost, and they have a cause you can fix.

Compare requests per run. A run with 40 requests when most have 6 is usually a loop: a tool that keeps failing, a model that never decides it's done, or a retry with no limit. Look at that run's tool list. A tool with many calls and many failures is the usual suspect.

Watch input tokens. Agents re-send the conversation on every step, so input tokens grow with each turn. If input tokens dwarf output tokens, trim the history you send or summarise older turns.

Check the model mix. If a premium model is doing routine steps like classifying, extracting or formatting, move those steps to a cheaper model and keep the premium one for the hard part. The run view shows which models each run used.

Cap each agent. Give every agent its own API key and set daily and monthly spend caps on it. A runaway agent then stops at its own limit instead of eating the budget for everything else. When a cap is reached, the next request gets HTTP 402 spend_cap_exceeded, so the agent can stop cleanly. There's more on this in spend caps and rate limits.

What this doesn't do (yet)

  • No hard budget per run. You can see each run's cost and cap the agent's key per day or month, but you can't yet say "stop this run at $0.50". An agent can enforce that itself by adding up the x-gateway-cost-usd header on its calls.
  • Costs are at catalog prices. On your own provider keys, the provider's invoice is the final word and can differ slightly, for example with discounts you've negotiated.
  • The gateway sees model calls, not your code. Time spent in your own tools or a database doesn't show up, only the model calls and the tool names the model requested.

Summary

To track AI agent costs per run:

  1. Pick a run id when a task starts and send it with every model call, plus the agent's name.
  2. In LangGraph, create one chat model per run with the two headers. In n8n, use the Leanroute Chat Model node and each execution is a run.
  3. Read cost per run in the dashboard or from GET /platform/v1/runs.
  4. Sort by cost, look for loops and bloated context, move routine steps to cheaper models, and cap each agent's key.

The full header reference and recipes for the OpenAI SDK, Vercel AI SDK and Claude Code are in the agent runs docs. For the controls side, see agent control and AI cost control. New accounts get 100 free requests on low-cost models, no card needed, which is enough to try it on a real agent.

Frequently asked questions

How do I track the cost of an AI agent run?
Give every model call in a run the same run id and record the cost of each call against it. With Leanroute you send two headers, X-Agent-Name and X-Agent-Session-Id, and the gateway groups the calls into runs with total cost, models used and tools called, in the dashboard and through GET /platform/v1/runs.
Why is my AI agent so expensive?
Usually a few runs cost far more than the rest: a loop that retries a failing tool, a long conversation re-sent on every step, or a premium model doing work a cheaper one could do. Cost per run, sorted, finds them; per-model totals hide them.
Can I set a budget per agent?
Yes, per agent: give each agent its own API key with daily and monthly spend caps. Leanroute doesn't have a hard budget per individual run yet; you can see each run's cost and cap the agent's key.
Does this work with LangGraph and n8n?
Yes. In LangGraph, set the two headers on the chat model you create for each run. In n8n, the Leanroute Chat Model node treats each workflow execution as a run automatically.
AI agentsAgent cost trackingLLM costLangGraphn8nFinOpsAI Gateway