Skip to content
agentgateway has joined the Agentic AI Foundation — Learn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Invoice-grade attribution

Page as Markdown

Carry a validated caller identity into AWS and Google Cloud billing records, so LLM spend is attributed per team, app, user, or any chosen attribution value on the provider’s own bill.

Invoice-grade attribution means that the value that names a request reaches the cloud provider’s own billing records. Finance then slices the same numbers that the provider charges. Agentgateway can also compute per-team spend from token counts and a price list, but that number is an estimate rather than the invoice. For the reasoning behind the term, see Invoice-grade attribution on Amazon Bedrock with agentgateway.

You configure the attribution values, and agentgateway resolves each one from an identity that it validated or from a static value that you assign.

Note

Invoice-grade attribution depends on the provider. The provider must accept a per-request attribution value and expose that value in its billing data. Providers with no equivalent billing dimension cannot support it. For those providers, attribute usage inside agentgateway instead, such as with virtual keys.

Before you begin

  1. Install the agentgateway binary.
  2. Configure the LLM provider that you want to attribute, such as Amazon Bedrock.
  3. Set up JWT authentication so that jwt.* values are available to attribution expressions.

Amazon Bedrock

Bedrock attributes inference cost to the IAM principal that made the call. For gateway traffic, the documented pattern is a per-caller session. Agentgateway assumes an AWS Identity and Access Management (IAM) role for each request. The session name and the session tags come from the caller’s identity.

The session name lands in AWS CloudTrail and in the IAM principal column of the Cost and Usage Report. The tags surface as cost allocation tags in Cost Explorer and in the Cost and Usage Report.

Session identity and tags

Configure auth.aws.assumeRole on the model. Each tag, and the session name, is either a static value or a CEL expression that agentgateway evaluates against the request.

Review the following example configuration.
# yaml-language-server: $schema=https://agentgateway.dev/schema/config

llm:
  policies:
    jwtAuth:
      issuer: agentgateway.dev
      audiences: [test.agentgateway.dev]
      jwks:
        file: ./manifests/jwt/pub-key
  models:
  - name: "*"
    provider: bedrock
    params:
      awsRegion: us-east-1
    auth:
      aws:
        assumeRole:
          roleArn: arn:aws:iam::123456789012:role/bedrock-invoke
          sessionName:
            expression: jwt.sub
          tags:
          - key: user
            expression: jwt.sub
          - key: team
            expression: request.headers["x-team"]
          - key: environment
            value: prod
Review the following table to understand this configuration.
SettingDescription
roleArnThe role that agentgateway assumes for each request. The credentials in the agentgateway environment are the source credentials for AWS Security Token Service (STS), and must be allowed sts:AssumeRole and sts:TagSession on the role.
sessionNameThe STS RoleSessionName, as a static string or as {expression: ...}. A per-caller session name makes callers distinguishable in CloudTrail and in the Cost and Usage Report. If you do not set it, the AWS SDK generates a random name. Must be 2 to 64 characters that match [\w+=,.@-].
tagsSTS session tags that agentgateway passes to AssumeRole. Each tag is {key, value} for a static value, or {key, expression} for a value that agentgateway computes per request. After you activate a key as a cost allocation tag, it appears in the Cost and Usage Report under resourceTags/user:<key>. STS allows at most 50 tags per role session, with keys up to 128 characters and values up to 256 characters.

Agentgateway checks static values against the STS limits at startup. Expressions are evaluated per request and fail closed. An expression that errors, or that produces an empty or invalid value, rejects the request before agentgateway calls AWS. No request reaches Bedrock unattributed.

To see the tags on the bill, activate the keys as cost allocation tags in the AWS Billing console. New keys take up to 24 hours to become available for activation. Activated tags apply to usage from that point on.

Choose attribution values

Where the value comes from decides what the bill is worth in a dispute.

  • jwt.* values come from a token that agentgateway validated under jwtAuth. The value is a fact about who logged in, checked on every request.
  • Static values are the ones that you assign to the model or route. Use them for callers that do not log in, such as batch jobs and internal services.
  • request.headers[...] is the caller’s word. Use it only for dimensions that the caller is trusted to assert, such as an environment name. Never use it for the identity that chargeback depends on.

Keep the values low-cardinality on the bill. Every distinct set of session tags is its own STS session and its own set of line items in the Cost and Usage Report. Tag by team and cost center everywhere, and tag per user only where the chargeback question needs it.

Verify

Learn more

Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate ↵ select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.