Chio/Docs
LOGIN · JOIN

AWS Bedrock Marketplace

Subscribe through AWS Marketplace and launch one IAM role, so Chio admits each Bedrock Converse request before the model runs.

Guide chio@5f63e6e

On this page

Amazon Bedrock traffic bought through the Chio listing on AWS Marketplace reaches the model only after Chio admits it. The listing puts the kernel between your agents and Bedrock without moving the control plane into your account.

The Chio control plane runs in the Chio seller account. For each Converse request it checks your Marketplace entitlement and the bound IAM principal, evaluates policy and guards, and signs a receipt, and only then calls Bedrock through one role in your account. Receipt volume above your base contract becomes Marketplace metering.

Start
Marketplace tenancyChoose a step.
Chio seller accountyour account · us-east-1entitlement · principal · policy · guardsεσπgConverse requestGetEntitlementssignsBatchMeterUsageAssumeRole + ExternalIdConverseaagentmAWS Marketplaceκintegration rolesBedrock RuntimeKChio control planeρallow receiptChio seller accountyour account · us-east-1entitlement · principalpolicy · guardsεσπgConverseentitlessignsAssumeRoleConverseaagentmMarketplaceκintegration rolesBedrockKcontrol planeρreceipt

Chio admits the request, then assumes your role

Agent traffic reaches the Chio control plane first. It checks the Marketplace entitlement and the bound IAM principal, evaluates policy and guards, signs the receipt, and only then calls Bedrock Converse through ChioBedrockIntegrationRole. The mediated call.

One Converse request from an agent through the Chio control plane in the seller account to Bedrock Runtime through the integration role in your account, in us-east-1. The rail marks the four checks; tool calls inside the reply, the Quick Launch stack, and the SSM endpoint parameter are left out.

Your account holds one role and one SSM parameter; entitlement lookup and metering both run from the seller account. If entitlement lookup, principal binding, guard evaluation, receipt issuance, or metering preparation fails, Chio refuses the request before it assumes your role, and Bedrock access stays refused until entitlement or metering state is repaired.

1. Subscribe and collect your onboarding values

Accept the Chio listing's SaaS contract in AWS Marketplace, which creates your tenant entitlement in the seller account. Chio onboarding then issues four values for the Quick Launch template: the tenant ID, the control-plane endpoint, the external ID, and the seller principal ARN. Write them into parameters.json.

parameters.jsonjson
[
  {
    "ParameterKey": "ChioControlPlaneEndpoint",
    "ParameterValue": "https://control.chio.computer/tenants/larkfield"
  },
  {
    "ParameterKey": "ChioTenantId",
    "ParameterValue": "larkfield"
  },
  {
    "ParameterKey": "ExternalId",
    "ParameterValue": "replace-with-tenant-external-id"
  },
  {
    "ParameterKey": "ChioSellerAccountPrincipalArn",
    "ParameterValue": "arn:aws:iam::444455556666:role/chio-control-plane"
  }
]

You should have four parameters. The template checks each one at launch: the endpoint must start with https://, the tenant ID is 1 to 32 characters, and the external ID is at least 16 characters and stored NoEcho.

2. Launch the integration role in us-east-1

From the root of the integration source, with the AWS CLI and the SAM CLI pointed at your account, validate the template and create the stack. The stack creates an IAM role, so the call needs CAPABILITY_IAM.

Terminal · your AWS accountbash
sam validate \
    --template integrations/aws-bedrock/cloudformation/quick-launch.yaml \
    --lint

aws cloudformation create-stack \
    --region us-east-1 \
    --stack-name chio-bedrock-larkfield \
    --capabilities CAPABILITY_IAM \
    --template-body file://integrations/aws-bedrock/cloudformation/quick-launch.yaml \
    --parameters file://integrations/aws-bedrock/cloudformation/parameters.json
Output · illustrative account
{
  "StackId": "arn:aws:cloudformation:us-east-1:111122223333:stack/chio-bedrock-larkfield/…"
}

You should see a stack ID in us-east-1. The template's IsSupportedRegion condition creates nothing in any other region, so a stack launched elsewhere leaves Chio no role to assume. Inside us-east-1 it creates two resources: ChioBedrockIntegrationRole and an SSM parameter holding the control-plane endpoint at /chio/bedrock/{ChioTenantId}/control-plane-endpoint.

3. Hand Chio the role it may assume

Read the stack's three outputs and send IntegrationRoleArn to the Chio onboarding operator.

Terminal · your AWS accountbash
aws cloudformation describe-stacks \
    --region us-east-1 \
    --stack-name chio-bedrock-larkfield \
    --query "Stacks[0].Outputs[].[OutputKey,OutputValue]" \
    --output text
Output · illustrative account
SupportedRegion                 us-east-1
IntegrationRoleArn              arn:aws:iam::111122223333:role/chio-bedrock-larkfield-…
ControlPlaneEndpointParameter   /chio/bedrock/larkfield/control-plane-endpoint

The role trusts only the seller principal, and only when the assume-role call carries your external ID. Its inline policy grants bedrock:InvokeModel and bedrock:InvokeModelWithResponseStream on us-east-1 foundation models, plus sts:GetCallerIdentity. With the ARN in hand, Chio calls sts:GetCallerIdentity through the role, binds the resolved IAM principal to your tenant, checks GetEntitlements, and enables governed Bedrock traffic. From then on every allow, deny, receipt, and overage decision is recorded.

4. Send a Converse request through Chio

The Python client chio-bedrock imports as chio_bedrock and wraps the Bedrock runtime client you inject: a boto3 bedrock-runtime client in production, or any object with a converse method in tests. This excerpt takes the runtime client and an enabled model ID from your deployment configuration.

converse.pypython
from chio_bedrock import BedrockChioClient

client = BedrockChioClient(
    bedrock_runtime=my_bedrock_runtime_client,
    principal_arn="arn:aws:sts::111122223333:assumed-role/chio-bedrock/larkfield",
    account_id="111122223333",
)

invocation = client.converse(
    tenant_id="larkfield",
    capability_id="cap-bedrock-a",
    model_id=model_id,
    messages=[{"role": "user", "content": [{"text": "hello"}]}],
)

You should get a BedrockInvocation with three fields: response, the Bedrock reply; receipt, a Chio receipt-compatible mapping; and metering, the Marketplace metering callback payload. The client checks the receipt it issued and raises instead of returning one that fails verification. Inject a runtime that reaches Bedrock through the governed path; a runtime with its own direct credentials sits outside the mediation boundary.

5. Read the principal trail and meter the receipt

Each receipt carries the IAM principal trail: Chio assumed ChioBedrockIntegrationRole with your external ID, called sts:GetCallerIdentity before the request, and wrote the resolved principal ARN and AWS account ID into the receipt metadata. A principal that cannot be resolved, or that does not match the signed tenant binding, is refused before the adapter invokes Converse or ConverseStream.

meter.pypython
client = BedrockChioClient(
    bedrock_runtime=my_bedrock_runtime_client,
    principal_arn="arn:aws:sts::111122223333:assumed-role/chio-bedrock/larkfield",
    account_id="111122223333",
    customer_identifier="customer-123",
    product_code="prod-chio-bedrock",
    trusted_kernel_keys=[kernel_public_key_hex],
)

payload = client.emit_metering(
    receipt=mediated_receipt,
    invocation_parameters={"modelId": model_id},
    dimension="bedrock_receipt_overage",
    quantity=1,
)

You should get a metering payload only for an authoritative mediated receipt signed by a kernel whose public key the client trusts. A client without trusted_kernel_keys raises instead of metering, and a receipt that fails verification raises MeteringTrustError, so no caller can bill against a receipt it minted itself. The verifier holds public keys only. Overage metering references the receipt ID and the tenant identifier.

Two dimensions price the listing

The listing pairs a per-tenant annual base entitlement with a metered receipt-overage dimension. The customer's Marketplace agreement supplies the prices and billing terms.

DimensionUnitBilling termCovers
tenant_basetenantannualGoverned Bedrock tenant base entitlement
bedrock_receipt_overagereceiptmetered_overageReceipts beyond the tenant base contract

The seller aggregates receipt overage and submits AWS BatchMeterUsage from the seller account. AWS deduplicates SaaS usage by customer, dimension, and hour, so the hour's quantity is aggregated before submission. Overage is never reported for a tenant whose entitlement is inactive or expired.

Tool calls inside a Converse reply cross the same kernel

The listing wraps chio-bedrock-converse-adapter, which carries tool use in both directions. When a model reply asks for a tool, the adapter lifts the toolUse block into the shared ToolInvocation shape before anything runs.

Provider tool callsChoose an outcome.

κcapabilityσscopegguardsBbudget

Lift, admit, lower, with the same call ID

The adapter lifts the native call into a ToolInvocation that names the provider, the tool, the canonical-JSON argument bytes, and a provenance stamp. The kernel admits it and dispatches the registered tool, and the adapter lowers the output into a native reply with the same call ID. Govern Any Provider.

One provider tool call lifted into the shared invocation contract, admitted by the kernel, and lowered back to the provider’s format. Provider transport and the shared error taxonomy are left out.Govern Any Provider

The invocation names the provider, the tool, the canonical-JSON argument bytes, and a provenance stamp. The kernel admits it and dispatches the registered tool, and the adapter lowers the output, or the refusal with its signed deny receipt, back into a toolResult block with the same call ID. On a stream, frames from contentBlockStart through contentBlockStop are buffered and the completed block is evaluated before any of its bytes are released: flushed on allow, dropped on deny.

Read more in Govern Any Provider Tool Calls.

Listing reference

Quick Launch parameters

ParameterConstraintPurpose
ChioControlPlaneEndpoint
^https://.+
Tenant gateway URL supplied by Chio; stored in SSM Parameter Store
ChioTenantId
1 to 32 chars, ^[A-Za-z0-9+=,.@_-]+$
Tenant identifier issued during onboarding; used for stack naming and SSM pathing
ExternalId
NoEcho, min 16 chars
Tenant-specific external ID gating cross-account sts:AssumeRole
ChioSellerAccountPrincipalArn
^arn:aws:iam::[0-9]{12}:(root|role/.+)$
Chio seller account root or control-plane role ARN, trusted to assume the integration role

Stack outputs

  • SupportedRegion. The integration region, us-east-1.
  • IntegrationRoleArn. ARN of ChioBedrockIntegrationRole, the role Chio assumes.
  • ControlPlaneEndpointParameter. Name of the SSM parameter holding the control-plane endpoint.

Role trust and permissions

The trust policy pins the external-ID condition on the assume-role statement. The inline policy is the minimum for governed Bedrock traffic from us-east-1: the two runtime invoke actions pinned to the foundation-model ARN, plus sts:GetCallerIdentity so Chio can resolve and bind the caller before any request. The customer role holds no Marketplace entitlement or metering permissions.

quick-launch.yaml · trust policyyaml
AssumeRolePolicyDocument:
  Version: "2012-10-17"
  Statement:
    - Effect: Allow
      Principal:
        AWS: !Ref ChioSellerAccountPrincipalArn
      Action: "sts:AssumeRole"
      Condition:
        StringEquals:
          "sts:ExternalId": !Ref ExternalId
integrations/aws-bedrock/iam/customer-attach.jsonjson
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "InvokePinnedBedrockRuntime",
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "arn:aws:bedrock:us-east-1::foundation-model/*"
    },
    {
      "Sid": "BindCallerIdentityForReceipts",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}

Entitlement contract

The chio-bedrock-control-plane crate holds the fail-closed entitlement and metering contract. Its public APIs are deterministic and testable without AWS credentials; the seller binds the decisions to aws-sdk-marketplaceentitlement and aws-sdk-marketplacemetering clients at the process edge. An EntitlementStore holds EntitlementRecord rows keyed by the (customer_identifier, product_code, dimension) triple, and check returns an EntitlementDecision only when a matching record is active and unexpired at the supplied epoch.

src/main.rs · in mainrust
use chio_bedrock_control_plane::{
    meter_usage, EntitlementRecord, EntitlementStore, MeteringApi, MeteringUsage,
};

// Seed the tenant entitlement resolved from GetEntitlements.
let mut store = EntitlementStore::default();
store.insert(EntitlementRecord {
    customer_identifier: "customer-123".into(),
    product_code: "prod-chio-bedrock".into(),
    dimension: "bedrock_receipt_overage".into(),
    expires_at_epoch_secs: 1_900_000_000,
    active: true,
})?;

// Fail-closed check before onboarding the tenant.
let decision = store.check(
    "customer-123",
    "prod-chio-bedrock",
    "bedrock_receipt_overage",
    now_epoch_secs,
)?;

// Report one receipt of overage past the base contract.
let receipt_id = "1faf4bc1566804062e145ef5cb2f95f8289ba448a2fe5b62a180c4381ff73007";
let event = meter_usage(
    &store,
    MeteringUsage {
        customer_identifier: decision.customer_identifier,
        product_code: decision.product_code,
        dimension: decision.dimension,
        quantity: 1,
        timestamp_epoch_secs: now_epoch_secs,
        receipt_id: receipt_id.into(),
    },
    now_epoch_secs,
)?;
assert_eq!(event.api, MeteringApi::MeterUsage);

Every failure is a distinct EntitlementError variant, so onboarding and metering both fail closed with a precise reason. Leading or trailing whitespace on an identifier is rejected at insert and check time.

  • MissingCustomerIdentifier. The customer identifier is empty or whitespace-padded.
  • MissingProductCode. The product code is empty or whitespace-padded.
  • MissingDimension. The dimension is empty or whitespace-padded.
  • MissingEntitlement. No record matches the customer, product, and dimension triple.
  • InactiveEntitlement. A record exists and is marked inactive.
  • ExpiredEntitlement. The record's expiry is at or before the supplied epoch.

Metering helpers

meter_usage validates one MeteringUsage and checks the entitlement again before it emits a MeteringEvent tagged MeteringApi::MeterUsage. batch_meter_usage folds a MeteringBatch into events tagged MeteringApi::BatchMeterUsage. These tags are internal contract values; the AWS product's billing API is BatchMeterUsage, which the seller submits with the aggregated overage.

A quantity of zero fails with QuantityMustBePositive and an empty receipt ID with MissingReceiptId. An inactive or expired entitlement surfaces as MeteringError::Entitlement. When metering is refused, the customer receives a fail-closed error envelope carrying urn:chio:error:aws-bedrock:marketplace-entitlement-denied.

AWS identifies new SaaS customers by CustomerAWSAccountId and LicenseArn; the seller resolves the agreement identity at its edge before it submits usage. Follow the AWS SaaS metering contract and the BatchMeterUsage fields.

Python client options

  • converse. Keyword-only. Optional inference_config, tool_config, and additional_model_request_fields pass through to the runtime request under their Bedrock names.
  • Construction. Rejects any region other than us-east-1, and an empty principal_arn or account_id.
  • Source. sdks/python/packages/chio-bedrock in the Chio repository.

Adapter pins

chio-bedrock-converse-adapter is pinned to BEDROCK_REGION (us-east-1) and BEDROCK_CONVERSE_API_VERSION (bedrock.converse.v1), and rejects any construction that drifts from either pin. It lifts Bedrock toolUse blocks into the shared ToolInvocation shape, lowers kernel verdicts back into toolResult blocks, and resolves the caller into the shared Principal::BedrockIam shape.

Next: account for what each receipt bills