Skip to main content
Vantage reads your Bedrock Model Invocation Logs from an S3 bucket. It joins each logged invocation to the matching Bedrock cost row in your AWS Cost and Usage Report (CUR), then splits that cost row into multiple enriched rows, proportionally allocated by token share. Each enriched row carries any requestMetadata key/value pairs your application attaches at invocation time, plus Managed AI Tags such as the model, Region, operation, and calling IAM principal. These become tags you can filter and group on in Cost Reports, Virtual Tags, Budgets, and Cost Alerts. This unlocks request-level cost attribution that the CUR alone cannot provide. See the example use cases for scenarios such as per-customer margins, per-feature spend, and team chargeback. AWS Bedrock LLM Enrichment is the native path for Bedrock: you enable Model Invocation Logging in AWS and Vantage reads the logs AWS already writes, with no telemetry to emit from your own applications. If your Bedrock traffic runs through an AI gateway, or you want to attribute spend across several providers from one stream, see Custom LLM Enrichment instead.
Do not enable AWS Bedrock LLM Enrichment and Custom LLM Enrichment for the same AWS account. Both features allocate the same Bedrock cost rows, so running them together counts the same usage twice in the token pool: your totals still reconcile, but each source’s slices receive a diluted share and the attribution becomes misleading. Pick one path per account: use AWS Bedrock LLM Enrichment when AWS writes your Model Invocation Logs, and Custom LLM Enrichment when you emit your own per-request telemetry.
Enrichment is metadata-only. Vantage reads the model, Region, operation, token counts, IAM principal, and the requestMetadata you attach at invocation time. Vantage does not collect or store your Bedrock prompt or completion content, and it is never written to a Vantage-owned artifact. This data is not used to train any models.

How It Works

When logging is enabled, Amazon Bedrock records every model invocation (i.e., InvokeModel, InvokeModelWithResponseStream, Converse, and ConverseStream) as a JSON record in your Model Invocation Logs. Each record includes token counts, the model, the calling identity, and the requestMetadata your application supplied. Vantage joins those records to your Bedrock CUR costs during AWS cost ingestion. The enrichment pipeline runs through the following steps:

How Bedrock Costs Are Matched

Vantage does not match logs to costs on the model alone, because Bedrock prices the same model differently depending on how it was called. A logged invocation and a cost row are joined on the billing day, the token kind, and the following dimensions: The model and the tier must always agree. Region, operation, and inference scope behave as qualifiers: when either the log record or the cost row does not report one, that side becomes a wildcard that matches any value on the other side. Vantage matches exactly qualified pools of logs first, so a precisely qualified group of invocations claims its cost rows before a wildcard pool can absorb what is left. The tier never wildcards; both sides default to standard. After the join, Vantage narrows the match further by AWS account and, when available, by calling IAM principal. If you also deliver gateway telemetry for Bedrock, the same qualifiers apply to those records. See How Telemetry Matches Provider Costs for the per-field breakdown. Token counts are matched per kind, using a shared vocabulary of input, output, cache_read, and cache_write.
Bedrock reports cache token counts separately from inputTokenCount, so its input count already excludes cached tokens. Vantage accounts for this when normalizing, and does not subtract cache tokens a second time.

Model Normalization

Model Invocation Logs and the CUR often identify the same model in different ways. A log record may carry an inference-profile ARN:
While the CUR may carry an AWS Marketplace display name:
Vantage resolves both to the same canonical model key, such as anthropic.claude-opus-4-5, so the two sides join. On the cost side, Vantage reads the model identity from the resource ID when it contains a Bedrock foundation-model or inference-profile ARN, then falls back to the transformed model identifier and finally to the service name. Models and token dimensions that Vantage cannot recognize are not guessed. An unmatchable record is recorded with its normalization reason and excluded from allocation rather than attributed to the wrong model.

How Cost Rows Are Split

For each matched Bedrock cost row, the cost is allocated proportionally across the metadata groups present in the Model Invocation Logs, weighted by token usage: attributed cost=bedrock cost row×group tokenstotal matched tokens for row\text{attributed cost} = \text{bedrock cost row} \times \frac{\text{group tokens}}{\text{total matched tokens for row}} Splits are additive: the sum of the enriched rows always equals the original Bedrock cost row. Existing Bedrock-level reports continue to show the same totals; enrichment only makes new dimensions available on the underlying rows.
Consider the below example: One CUR row for anthropic.claude-3-5-sonnet in us-east-1 is $120 for the day, covering 60M input tokens. The Model Invocation Logs for that day show:After enrichment, the single $120 row becomes three rows:The total is unchanged at $120. The leftover row carries the portion of the cost row’s tokens your logs do not cover. It keeps the original CUR dimensions and the vntg:ai: tags derived from the cost row, but none of your requestMetadata keys, so totals always reconcile and no dollars are lost.

Data Freshness and Backfill

Enrichment runs inside the existing AWS cost ingestion pipeline, so it follows the same cadence as the rest of your AWS cost data. Month-to-date Bedrock rows are refreshed on every AWS data refresh, and recent days are reprocessed within a rolling three-day window so late-arriving logs are picked up. See the provider data refresh documentation for AWS timing. There is no Vantage-imposed backfill window: a billing period is enriched whenever it is processed while an active source exists, for as long as the matching logs remain in your bucket. Connecting a source does not, by itself, reprocess months that have already finished importing. Those periods are enriched the next time they are reprocessed, such as when AWS restates that month’s CUR or when the period is re-ingested through the AWS CUR backfill process.

Prerequisites

Before you begin, make sure:

Set Up AWS Bedrock LLM Enrichment

Setup has three steps: enable Model Invocation Logging in AWS, attach requestMetadata to your invocations (optional, but recommended), and connect the log buckets in Vantage.

Step 1: Enable Bedrock Model Invocation Logging

In the AWS Bedrock console (or via the AWS API), enable Model Invocation Logging and choose an S3 bucket as the destination. Vantage ingests logs from S3 only; a CloudWatch-only destination is not supported. For full setup instructions, see the AWS documentation on model invocation logging.
Model Invocation Logging is disabled by default in AWS and is configured per Region. Enable it in each Region where you invoke Bedrock and deliver the logs to an S3 bucket.
AWS delivers logs as gzipped JSON objects under a predictable prefix. Vantage automatically discovers this prefix from your Bedrock logging configuration, but for reference the path pattern is:
Each connected bucket is scanned for a single AWS Region, resolved automatically from your Bedrock logging configuration. Because you can connect more than one bucket, multi-Region coverage is a matter of connecting one bucket per Region:
  • One bucket per AWS account, for example a separate log bucket for Development, Staging, and Production.
  • Multiple regional buckets on the same AWS account, for example one bucket for eu-central-1 and another for us-east-1.
Connect a bucket for every Region where you invoke Bedrock. Bedrock usage in a Region with no connected bucket still appears in your costs, but it is not split into enriched rows.
Confirm logging is enabled for the Region you deliver to each bucket, and that new objects appear in the S3 bucket after you make a test invocation.
Request metadata lets you attribute Bedrock cost to per-request dimensions such as team, application, customer, and feature. You attach a flat map of string key/value pairs to each invocation, AWS records it in the requestMetadata field of the matching log record, and Vantage surfaces those pairs as tags. Costs for invocations without metadata are still split by the model, Region, operation, and IAM principal, but they will not carry your custom dimensions. The way you attach metadata depends on the API:
  • Converse and ConverseStream accept a requestMetadata field in the request body.
  • InvokeModel and InvokeModelWithResponseStream accept the X-Amzn-Bedrock-Request-Metadata HTTP header.
See the AWS guide on per-request metadata tagging for full details.
When you sign requests with AWS Signature Version 4 (SigV4), include X-Amzn-Bedrock-Request-Metadata in the SignedHeaders list. Requests that omit the header from the signed list are rejected with an InvalidSignatureException. AWS SDKs that expose request metadata as a parameter handle this automatically.
Limits and constraints (apply to both the header and the body field): Follow these best practices when attaching request metadata:
  • Set requestMetadata in a shared client or LLM gateway so every invocation is tagged consistently, without relying on each caller to remember.
  • Choose stable, low-cardinality keys such as team, environment, or feature for easy aggregation, and reserve high-cardinality values such as customer_id or flow_run_id for when you need per-entity tracing.
  • Avoid placing personally identifiable information (PII), credentials, or other sensitive data in request metadata. Values are stored in your logs and any system that reads them.
  • Request metadata is only recorded when Model Invocation Logging is enabled in the Region where the call is made. Otherwise the invocation still succeeds, but no metadata is retained.
Vantage derives some dimensions itself, such as the model, Region, operation, and IAM principal, and surfaces them as Managed AI Tags. If one of your requestMetadata keys collides with one of those names, the value Vantage derives wins. The AWS account and IAM principal are always taken from the log record and cannot be set through requestMetadata.

Step 3: Connect the Log Buckets in Vantage

In Vantage, navigate to the Integrations page and, under LLM Enrichment, select AWS Bedrock, then select the S3 buckets that receive your Bedrock logs. The connect screen walks you through granting read access and validating it.
You can also reach the same screen from the Model Invocation Logs tab on the AWS Settings page, which appears once at least one AWS account is connected.
You can connect one or more buckets per AWS account, including multiple regional buckets for the same account. Vantage creates one enrichment source per bucket, and each source is scanned for a single Region.
Connecting a bucket reuses your existing AWS cross-account IAM role, adding read-only access to the bucket that holds your Model Invocation Logs. It does not create a new role or require new credentials.
1

Select the buckets

Select the S3 buckets that receive your Bedrock logs. You can select several at once. Once Vantage can read your Bedrock logging configuration, the list is narrowed to the buckets Bedrock is actually configured to log to, so you do not have to search your whole S3 inventory; until then, every bucket in the account is listed. Buckets that are already connected or paused are shown with a Connected or Paused label and cannot be selected again.
If your bucket does not appear in the list, it may not be synced into Vantage’s inventory yet. Newly created buckets can take up to 24 hours to appear.
2

Grant Vantage read access

Deploy in the AWS account that owns the Model Invocation Log bucket, and make sure the bucket ARN in the policy matches the bucket you connect in Vantage. A mismatch is the most common cause of an access denied result when you check permissions.
The connect screen offers three ways to grant access, each prefilled for your account:
The connect screen provides a CloudFormation quick-create link that opens the AWS Console with the stack name, template URL, and parameters prefilled. Acknowledge that CloudFormation may create IAM resources, then create the stack.The stack applies the Vantage-published template with two parameters:
  • VantageCrossAccountRole: the name of your existing Vantage cross-account IAM role.
  • ModelInvocationLoggingBuckets: a comma-separated list of destination bucket ARNs, each as arn:aws:s3:::your-bucket/*.
Deploy the stack in the account that owns the bucket, not necessarily your management/payer account. The quick-create link targets us-east-1, which only controls where the stack is created; it does not limit which bucket Regions are covered.
Whichever method you use, Vantage needs the following read-only access to validate and ingest your Model Invocation Logs:Your existing Vantage cross-account role already grants s3:ListBucket and s3:GetBucketLocation. The grant above adds only object read on the log bucket (s3:GetObject, and the generated policy always includes s3:GetObjectAcl) plus the Bedrock logging-configuration read.
The CloudFormation, CLI, and Terraform options above grant S3 and Bedrock read access only. If your log bucket uses SSE-KMS encryption, you must grant kms:Decrypt separately. See KMS-Encrypted Buckets.
3

Check permissions and connect

Click Check Permissions. Vantage validates that it can read your Bedrock logging configuration, resolve the bucket Region, list objects under the log prefix, and read a sample log object. Resolve any reported issues using the Troubleshooting section. Then click Connect. Vantage resolves the log prefix and Region for each bucket from your Bedrock logging configuration and begins enriching Bedrock costs on the next AWS data refresh.
A success message confirms the sources are configured. Each bucket then appears in the connected sources table with its AWS account and status.

Manage AWS Bedrock Enrichment Sources

Manage your connected buckets from the AWS Bedrock integration page. The sources table lists each bucket with its AWS account, creation date, and Status (for example, Pending before an import starts, Importing while one runs, Stable once all imports succeed, Warning if only some imports fail, Error if all imports fail, or Paused if the source is stopped). Error details appear beneath the status. Paused sources show a Resume button, and each row has a ⋮ (More actions) menu with View import history and, for sources that are not paused, Stop.
Because Bedrock logs carry their own account and Region path layout, Vantage knows which costs each bucket applies to as soon as it connects. There is no log-scanning step, no provider review screen, and no per-source edit screen, which is how this integration differs from Custom LLM Enrichment and Cloudflare AI Gateway Enrichment. To change which buckets are connected, connect or stop sources from this page.

View Import History

In the sources table, open the row’s ⋮ (More actions) menu and select View import history to open the source’s Import History. The screen lists one row per billing period that ran enrichment, with columns for the Integration (with its account beneath), Status, Tokens Kept, Log Lines Kept, Bill Match, Billing Period, and Last Enriched At. When a run needs attention, the reason appears in the Status column. Lifecycle changes also appear as marker rows: Added when enrichment is first enabled for the bucket, and Paused or Resumed when you stop or resume it.

Stop a Source

To stop a source, open the row’s ⋮ (More actions) menu and select Stop, then confirm in the Stop enrichment source dialog. This is a soft deactivation, not a hard delete: Vantage stops enriching new cost data for that bucket, but your existing enriched history is left unchanged, and the source stays visible in the list so you can bring it back at any time.
Stopping a source does not re-import or roll back already-enriched costs. Going-forward enrichment simply pauses for that bucket until you resume it.

Resume a Source

To resume a stopped source, select Resume in its row. Going-forward enrichment restarts on the next AWS data refresh. A paused bucket cannot be re-added through the connect flow; use Resume instead.

View Enriched Costs on Cost Reports

Once enrichment runs, a single Bedrock CUR line is split into multiple rows, each carrying enrichment tags. You can filter and group by these tags anywhere tags are supported: Cost Reports, Virtual Tags, Budgets, and Cost Alerts. Because enrichment splits (allocates) your Bedrock costs, enrichment tags behave like Vantage’s cost allocation tags: you can build a Virtual Tag on them, but a cost can be allocated only once, so an enrichment tag can belong to only one allocation chain. Allocated values show the allocated badge (calculator icon) in the console.

Enrichment Tag Reference

Your own requestMetadata keys appear exactly as you send them, with no prefix. The dimensions Vantage derives and adds itself, such as the model identifier, carry a vntg:ai: prefix (for example, vntg:ai:model); this keeps them distinct from your keys and consistent with the AI tags Vantage applies across every provider you have connected. Because your key is just team (not provider-namespaced), the same key lines up across Bedrock, OpenAI, Anthropic, and the other providers, so you can group your entire AI stack by one team tag. Consistent key naming matters: team and Team are two different keys. Vantage writes a tag only when the source data provides a reliable value for it, so the exact set you see depends on what your logs and CUR report. See Managed AI Tags for the full cross-provider schema. Enrichment tags behave like any other provider tag in the console:
  • To group: open the Group By menu, select Tag, and choose the tag key, for example vntg:ai:model (values like claude-opus-4-5) or a requestMetadata key such as team.
  • To filter: open the Filters menu, click New Rule, select Tag, choose the Tag Key, then pick an operator and one or more values.
The tag keys appear in the Tag Key dropdown once enriched Bedrock costs exist. If you use a handful of keys often, mark them as preferred tags so they sort to the top of these menus.
Enriched rows retain your existing AWS tags and add the Vantage-managed vntg:ai:* tags (such as vntg:ai:model); split rows also carry the requestMetadata from their usage slice. When a vntg:ai: key is present on both the cost row and the enrichment, the value derived from your CUR wins. The leftover row (usage not covered by your logs) keeps the original CUR dimensions and the applicable vntg:ai:* tags but carries none of your requestMetadata. The AWS account and IAM principal are always taken from the log record and can never be supplied through requestMetadata.
In the example below, a Cost Report splits Amazon Bedrock spend by the team and purpose metadata attached at invocation time, alongside vntg:ai:model, so the same model can be compared across teams and workloads.
A Vantage Cost Report splitting Amazon Bedrock spend by team, purpose, and model from Model Invocation Log requestMetadata

IAM Principal Normalization

Vantage derives vntg:ai:principal_id from the caller identity (identity.arn) in each log record and normalizes it to a readable value: This tag comes from your logs, so it does not depend on your CUR format. When your CUR also reports a calling principal, Vantage uses it to narrow which logged invocations can match a given cost row:
  • If your logs carry no principal, the match is not scoped by principal.
  • If the cost row names a specific user or session, only invocations from that principal can match it.
  • If the cost row names a bare IAM role, every logged session of that role can match it.
  • If the cost row names a principal that matches none of the logged invocations, that row is left unenriched rather than attributed to the wrong caller.
  • If some cost rows for the same model and day name a principal and others do not, the unattributed rows draw only from invocations that carry no principal, so usage is never counted against two callers.
Cost splitting is scoped per AWS account. To distinguish the same principal name across multiple accounts in a report, add both the Account dimension and the vntg:ai:principal_id tag to your Group By.

CUR 2.0 and IAM Principal Attribution

AWS Bedrock LLM Enrichment works with both AWS Legacy CUR and CUR 2.0. Vantage converts CUR 2.0 rows to a common format before enrichment runs, so the same join and cost-splitting behavior applies regardless of which CUR format your AWS integration uses. See CUR Format for how to enable CUR 2.0. CUR 2.0 can also attribute Bedrock cost by the calling IAM principal without Model Invocation Logs. When you enable Include caller identity (IAM principal) allocation data on the CUR 2.0 export, Vantage surfaces the caller as the aws:IamPrincipal tag (plus any activated aws:iamPrincipal:* tags), and copies its normalized value into vntg:ai:principal_id. You can use this alongside LLM Enrichment, but it is less detailed: it tells you which IAM role or user made the call, not the per-request dimensions (such as team, customer, or feature) that Model Invocation Logs capture. When both sources report a principal, the CUR value takes precedence. The two paths support different attribution dimensions:
AWS advises against high-cardinality IAM principal tag values such as customer, session, or request identifiers, so those per-request dimensions belong in requestMetadata rather than on IAM principals.

Troubleshooting

Most errors are displayed when you click Check Permissions or Connect. The tables below list the messages you may see, their cause, and how to resolve them. Expand a section for the relevant category.
Confirm the permissions were deployed in the AWS account that owns the bucket, and that the bucket ARN in the policy matches the connected bucket.
Enrichment can only split costs by dimensions present in your logs. If enriched rows are missing your custom tags:
  • Confirm your application is attaching requestMetadata to Bedrock invocations. Costs from invocations without metadata are split by model, Region, operation, and IAM principal only.
  • Confirm Model Invocation Logging is enabled in the Region where the calls are made, and that a bucket for that Region is connected. Metadata is recorded only when logging is on for that Region.
  • Allow a full AWS data refresh to complete after connecting. Enrichment applies on the next refresh.
Bedrock costs pass through unchanged (no split) when any of the following is true:
  • There is no active Model Invocation Log source for the account, the source is paused, or the log import has not completed successfully.
  • The cost row is not a Bedrock usage row, or its model, Region, operation, inference scope, tier, or token type could not be matched to a logged invocation.
  • The cost row is a batch inference row. Model Invocation Logging does not record asynchronous batch jobs, so batch costs pass through unchanged.
  • The cost row reports an IAM principal that does not match any logged invocation.
  • Your AWS integration still imports on the legacy cost pipeline, which has no enrichment stage.
Unmatched usage is preserved on the leftover row with the original CUR dimensions, so totals always reconcile.
Totals should not change. Splits are additive and always sum to the original cost row to the cent, even when more than one enrichment source is connected. Enrichment only makes new dimensions available on the underlying rows; it never adds or removes cost.
If your totals reconcile but the split looks wrong, check whether more than one feature is enriching the same Bedrock costs, such as AWS Bedrock LLM Enrichment and Custom LLM Enrichment both being active for the same AWS account. When two sources describe the same invocations, their tokens pool into a single denominator, so each source’s slices receive a diluted share and the same usage is represented twice under two different sets of metadata. The totals still reconcile, but the attribution is misleading. Enable only one per AWS account.

KMS-Encrypted Buckets

If your log bucket is encrypted with AWS Key Management Service (KMS), Check Permissions reports a decryption error until Vantage can read the objects. Either remove encryption on the bucket, or grant the cross-account role kms:Decrypt for the encrypting key and allow that role in the KMS key policy. The CloudFormation, CLI, and Terraform options in Step 3 grant S3 and Bedrock read access only, so KMS access must be added separately.

Use Cases

Each row below shows example requestMetadata keys to attach to your Bedrock calls and what that attribution enables in Vantage. The key names are examples; you choose your own, and Vantage surfaces whatever requestMetadata you send. “Attach” means including those key/value pairs in each invocation’s requestMetadata, as shown in Step 2. All rows assume Model Invocation Logging is enabled and the bucket is connected.

Frequently Asked Questions

You need the Organization Owner or Integration Owner role to connect the source. Viewing the enriched costs does not require a special role; the resulting tags follow the same access rules as other cost data. See Role-Based Access Control.
Read-only access to the Model Invocation Log bucket you connect: s3:GetObject, s3:ListBucket, s3:GetBucketLocation, and kms:Decrypt for KMS-encrypted objects (generated policies may also include s3:GetObjectAcl), plus bedrock:GetModelInvocationLoggingConfiguration to auto-discover the log prefix and Region. The policy attaches to your existing cross-account role; no new role is created. See Step 3: Connect the Log Buckets in Vantage.
Use AWS Bedrock LLM Enrichment. It is the native path: AWS writes the Model Invocation Logs for you, so there is no telemetry to emit or maintain in your own applications. Custom LLM Enrichment is the right choice when your Bedrock traffic runs through an AI gateway that already emits per-request telemetry, or when you want one telemetry stream to cover several providers at once. Do not enable both for the same AWS account. They allocate the same Bedrock cost rows, so the same usage is counted twice in the token pool and each source’s slices receive a diluted, misleading share.
No. Splits are additive and always sum to the original cost row. Existing Bedrock-level reports continue to show the same totals; enrichment only makes new dimensions available on the underlying rows.
There is no Vantage-imposed backfill window: a billing period is enriched when it is processed while a source is active, as long as the matching logs are still in your bucket. The current month enriches automatically on the next refresh. Months that have already finished importing are not reprocessed just by connecting a source; they are enriched the next time they are reprocessed, such as a CUR restatement from AWS or a re-ingestion through the AWS CUR backfill process.
No. Bedrock Model Invocation Logging records runtime calls only, so asynchronous batch inference costs pass through without being split.
Connect one bucket per Region and per AWS account. Each connected bucket becomes its own enrichment source and is scanned for a single Region, and you can connect several at once from the same screen. See Step 1.
Configuration of the enrichment source is done in the Vantage console. The AWS-side permissions can be deployed via CloudFormation, the AWS CLI, or Terraform (see Step 3: Connect the Log Buckets in Vantage).
No code changes are required to invoke Bedrock. To attribute costs by your own dimensions, attach requestMetadata, a standard Bedrock invocation parameter, to your calls.
No. Enrichment is metadata-only. Vantage reads the model, Region, operation, token counts, IAM principal, and the requestMetadata you attach at invocation time. Prompt and completion text are never collected or stored.