Skip to content
AgentDock

Using AgentDock

Usage, cost and budgets

API-equivalent cost per run, model and project, and limits that stop new spend.

AgentDock records the tokens of every LLM request your agents make and prices them, so you can see spend per run, model, project, issue and slot. Budgets then put a limit on that spend and refuse new work when it is used up.

API-equivalent cost, not a bill

AgentDock does not bill anything and takes no payments. Every dollar figure is API-equivalent cost: what the recorded tokens would cost at public API prices, even when your agents run on a Claude or ChatGPT subscription. It is the one number you can compare across runtimes, models and months. Your actual invoice comes from your provider.

What is recorded

Each LLM request is stored with its model, duration, stop reason and token counts in six buckets. Every token is in exactly one bucket:

BucketMeaning
inputUncached input tokens
outputOutput tokens
cacheReadInput tokens read from the prompt cache
cacheWrite5mTokens written to the 5-minute cache
cacheWrite1hTokens written to the 1-hour cache
reasoningThinking tokens. These are part of output and never counted twice

Only metadata is stored: no prompt, response or tool input and output text. See What is stored.

Where the numbers come from

  1. OpenTelemetry, live. The runner listens for OTLP/HTTP logs on 127.0.0.1:4318 and turns each claude_code.api_request record into a request as it happens. Connections from anything but loopback are refused.
  2. Transcripts, for everything else. The runner tails Claude Code session transcripts (projects/**/*.jsonl in each profile's config directory) and backfills what telemetry did not cover. When both report the same request, it is stored once, and the transcript fills the fields telemetry lacks (such as the 5-minute versus 1-hour cache split and reasoning tokens).

Skill runs that AgentDock launches turn telemetry on by themselves. Other sessions are picked up from their transcripts, so they also appear, a little later. To get live numbers from a session you start by hand on a runner machine:

Terminal
CLAUDE_CODE_ENABLE_TELEMETRY=1 \
OTEL_LOGS_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 \
OTEL_RESOURCE_ATTRIBUTES=agentdock.project=<id>,agentdock.slot=<slot>,agentdock.issue=<n>,agentdock.run=<run> \
claude

The agentdock.* attributes are optional. Without them, the request is matched to its session by session id, and the session to a project by its working directory.

The runtime's own cost_usd figure is kept for reference but never added up: AgentDock prices tokens itself.

Prices

Prices live in versioned tables under Admin → Prices.

  • Each model price has a case-insensitive regex matchPattern against the model id, a priority, and tiers. A tier can have conditions, for example a long-context price above 200k input tokens.
  • Version 1 is seeded from Langfuse's public model price file (MIT, with attribution) when the database is set up.
  • Editing a price creates a new version; old versions are never changed in place. The newest version is current.
  • Cost is computed when a request is stored, with the current version, and saved with the version it used.
  • A bucket without its own price falls back: reasoning to output, 1-hour cache writes to 5-minute cache writes, cache writes and reads to input.

The Prices page also has a test calculator for checking a model id and token counts against the table.

Unpriced requests

A request whose model matches no pattern gets no cost. It is shown as unpriced, never as $0, and the Usage page counts how many there are. An admin fixes it by adding the model under Admin → Prices.

Re-pricing

Prices change and models get added after the fact. Admin → Prices → Re-price requests recomputes a date range with a chosen version, in background batches (USAGE_RECOMPUTE_BATCH, default 1000), and rebuilds the hourly rollups. One re-price runs at a time. Afterwards, Admin → Budgets → Recompute budget totals brings budget periods in line.

The Usage screen

Open Usage in the navigation.

  • Range: 24h, 7d, 30d or a custom From / To.
  • Project: one project or all of yours. Time zone sets how days are grouped.
  • Tiles for API-equivalent cost, Requests, Tokens and Unpriced requests over the range.
  • A cost-over-time chart, stacked by runtime.
  • A breakdown table by Project, Model, Runtime, Issue or Slot.

You see usage only for projects you are a member of. Sessions with no project, such as a person's own claude in an unrelated folder on a runner machine, are admin-only and show as "No project (machine-wide)".

Cost also shows per run in Project → History and per slot in the Fleet slot sheet.

Sessions

Sessions lists every agent session you can see: started, project and slot, runtime, models, turns, requests, tokens (input / output / cache), cost and duration. Filter by project, runtime, model, slot and date.

A session's page is a tree with a waterfall: the session, its turns, and under each turn the LLM requests, tool calls (by name and duration only) and subagent sessions, with time bars and totals per node. It is the place to find which turn or subagent burned the tokens.

Budgets

A budget caps the API-equivalent spend of a project or a user per period. Create one under Admin → Budgets → New budget or in Project → Settings → Budget.

FieldValues
Scopeproject or user
Periodday, week (starts Monday) or month
TimezoneIANA name; default APP_TIMEZONE, else UTC
Limit (USD)In API-equivalent dollars
Thresholds (%)Default 50, 80, 100. 100 is always included
When the limit is reachedalert or stop

There is at most one enabled budget per scope and period. Periods reset by themselves in the budget's timezone.

What counts

  • Project spend: every priced request whose session belongs to the project: fleet workers, the orchestrator, skill runs, and sessions people start in the project folder.
  • User spend: skill runs the user started, and an orchestrator the user started from the Fleet page. Fleet workers, scheduled runs and webhook-triggered runs count toward the project only, because nobody started them by hand.
  • Unpriced requests count as zero and are shown next to the budget as "N unpriced requests".

Thresholds and notifications

Each threshold notifies once per period: budget.threshold below 100%, budget.exceeded at 100%. A project budget notifies the project's operators and admins; a user budget notifies the user and admins. Both go in-app and to Telegram by default. See Notifications.

Stop means no new spend

With action stop, an exceeded budget refuses new work for its scope with 409 budget_exceeded, naming the budget and when it resets:

  • new skill runs (manual, scheduled or triggered);
  • Start… with start or next on the Fleet page, and scheduled orchestrator rounds.

It does not kill anything. Running workers and a running orchestrator keep going. Killing a worker mid-edit would leave a half-written branch that the orchestrator later resumes at full cost, and killing the orchestrator would stop merges of work you already paid for. If you want a harder stop, use Stop and Stop slot on the Fleet page. The Fleet page shows a banner while a budget is used up.

Overrides

An admin can lift a stop for the rest of the current period with Override budget: an end time (no later than the period end) and a required reason. Starts are allowed while the override lasts; thresholds still notify. Overrides do not carry into the next period.

Every budget change, enable, disable and override is audited with before and after values.

Who manages budgets

BudgetEditView
ProjectAdminsOperators of the project
UserAdminsThe user it applies to

Next steps