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_esimaction 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_esimaction. 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).