End-to-End Deploy with the AgentCore CLI
create, dev, deploy, invoke — CodeZip vs. Container
- Run the new-CLI loop: `create` → `dev` → `deploy` → `invoke` → `status`/`logs`/`traces`, and attach capabilities with `agentcore add`
- Map the new CLI to the legacy starter-toolkit (`configure` → `launch`/`deploy` → `invoke` → `status` → `destroy`) so you can follow any tutorial
- Choose between the CodeZip build (default, no Docker, size-limited) and the Container build (Docker, ARM64-only)
- Configure the execution role, its trust policy, and the developer policy needed to deploy
- Diagnose the canonical deploy failures: the two-CLI verb mismatch, amd64 images, missing model access, short session IDs, and missing `iam:PassRole`
This lesson runs the full AgentCore developer loop end to end. You will scaffold an agent with the current npm CLI (`@aws/agentcore`), iterate locally with `dev`, ship to a serverless Runtime with `deploy`, invoke it, and watch status/logs/traces. You will also learn the legacy starter-toolkit verbs so you can read any tutorial, pick the right build mode (CodeZip vs Container), wire up the execution role and developer IAM, and avoid the long tail of deploy gotchas.
- 1Two tools, one Runtime: the disambiguation you must internalize
- 2Prerequisites and IAM: what must exist before you deploy
- 3The new-CLI developer loop: create → dev → deploy → invoke
- 4Reading legacy tutorials: the starter-toolkit verbs
- 5Two build modes: CodeZip vs Container
- 6The deploy gotchas checklist
Two tools, one Runtime: the disambiguation you must internalize
Before any command, fix this in your head: there are two different CLIs, both of which install a binary called agentcore, and they have different verbs. This single ambiguity is the most common source of copy-paste failures when following tutorials.
| Starter Toolkit (legacy) | AgentCore CLI (current/recommended) | |
|---|---|---|
| Package | bedrock-agentcore-starter-toolkit (PyPI) | @aws/agentcore (npm) |
| Install | pip install bedrock-agentcore-starter-toolkit | npm install -g @aws/agentcore |
| Runtime | Python ≥ 3.10 | Node.js 20+ (plus Python 3.10+) |
| Core verbs | configure, launch/deploy, invoke, status, destroy | create, dev, deploy, invoke, status, add, remove, logs, traces |
| Build infra | AWS CodeBuild (default) / local Docker | AWS CDK + CloudFormation |
| Config files | .bedrock_agentcore.yaml + generated Dockerfile | agentcore/agentcore.json, aws-targets.json, .env.local |
Both deploy to the same Runtime, and both wrap your agent with the same bedrock-agentcore Python SDK (BedrockAgentCoreApp, @app.entrypoint, app.run()). The toolkit README now marks itself (legacy) and points at the AgentCore CLI. New work should use @aws/agentcore; you learn the legacy verbs only so you can read older content.
A further trap lives even inside the legacy world: the AWS devguide and the Python Runtime API use the verb launch / .launch(), but the current starter-toolkit CLI (v0.3.x) renamed that verb to deploy (with destroy for teardown) — the same operation, two names. The Python method is always .launch().
Watch out
Pin which CLI a tutorial assumes
If a tutorial runs agentcore configure -e agent.py, it is the legacy Python toolkit. If it runs agentcore create --name MyAgent, it is the new npm CLI. Mixing the two — e.g. agentcore configure then agentcore deploy from different installs — fails because the config files and verbs don't match. Decide which CLI you're using before the first command.
Prerequisites and IAM: what must exist before you deploy
The new CLI deploys through AWS CDK → CloudFormation, so the toolchain is heavier than the legacy CodeBuild path.
Toolchain prerequisites (new CLI):
- Node.js 20+ (the CLI itself) and Python 3.10+ (your agent runs Python).
- AWS credentials configured (
aws configure/ SSO / env vars). - AWS CDK bootstrapped in the target account+region — run
cdk bootstraponce. If you skip this,agentcore deployfails at the CloudFormation stage.
node --version # v20+
python --version # 3.10+
aws sts get-caller-identity
cdk bootstrap aws://<account-id>/us-east-1Two distinct IAM identities are involved — don't conflate them.
-
The execution role — the role the agent assumes at runtime. Abbreviated, it needs: CloudWatch Logs (
CreateLogGroup/CreateLogStream/PutLogEvents/Describe*on/aws/bedrock-agentcore/runtimes/*), X-Ray (PutTraceSegments/PutTelemetryRecords/GetSamplingRules/GetSamplingTargets),cloudwatch:PutMetricData(scoped to thebedrock-agentcorenamespace), workload tokens (bedrock-agentcore:GetWorkloadAccessToken*), and — if your agent calls Bedrock —bedrock:InvokeModel/bedrock:InvokeModelWithResponseStream. ECR read actions (BatchGetImage/GetDownloadUrlForLayer/GetAuthorizationToken) are needed only for Container deploys.Its trust policy must let the service assume it: principal
bedrock-agentcore.amazonaws.com, actionsts:AssumeRole, withaws:SourceAccountandaws:SourceArn(arn:aws:bedrock-agentcore:<region>:<account>:*) conditions to prevent the confused-deputy problem.json{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "bedrock-agentcore.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:SourceAccount": "123456789012" }, "ArnLike": { "aws:SourceArn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:*" } } }] } -
The caller/developer identity — your permissions to run the deploy. The quickest path is the managed policy
BedrockAgentCoreFullAccess. The new CLI additionally needs CloudFormation/CDK permissions (andcdk bootstrapdone). The legacy CodeBuild path instead needs IAM (CreateRole/PassRoleon*BedrockAgentCore*), CodeBuild, ECR, S3, and Logs permissions.
Watch out
iam:PassRole is the silent blocker
Deploy hands the execution role to the AgentCore service, which requires iam:PassRole on your developer identity. Without it the deploy fails with an access-denied on PassRole even though every other permission is present. BedrockAgentCoreFullAccess covers the common case.
Note
Auto-generated dev policies are broad
Both CLIs can auto-create the execution role and ECR repo for you (the legacy toolkit via auto_create_execution_role=True, auto_create_ecr=True). AWS warns these auto-generated developer policies are deliberately broad and not production-grade. Treat the exact action lists as [VOLATILE] — verify them against the live runtime permissions page and tighten before production.
The new-CLI developer loop: create → dev → deploy → invoke
The @aws/agentcore CLI gives you a tight, scaffold-first loop. Install it globally, scaffold a project, iterate locally, then ship.
npm install -g @aws/agentcore
# Scaffold a project (interactive flags shown; or use --defaults)
agentcore create --name MyAgent \
--framework Strands \
--protocol HTTP \
--model-provider Bedrock \
--memory none
# or simply: agentcore create --name MyAgent --defaults
cd MyAgentcreate flags worth knowing:
--name— alphanumeric, must start with a letter, ≤ 36 chars.--framework—Strands|LangChain_LangGraph|GoogleADK|OpenAIAgents.--protocol—HTTP(default) |MCP|A2A.--build—CodeZip(default) |Container.--model-provider—Bedrock|Anthropic|OpenAI|Gemini.--memory—none|shortTerm|longAndShortTerm.
Iterate locally with hot reload. agentcore dev runs a hot-reloading server plus an agent inspector on port 8080:
agentcore dev # hot-reload server + inspector on :8080
agentcore dev -p 3000 # if 8080 is already takenYou can hit the same service contract the cloud will use:
curl -X POST http://localhost:8080/invocations \
-H 'Content-Type: application/json' \
-d '{"prompt":"What is the weather?"}'Deploy packages the agent, synthesizes a CDK stack, and applies it via CloudFormation:
agentcore deploy # package → CDK synth → CloudFormation deployInvoke the deployed Runtime, optionally streaming or pinning a session:
agentcore invoke "Tell me a joke"
agentcore invoke "Tell me a joke" --stream --session-id <id> --runtime <runtime>Observe and tear down:
agentcore status # ARN, endpoint, log group
agentcore logs # CloudWatch logs
agentcore traces list # observability traces
agentcore remove all && agentcore deploy # teardown / clean redeployAttach capabilities without leaving the CLI — each add wires the corresponding AgentCore service into your project:
agentcore add memory # AgentCore Memory
agentcore add gateway # AgentCore Gateway (governed MCP tools)
agentcore add agent # compose another agent
agentcore add credential # AgentCore Identity credential provider
agentcore add evaluator # AgentCore EvaluationsTip
API-key model providers need a local .env
If you pick --model-provider Anthropic | OpenAI | Gemini instead of Bedrock, the CLI expects the provider key in agentcore/.env.local. Scaffold the variable name there and fill the value yourself — never commit the key. With --model-provider Bedrock you authenticate with your AWS credentials instead, and the execution role needs bedrock:InvokeModel.
Reading legacy tutorials: the starter-toolkit verbs
A large fraction of existing AgentCore content uses the legacy bedrock-agentcore-starter-toolkit. Here is the equivalent loop so you can follow it. Note that the default build path uses AWS CodeBuild — no local Docker required.
pip install bedrock-agentcore-starter-toolkit
# 1. configure — generates .bedrock_agentcore.yaml + a Dockerfile
agentcore configure -e my_agent.py --name my_agent
# 2. launch (a.k.a. deploy) — default builds ARM64 via CodeBuild, pushes to ECR,
# creates the Runtime, and prints the agent runtime ARN
agentcore launch
# 3. invoke — session id must be >= 33 chars
agentcore invoke '{"prompt":"What is the weather?"}'
# 4. status — agent ARN, endpoint, log group
agentcore status -v
# 5. teardown
agentcore destroy --delete-ecr-repoKey configure flags: -e/--entrypoint (required), -n/--name, -er/--execution-role, -ecr/--ecr, -dt/--deployment-type (direct_code_deploy | container), -rf/--requirements-file, -do/--disable-otel, -ac/--authorizer-config (inbound JWT JSON), --vpc/--subnets/--security-groups, -p/--protocol (HTTP | MCP | A2A), -r/--region, -ni/--non-interactive. Useful launch flags: -l/--local (build + run locally; needs Docker/Finch/Podman), -lb/--local-build (build locally, deploy to cloud), -env/--env KEY=VALUE, -auc/--auto-update-on-conflict.
Verb mapping at a glance:
| Step | Legacy toolkit CLI | New CLI (@aws/agentcore) | Python API |
|---|---|---|---|
| Scaffold/config | configure -e agent.py | create --name MyAgent | runtime.configure(...) |
| Local iterate | launch --local / python agent.py | dev | runtime.launch(local=True) |
| Ship | launch (a.k.a. deploy) | deploy | runtime.launch() |
| Call it | invoke '{...}' | invoke "..." | runtime.invoke({...}) |
| Inspect | status | status / logs / traces | — |
| Tear down | destroy | remove all | — |
The Python Runtime API never renames the verb — it is always .launch():
from bedrock_agentcore_starter_toolkit import Runtime
runtime = Runtime()
runtime.configure(
entrypoint="my_agent.py",
auto_create_execution_role=True,
auto_create_ecr=True,
requirements_file="requirements.txt",
region="us-east-1",
agent_name="my_agent",
)
runtime.launch() # same operation the CLI calls "deploy"
runtime.invoke({"prompt": "What is the weather?"})Key insight
launch vs deploy is the same button
The verb mismatch is purely naming. The devguide and Python API say launch/.launch(); the v0.3.x toolkit CLI says deploy (and destroy for teardown); the new npm CLI also says deploy. They all package an ARM64 agent and create the Runtime. When a tutorial's command 404s, check whether you're running the verb its CLI version expects.
Two build modes: CodeZip vs Container
Whichever CLI you use, deployment ultimately packages your agent one of two ways. The choice matters for Docker requirements, size limits, and which IAM actions you need.
| CodeZip (default) | Container | |
|---|---|---|
| Docker required? | No — zip → uploaded to S3 | Yes — build + push an image to ECR |
| Size limits | 250 MB compressed / 750 MB uncompressed | up to ~2 GB image (verify live quotas) |
| Architecture | handled automatically | ARM64 only — you must build for it |
| Execution-role ECR actions | not needed | required (BatchGetImage, etc.) |
| When to use | most agents; fastest path | custom system dependencies, non-Python tooling |
CodeZip is the default and the path of least resistance — no Docker, no ECR, just a zip to S3. Reach for Container only when you need system-level dependencies the zip can't carry.
The Runtime runs on AWS Graviton (ARM64). CodeZip and the CLIs handle the architecture for you, but a hand-built container must target linux/arm64. An amd64 image is one of the most common deploy failures — and it fails silently at invoke time, not at build time:
# Container build MUST be ARM64
docker buildx build --platform linux/arm64 -t my-agent:arm64 .In the legacy toolkit, the default launch builds ARM64 in CodeBuild (no local Docker); only --local / --local-build need a local container runtime (Docker, Finch, or Podman). In the new CLI, pick the mode at scaffold time with agentcore create --build CodeZip|Container.
Watch out
amd64 fails silently
If you build a container on an x86 laptop without --platform linux/arm64, the image pushes and the deploy reports success — then every invoke fails because the binary can't run on Graviton. Always pass --platform linux/arm64 to docker buildx build, or stay on CodeZip and let the toolchain handle the arch.
The deploy gotchas checklist
Most failed first deploys are one of a short, well-known list. Run through it before you debug anything exotic.
- Wrong
agentcorebinary. Two CLIs, different verbs.configure/launchis legacy;create/dev/deployis new. Confirm which is on yourPATH. launchvsdeploy. Match your CLI version (Python API is always.launch()).- amd64 image. The Runtime is ARM64 (Graviton). A wrong-arch container fails silently at invoke. Build with
docker buildx build --platform linux/arm64, or use CodeZip. - Docker assumed but not needed. CodeZip (default) needs no Docker; the legacy default builds via CodeBuild. Don't install Docker chasing a problem you don't have.
- Bedrock model access not enabled. If you call Bedrock models, you must enable model access in the Bedrock console for that account/region first — otherwise invokes return access-denied.
- Session ID too short.
runtimeSessionIdmust be ≥ 33 characters. A short ID (e.g."abc") is rejected. Use a UUID. (The exact 33-char minimum is commonly cited — confirm in the live API reference.) - Missing
iam:PassRole. The deployer needs to pass the execution role to the service. - CDK not bootstrapped (new CLI). Run
cdk bootstrap aws://<account>/<region>once per account+region. - Container vs direct-code role mismatch. Container deploys need ECR read actions on the execution role; CodeZip does not. Using a CodeZip role for a Container deploy fails on image pull.
- Forgetting
aws-opentelemetry-distro. Add it torequirements.txtto get built-in tracing; without it your traces are empty. - Port 8080 in use.
agentcore devbinds 8080. Free the port or runagentcore dev -p 3000.
When invoking from boto3 directly (the SigV4 data-plane path), the session-ID rule shows up concretely:
import json, uuid, boto3
client = boto3.client("bedrock-agentcore") # data plane
resp = client.invoke_agent_runtime(
agentRuntimeArn="arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/MyAgent-XXXX",
runtimeSessionId=str(uuid.uuid4()), # >= 33 chars; reuse for context/affinity
payload=json.dumps({"prompt": "Tell me a joke"}).encode(),
qualifier="DEFAULT",
)
print(json.loads("".join(c.decode("utf-8") for c in resp.get("response", []))))Watch out
OAuth-inbound agents can't use the AWS SDK to invoke
If your Runtime uses OAuth/JWT inbound auth instead of SigV4, you cannot call InvokeAgentRuntime through the AWS SDK — you must make a raw HTTPS request carrying the bearer token. The boto3 snippet above is for SigV4 (IAM) inbound auth only.
Try it: Deploy an agent end-to-end with the new CLI, then break and fix it
Goal: run the full new-CLI loop, deploy a Strands agent on CodeZip, then reproduce and fix two canonical gotchas.
Setup (one-time per account/region).
- Confirm prerequisites:
node --version(20+),python --version(3.10+),aws sts get-caller-identity. - Bootstrap CDK:
cdk bootstrap aws://<account-id>/us-east-1. Note what happens if you skip this in step 5. - Ensure your identity has
BedrockAgentCoreFullAccess(or equivalent includingiam:PassRole). Enable Bedrock model access for your chosen model in the Bedrock console.
Build and iterate.
4. Scaffold: agentcore create --name LabAgent --framework Strands --protocol HTTP --model-provider Bedrock --build CodeZip --memory none, then cd LabAgent.
5. Run agentcore dev. From another terminal, hit the local contract: curl -X POST http://localhost:8080/invocations -H 'Content-Type: application/json' -d '{"prompt":"Say hello"}'. Stop it, then re-run with agentcore dev -p 3000 to prove the port-8080 escape hatch.
Deploy and invoke.
6. agentcore deploy. When it finishes, run agentcore status and record the agent runtime ARN, endpoint, and log group.
7. agentcore invoke "Tell me a joke" --stream. Then agentcore logs and agentcore traces list to see the request land.
Reproduce two gotchas.
8. Short session ID. Invoke from boto3 with runtimeSessionId="abc" and capture the error. Fix it by switching to str(uuid.uuid4()) and confirm the call succeeds.
9. Verb mismatch. In a scratch venv, pip install bedrock-agentcore-starter-toolkit and run agentcore --help. Compare its verbs (configure/launch) to the new CLI's (create/dev/deploy). Write one sentence on how you'd tell which CLI a random tutorial assumes.
Tear down.
10. agentcore remove all to delete the stack. Confirm with agentcore status.
Reflect (3-4 sentences). When would you have chosen Container over CodeZip, and what extra IAM/build steps would that have added? Which gotcha would have cost you the most time without this checklist?
Key takeaways
- 1There are two CLIs that both install an `agentcore` binary with different verbs: the legacy `bedrock-agentcore-starter-toolkit` (`configure`/`launch`/`invoke`/`status`/`destroy`) and the current `@aws/agentcore` npm CLI (`create`/`dev`/`deploy`/`invoke`/`status`/`add`/`remove`/`logs`/`traces`). Pin which one a tutorial assumes.
- 2The new-CLI loop is `create` → `dev` (hot reload + inspector on :8080) → `deploy` (CDK → CloudFormation) → `invoke` → `status`/`logs`/`traces`, with `agentcore add memory|gateway|agent|credential|evaluator` to attach capabilities.
- 3Legacy mapping: `configure` (writes `.bedrock_agentcore.yaml` + Dockerfile, default build via CodeBuild) → `launch`/`deploy` → `invoke` → `status` → `destroy`. The Python `Runtime` API is always `.launch()` regardless of CLI verb naming.
- 4CodeZip is the default build — no Docker, limited to 250 MB compressed / 750 MB uncompressed. Container is for custom system deps and is ARM64-only: `docker buildx build --platform linux/arm64`. An amd64 image fails silently at invoke.
- 5Prerequisites for the new CLI: Node 20+, Python 3.10+, AWS credentials, and `cdk bootstrap`. Set up the execution role (trust principal `bedrock-agentcore.amazonaws.com` with SourceAccount/SourceArn) and a developer identity with `BedrockAgentCoreFullAccess`.
- 6Top deploy gotchas: confusing the two binaries; `launch` vs `deploy`; amd64 instead of ARM64; Bedrock model access not enabled; session ID under 33 chars; missing `iam:PassRole`; CDK not bootstrapped; forgetting `aws-opentelemetry-distro`; port 8080 already in use.
- 7Pricing, quotas, region lists, SDK versions, and the exact IAM action lists are fast-moving — treat them as values to verify against the live AWS pages, not timeless facts.
Quiz
Lock in what you learned
Check your understanding
0 / 4 answered
1.A tutorial tells you to run `agentcore configure -e agent.py` and then `agentcore deploy`, but `configure` errors as an unknown command. What is the most likely cause?
2.Your container-based agent deploys successfully and `agentcore status` looks healthy, but every `invoke` fails. You built the image on an x86 laptop with a plain `docker build`. What is the fix?
3.Your boto3 call to `client.invoke_agent_runtime(...)` is rejected for an invalid `runtimeSessionId`. You passed `runtimeSessionId="chat-1"`. What's wrong?
4.You run `agentcore deploy` with the new CLI for the first time in a fresh account and region. Deploy gets through packaging but fails at the infrastructure stage. Which prerequisite is most likely missing?
Go deeper
Hand-picked sources to keep learning
The canonical new-CLI walkthrough: create / dev / deploy / invoke and prerequisites.
Authoritative, frequently updated list of execution-role actions and the trust-policy conditions. Treat the exact actions as [VOLATILE] and verify here.
The legacy configure/launch/invoke toolkit and its docs site (aws.github.io/bedrock-agentcore-starter-toolkit). Marks itself (legacy) and points to the new CLI.
Source and changelog for the current npm CLI. Check the npm package for the latest version (versions are [VOLATILE]).
Verify the CodeZip 250 MB / 750 MB limits, image-size caps, and the session-ID minimum against the live page.
End-to-end deploy examples across frameworks and both build modes.