Track Spend by Tag
Cost-allocation tags reuse the key/value tags you already set on an agent and give them a second job: grouping and filtering LLM spend. Tag your agents with a dimension that matches how you report cost (for example, department, team, or env), and the Agentic Data Plane attributes every LLM call that agent makes to those tags. You can then break spend down by department on the Cost & Usage page, filter a report to env=prod, or pull per-team totals through the API for chargeback.
You configure no separate tag registry and no spending pipeline. Tag an agent, and its spend is attributed automatically from the next call onward.
After reading this page, you will be able to:
-
Tag agents so their LLM spend is attributed to a department, team, or environment
-
Group and filter spend by tag in the Cost & Usage page
-
Query spend by tag programmatically through SpendingService
Prerequisites
-
A running agent. If you do not have one, see Agentic Data Plane Quickstart for Administrators.
-
To query spend through the API, a service account with the
dataplane_adp_spending_getpermission. See Spending permissions.
How tag-based spend tracking works
When an agent makes an LLM call through AI Gateway, the Agentic Data Plane records a spending event and stamps it with a snapshot of that agent’s tags at the time of the call. Cost reports then group and filter on those stamped tags.
Three behaviors follow from this design:
- Attribution is point-in-time and immutable
-
The tags recorded on a spending event are the agent’s tags at the moment of the call. Editing an agent’s tags later never rewrites past spend: historical rows keep the tags they were recorded with, and new spend picks up the new tags. A chargeback report for a closed period stays stable even after you retag agents.
- Tag changes take a short time to take effect
-
After you create or retag an agent, its spend can briefly record under the old tags, or as untagged, until the change takes effect.
- Unattributable spend is grouped as Untagged
-
Calls that carry no value for the tag key you group on collapse into a single Untagged bucket. This bucket covers direct user calls that do not run through an agent, calls from an agent that has no tags, and the brief window before a new agent’s tags take effect.
Tag your agents for cost tracking
Tags live on the agent. Set them when you create an agent or edit an existing one, either in the agent form (the Tags section) or through the CreateAgent and UpdateAgent methods. See Create an Agent.
A tag is a key/value pair. Choose keys that match your reporting dimensions and apply them consistently across agents:
| Tag | Attributes spend to |
|---|---|
|
A business unit or cost center. |
|
A team within a department. |
|
An environment, to separate production spend from staging or development. |
|
Do not put secrets or personally identifiable information (PII) in tag values. Tag values appear in cost reports and API responses. |
Track spend by tag in the UI
Open Cost & Usage under Governance in the sidebar. For the page overview, see View cost and usage. Tags add two independent controls:
- Group by Tag
-
Choose Tag as the group-by dimension, then pick a tag key, for example,
department. Each chart series becomes one tag value, plus an Untagged series for spend with no value for that key. Use it to see how spend splits across departments or environments over the selected range. - Tag filter
-
Add a tag filter to scope the whole page to specific tag values, independent of what you group by. Selecting several values of the same key matches any of them (OR); selecting values across different keys requires all of them (AND). For example, filter to
department=salesORdepartment=support, andenv=prod, to see production spend for those two departments.
The filter also applies to the CSV export, so an exported report matches what you see on screen.
Query spend by tag with the API
The SpendingService API exposes tags as a breakdown dimension and a filter. These calls use the same authentication, SpendingFilter shape, and dataplane_adp_spending_get permission as the rest of the spending API. For authentication and the base request shape, see Query spend programmatically.
Reach the methods over the Connect protocol (POST and JSON) at <dataplane-base>/redpanda.api.adp.v1alpha1.SpendingService/<Method>. In this path, <dataplane-base> is your cluster’s AI Gateway base URL. Request fields use snake_case (start_time, tag_key), and the JSON response uses camelCase (totalCostMicrocents, totalRequests).
Group a breakdown by tag
The GetSpendingBreakdown and GetSpendingTimeSeriesByDimension methods accept BREAKDOWN_DIMENSION_TAG as the dimension, together with a tag_key that names the key to group on:
| Field | Meaning |
|---|---|
|
Set to |
|
The tag key to group on, for example, |
Each entry in the response keys on a tag value, with the same stats object (cost in microcents, request count, and token buckets) as the other breakdown dimensions. Spend with no value for the key is returned under the empty-string key, which the UI labels Untagged.
Filter any query by tag
Every spending query reads a SpendingFilter, which accepts an AIP-160 filter expression. Reference a tag with tags.<key>, where <key> is the tag key to match:
tags.department = "sales"
tags.department = "sales" AND tags.env = "prod"
Tag predicates compose with the structured SpendingFilter fields, such as provider_name, model_id, user_email, and agent_name, so you can scope a per-user breakdown to one department.
cURL example
Break down the last seven days of spend by department:
ACCESS_TOKEN="<oidc-access-token>" # from the client_credentials flow
DATAPLANE_BASE="https://aigw.<cluster-id>.clusters.rdpa.co"
curl -s --request POST \
--url "${DATAPLANE_BASE}/redpanda.api.adp.v1alpha1.SpendingService/GetSpendingBreakdown" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"filter": {
"start_time": "2026-05-17T00:00:00Z",
"end_time": "2026-05-24T00:00:00Z"
},
"dimension": "BREAKDOWN_DIMENSION_TAG",
"tag_key": "department"
}' | jq
In this URL, <cluster-id> is your cluster’s ID, and <oidc-access-token> is a token from the client-credentials flow. The response carries one entries row per department value in the window, plus a row for untagged spend whose key is the empty string (omitted from the JSON). Each row has a key, the tag value, and a stats object whose fields use camelCase JSON names, such as totalCostMicrocents and totalRequests, plus per-bucket token usage. Divide totalCostMicrocents by 100,000,000 to convert to dollars.
Limits and constraints
| Constraint | Value |
|---|---|
Tags per agent |
At most 50 key/value pairs per agent. |
Tag value length |
At most 256 characters per value. |
Distinct tag keys |
No fixed limit. The keys available for grouping are whatever keys exist across agents that have recorded spend in the selected window. |
Untagged spend |
Spend with no value for the grouped key (direct user calls, untagged agents, and spend recorded before an agent’s tags take effect) is grouped under a single Untagged bucket. |
Troubleshooting
- Spend you expect under a tag shows as Untagged
-
The agent had no tags when it made the call, or you tagged or retagged it moments earlier and the change had not taken effect yet. Recheck after a short wait. Direct user calls that do not run through an agent are always untagged.
- Editing an agent’s tags did not change past reports
-
Attribution is point-in-time by design. Only spend recorded after the edit picks up the new tags; historical spend keeps the tags it was recorded with.