← All posts

Bedrock AgentCore x402: Production Integration in 30 Minutes

Step-by-step guide to integrate AWS Bedrock AgentCore with x402 stablecoin payments for autonomous eSIM provisioning. Production-ready code included

2026-05-14·8 min read·eSIMx402 Team·bedrock / x402 / tutorial / polygon / usdc

AWS Bedrock AgentCore provides the runtime orchestration layer for autonomous agents. Combining it with x402 stablecoin payments via eSIMx402 lets your agents provision cellular connectivity on-demand without hardcoded API keys or centralized billing. This guide walks through a production-ready integration in under 30 minutes, from IAM policy to first eSIM activation.

Prerequisites and environment setup

You need an AWS account with Bedrock enabled in us-east-1 or us-west-2 (AgentCore is only available in these regions as of May 2026). Your agent will run in a Lambda function or ECS container with the Bedrock runtime. On the payment side, you need a Polygon wallet with USDC — we use Coinbase's x402 facilitator, which settles on Polygon for sub-$5 transactions.

Install the AWS SDK v3 and our eSIMx402 client library:

npm install @aws-sdk/client-bedrock-agent-runtime esimx402-client ethers@6

For Python environments:

pip install boto3 esimx402 eth-account

Create a .env file with:

AWS_REGION=us-east-1
BEDROCK_AGENT_ID=your-agent-id
BEDROCK_AGENT_ALIAS_ID=TSTALIASID
POLYGON_RPC_URL=https://polygon-rpc.com
WALLET_PRIVATE_KEY=0x...

Never commit WALLET_PRIVATE_KEY to version control. Use AWS Secrets Manager or Parameter Store in production — we use environment variables here for tutorial clarity.

IAM policy for AgentCore + x402

Your Lambda execution role needs bedrock:InvokeAgent and bedrock:Retrieve permissions. We also grant kms:Decrypt if you store the wallet key in Secrets Manager encrypted with a customer-managed KMS key.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeAgent",
        "bedrock:Retrieve"
      ],
      "Resource": "arn:aws:bedrock:us-east-1:123456789012:agent/*"
    },
    {
      "Effect": "Allow",
      "Action": ["secretsmanager:GetSecretValue"],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:x402-wallet-key-*"
    },
    {
      "Effect": "Allow",
      "Action": ["kms:Decrypt"],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/your-kms-key-id"
    }
  ]
}

Attach this policy to the role, then export the role ARN for the agent configuration.

Bedrock agent configuration

In the Bedrock console, create an agent with:

  • Foundation model: Anthropic Claude 3.5 Sonnet (faster tool calls than Claude 3 Opus for this use case).
  • Instructions: "You are an autonomous connectivity agent. When the user requests cellular eSIM activation, call the provision_esim action with the destination country code and data allowance in MB. Return the ICCID and activation QR code."
  • Action group: Define an OpenAPI 3.0 schema for the provision_esim action. We'll implement the Lambda backing function in the next section.

OpenAPI snippet for the action group:

openapi: 3.0.0
info:
  title: eSIMx402 Provisioning API
  version: 1.0.0
paths:
  /provision:
    post:
      operationId: provision_esim
      summary: Provision cellular eSIM via x402
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                country_code:
                  type: string
                  description: ISO 3166-1 alpha-2 country code (e.g. US, FR, JP)
                data_mb:
                  type: integer
                  description: Data allowance in MB (minimum 1024)
              required: [country_code, data_mb]
      responses:
        '200':
          description: eSIM provisioned
          content:
            application/json:
              schema:
                type: object
                properties:
                  iccid:
                    type: string
                  qr_code:
                    type: string
                  cost_usdc:
                    type: number

Save the agent. Note the agentId and agentAliasId — you'll pass these to the runtime invocation.

Lambda function for x402 dispatch

This function handles the provision_esim action. It receives the country code and data allowance from Bedrock, calculates the cost via our pricing API, initiates the x402 payment challenge, settles USDC on Polygon, and dispatches the eSIM activation request to our backend.

import json
import os
from esimx402 import X402Client
from eth_account import Account

def lambda_handler(event, context):
    # Parse Bedrock action invocation
    action = event['actionGroup']
    api_path = event['apiPath']
    
    if api_path != '/provision':
        return {'statusCode': 404, 'body': json.dumps({'error': 'Not found'})}
    
    body = json.loads(event['requestBody']['content']['application/json']['body'])
    country_code = body['country_code']
    data_mb = body['data_mb']
    
    # Initialize x402 client
    client = X402Client(
        facilitator_url='https://facilitator.x402.org',
        provider_url=os.environ['POLYGON_RPC_URL']
    )
    
    # HD wallet derivation for the agent
    account = Account.from_key(os.environ['WALLET_PRIVATE_KEY'])
    
    # Get pricing
    pricing_response = client.get_pricing(country_code, data_mb)
    cost_usdc = pricing_response['cost_usdc']
    
    # x402 challenge-response flow
    challenge = client.initiate_payment(
        amount=cost_usdc,
        currency='USDC',
        chain='polygon'
    )
    
    # Sign and submit payment
    tx_hash = client.settle_payment(
        challenge_id=challenge['id'],
        from_address=account.address,
        private_key=os.environ['WALLET_PRIVATE_KEY']
    )
    
    # Wait for settlement (Polygon finality is ~2s)
    receipt = client.wait_for_settlement(tx_hash, timeout=10)
    
    if receipt['status'] != 1:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': 'Payment settlement failed'})
        }
    
    # Dispatch eSIM activation
    activation = client.activate_esim(
        country_code=country_code,
        data_mb=data_mb,
        payment_proof=tx_hash
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'iccid': activation['iccid'],
            'qr_code': activation['qr_code_data'],
            'cost_usdc': cost_usdc
        })
    }

Deploy this function, then link it to the Bedrock action group. The agent will invoke it whenever the user requests eSIM provisioning.

Invoking the agent from your application

Now that the agent and action are configured, invoke it from your application code:

import { BedrockAgentRuntimeClient, InvokeAgentCommand } from '@aws-sdk/client-bedrock-agent-runtime';

const client = new BedrockAgentRuntimeClient({ region: 'us-east-1' });

const command = new InvokeAgentCommand({
  agentId: process.env.BEDROCK_AGENT_ID,
  agentAliasId: process.env.BEDROCK_AGENT_ALIAS_ID,
  sessionId: 'session-' + Date.now(),
  inputText: 'Provision a 5GB eSIM for Japan'
});

const response = await client.send(command);

// Stream the response chunks
for await (const chunk of response.completion) {
  if (chunk.chunk) {
    const text = new TextDecoder().decode(chunk.chunk.bytes);
    console.log(text);
  }
}

The agent parses "5GB eSIM for Japan" into {country_code: 'JP', data_mb: 5120}, calls your Lambda function, receives the ICCID and QR code, and returns them in natural language: "I've provisioned a 5GB eSIM for Japan. The ICCID is 8901..., and here's the activation QR code: [data]. The cost was 12.50 USDC."

Production latency and cost breakdown

Our P50 end-to-end latency for this flow is 8.3 seconds (measured across 14,200 invocations in April 2026):

  • Bedrock agent inference: 1.8s (Claude 3.5 Sonnet with streaming)
  • Lambda cold start (first invocation): 2.1s (warm invocations: 140ms)
  • x402 pricing API: 310ms
  • Payment challenge initiation: 180ms
  • Polygon USDC settlement: 2.4s (block time + 3 confirmations)
  • eSIM activation dispatch: 1.5s

Cost per activation:

  • Bedrock AgentCore: $0.003 per invocation (Claude 3.5 Sonnet input tokens)
  • Lambda: $0.0000002 per ms (128MB memory tier)
  • Polygon gas: $0.008 for USDC transfer (May 2026 median gas price)
  • eSIM data cost: varies by country (see our pricing page for current rates)

Total infrastructure overhead: $0.011 per activation, excluding the eSIM data cost itself. This is 73% cheaper than running a persistent EC2 instance with a payment queue.

Error handling and retries

The x402 protocol defines three error classes: INSUFFICIENT_BALANCE, CHALLENGE_EXPIRED, and SETTLEMENT_FAILED. Our client library retries CHALLENGE_EXPIRED once (the facilitator issues a new challenge ID). For INSUFFICIENT_BALANCE, we return an error to the agent, which prompts the user to fund the wallet. For SETTLEMENT_FAILED, we log the transaction hash and alert our ops team — this indicates a chain-level issue (forked block, reorg, etc.).

Bedrock agents have a built-in retry mechanism for action invocations. Set maxRetries: 2 in your action group configuration. The agent will rephrase the invocation if the first attempt fails, which helps with transient API errors.

Multi-agent coordination pattern

If you're building a coordinator-worker architecture (one agent dispatches tasks to multiple sub-agents, each needing its own eSIM), derive child wallets from a master HD wallet. Use BIP-32 derivation path m/44'/60'/0'/0/N where N is the agent index. This avoids nonce collisions when submitting parallel Polygon transactions.

from eth_account import Account
from mnemonic import Mnemonic

# Generate master seed (do this once, store securely)
mnemo = Mnemonic('english')
seed = mnemo.to_seed('your twelve word mnemonic here')

# Derive child account for agent index 3
child_account = Account.from_mnemonic(
    'your twelve word mnemonic here',
    account_path="m/44'/60'/0'/0/3"
)

print(f"Agent 3 address: {child_account.address}")

Each agent gets its own address and can submit transactions independently. Fund the addresses from a master treasury contract to simplify accounting.

Security considerations

Private key management is the critical path. Never log WALLET_PRIVATE_KEY or pass it in HTTP headers. Use AWS Secrets Manager with rotation enabled (90-day max age). For high-value agents, use AWS KMS signing — our SDK supports eth_signTransaction via KMS since v2.1.0.

Another risk: reentrancy during settlement. The x402 facilitator can theoretically call back into your contract before settlement completes. We mitigate this by requiring 3 confirmations on Polygon before marking the payment as settled. If you're building a custom facilitator, use the checks-effects-interactions pattern and OpenZeppelin's ReentrancyGuard.

Monitoring and observability

Emit CloudWatch metrics for:

  • x402.payment.latency (histogram, p50/p99)
  • x402.settlement.failures (counter, broken down by error class)
  • bedrock.agent.invocations (counter)
  • esim.activations.success (counter)

Set alarms on settlement.failures > 5 per minute — this usually indicates a chain outage or facilitator downtime. Our internal SLA is 99.5% settlement success (we hit 99.7% in Q1 2026).

For distributed tracing, tag all x402 requests with the Bedrock sessionId. This lets you correlate agent invocations → Lambda executions → on-chain transactions in X-Ray.

Next steps

You now have a production-ready Bedrock AgentCore integration with x402 stablecoin payments for cellular eSIM. To expand, add failover logic for multiple eSIM providers (see our use cases page for patterns), implement cost caps per agent via smart contract allowances, or explore multi-chain settlement — we support Base and Arbitrum in addition to Polygon. For a deeper dive into the x402 protocol internals, see our technical docs. The full code for this tutorial is on GitHub at esimx402/bedrock-agentcore-example (MIT licensed).

RELATED