Amazon Bedrock AgentCore Runtime
5-minute deploy · BYO Python code · AgentCore managed microVM
This is the BYO-code path on Amazon Bedrock AgentCore Runtime:
you write your agent in Python, ship it via the agentcore CLI,
and AWS hosts it in a managed microVM. Because the microVM runs
your code, waxell-observe installs and runs inside the runtime
just like any other Python dependency — the AgentCore boundary is
transparent to the SDK.
What you get
- Every LLM call your agent makes (Bedrock Converse / InvokeModel, OpenAI, Anthropic, anything) → captured as a child LLM span on the parent run with real model id, token counts, and cost.
- Every tool call (MCP, function tools, action group invocations from inside the agent loop) → captured as tool spans.
- Every
ctx.check_policy(...)gate → enforced inside the runtime before the LLM/tool call fires. - Sub-agent lineage, memory ops, custom spans → same shape as any other host you'd deploy the agent to.
The microVM is just another Python host. Your agent code is unchanged; AWS handles isolation, scaling, and lifecycle.
Prerequisites
pipx install bedrock-agentcore-starter-toolkit # provides the `agentcore` CLI
pipx install uv # required by direct_code_deploy
You also need:
- AWS IAM credentials with
bedrock-agentcore-control:*perms (the toolkit auto-creates the runtime execution role on first deploy). - Bedrock model access in your region for whichever foundation model your agent calls.
Project layout
Scaffold a new project:
agentcore create -p mywaxellagent -t basic
cd mywaxellagent
Edit pyproject.toml to add waxell-observe:
[project]
name = "mywaxellagent"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"waxell-observe[bedrock]>=0.1.1",
"bedrock-agentcore>=1.0.3",
"boto3>=1.40,<2.0",
]
Edit .bedrock_agentcore.yaml to use Python 3.12 or 3.13 (the
versions waxell-observe ships wheels for):
runtime_type: PYTHON_3_13
Edit src/main.py with the canonical two-line instrumentation
pattern:
import os
import waxell_observe as waxell
waxell.init()
import boto3
from bedrock_agentcore.runtime import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
REGION = os.getenv("AWS_REGION", "us-east-1")
@waxell.observe(agent_name="my-byo-agent")
def chat_turn(user_message: str) -> str:
client = boto3.client("bedrock-runtime", region_name=REGION)
response = client.converse(
modelId="amazon.nova-lite-v1:0",
messages=[{"role": "user", "content": [{"text": user_message}]}],
)
return response["output"]["message"]["content"][0]["text"]
@app.entrypoint
async def invoke(payload, context):
yield chat_turn(payload.get("prompt", ""))
if __name__ == "__main__":
app.run()
Deploy
WAXELL_API_KEY + WAXELL_API_URL are passed via the --env
flag on agentcore deploy — they end up as environmentVariables
on the AgentCore Runtime config and propagate into the microVM at
provision time.
export WAXELL_API_KEY=<your-key> # from `wax setup` or your .env
agentcore deploy \
--env "WAXELL_API_KEY=$WAXELL_API_KEY" \
--env "WAXELL_API_URL=https://api.waxell.dev"
If you try WAXELL_API_KEY=... agentcore deploy --env "WAXELL_API_KEY=$WAXELL_API_KEY" ...
in a single line, Bash expands $WAXELL_API_KEY before the
prefix assignment runs and the runtime ends up with an empty key.
Always export the value first or read it from a file with a
separate command. Verify after deploy:
aws bedrock-agentcore-control get-agent-runtime \
--agent-runtime-id <id> --region <region> \
--query 'environmentVariables.WAXELL_API_KEY'
If it returns "", re-deploy with the export trick above.
Invoke
agentcore invoke '{"prompt": "what is the deepest known cave?"}'
Then check Waxell:
wax runs list --limit 5
You'll see your agent run under agent_name=my-byo-agent with the
same shape as 01-hello-waxell — parent agent span, chat amazon.nova-lite-v1:0 LLM child span, real token counts and cost.
Network egress
AgentCore Runtime's default network_mode: PUBLIC gives the
microVM NAT egress over the public internet — api.waxell.dev
(HTTPS) is reachable out of the box. If you switch to
network_mode: VPC you'll need a NAT gateway / VPC endpoint in
your VPC so the microVM can still reach Waxell.
Policy enforcement inside the runtime
The full @waxell.observe + @waxell.tool + ctx.check_policy(...)
stack runs unchanged inside the microVM — there is no AgentCore-
specific shim or escape hatch. A policy denial raised during
execution aborts the agent before the offending LLM or tool call
lands, surfaces as PolicyViolationError to your entrypoint, and
records the violation in your Waxell governance dashboard.
Related examples
waxell-ai/waxell-agent-examples/examples/14-bedrock-agentcore-runtime-byo— full working example with deploy commands.