From a37b8a4a0ba1533bd8cf61fb36538912a1abddf6 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 17:25:19 +0000 Subject: [PATCH 1/6] feat: simplify hello-world into a framework-free agent-python template --- .../Dockerfile.template | 0 src/assets/templates/agent-python/README.md | 31 ++++++++++ .../dockerignore.template | 0 src/assets/templates/agent-python/main.py | 13 ++++ .../pyproject.toml | 5 +- .../hello-world-python-container/README.md | 33 ---------- .../hello-world-python-container/main.py | 17 ----- .../pyproject.toml | 19 ------ .../templates/hello-world-python/README.md | 62 ------------------- .../templates/hello-world-python/main.py | 17 ----- 10 files changed, 46 insertions(+), 151 deletions(-) rename src/assets/templates/{hello-world-python-container => agent-python}/Dockerfile.template (100%) create mode 100644 src/assets/templates/agent-python/README.md rename src/assets/templates/{hello-world-python-container => agent-python}/dockerignore.template (100%) create mode 100644 src/assets/templates/agent-python/main.py rename src/assets/templates/{hello-world-python => agent-python}/pyproject.toml (73%) delete mode 100644 src/assets/templates/hello-world-python-container/README.md delete mode 100644 src/assets/templates/hello-world-python-container/main.py delete mode 100644 src/assets/templates/hello-world-python-container/pyproject.toml delete mode 100644 src/assets/templates/hello-world-python/README.md delete mode 100644 src/assets/templates/hello-world-python/main.py diff --git a/src/assets/templates/hello-world-python-container/Dockerfile.template b/src/assets/templates/agent-python/Dockerfile.template similarity index 100% rename from src/assets/templates/hello-world-python-container/Dockerfile.template rename to src/assets/templates/agent-python/Dockerfile.template diff --git a/src/assets/templates/agent-python/README.md b/src/assets/templates/agent-python/README.md new file mode 100644 index 000000000..ed945bd99 --- /dev/null +++ b/src/assets/templates/agent-python/README.md @@ -0,0 +1,31 @@ +# agent-python + +A minimal AgentCore Runtime HTTP agent with no agent framework. Its +`@app.entrypoint` returns a fixed `Hello, world!` message for every +invocation — a starting point you own and grow into a real agent. + +## What's here + +- `main.py` — the agent. A `BedrockAgentCoreApp` wraps the entrypoint that + receives each invocation payload and returns the response. +- `pyproject.toml` — Python dependencies, managed with + [uv](https://docs.astral.sh/uv/). `agentcore project create` has already run + `uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready. + +## Develop + +Run the agent locally from the project root: + +```bash +agentcore project dev +``` + +Environment variables for local development go in `agentcore/.env.local` +(gitignored). + +## Deploy + +```bash +agentcore project deploy +agentcore project invoke runtime --payload '{"prompt":"Hello!"}' +``` diff --git a/src/assets/templates/hello-world-python-container/dockerignore.template b/src/assets/templates/agent-python/dockerignore.template similarity index 100% rename from src/assets/templates/hello-world-python-container/dockerignore.template rename to src/assets/templates/agent-python/dockerignore.template diff --git a/src/assets/templates/agent-python/main.py b/src/assets/templates/agent-python/main.py new file mode 100644 index 000000000..9882ec785 --- /dev/null +++ b/src/assets/templates/agent-python/main.py @@ -0,0 +1,13 @@ +from bedrock_agentcore.runtime import BedrockAgentCoreApp + +app = BedrockAgentCoreApp() + + +@app.entrypoint +def invoke(payload, context): + """Return a fixed greeting for every invocation.""" + return {"message": "Hello, world!"} + + +if __name__ == "__main__": + app.run() diff --git a/src/assets/templates/hello-world-python/pyproject.toml b/src/assets/templates/agent-python/pyproject.toml similarity index 73% rename from src/assets/templates/hello-world-python/pyproject.toml rename to src/assets/templates/agent-python/pyproject.toml index c352cc800..684d8f604 100644 --- a/src/assets/templates/hello-world-python/pyproject.toml +++ b/src/assets/templates/agent-python/pyproject.toml @@ -3,16 +3,15 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "hello-world" +name = "agent-python" version = "0.1.0" -description = "AgentCore Runtime application using the Strands SDK" +description = "Minimal AgentCore Runtime HTTP agent" readme = "README.md" requires-python = ">=3.10" dependencies = [ "aws-opentelemetry-distro ~= 0.18.0", "bedrock-agentcore ~= 1.9.1", "botocore[crt] ~= 1.43.0", - "strands-agents ~= 1.15.0", ] [tool.hatch.build.targets.wheel] diff --git a/src/assets/templates/hello-world-python-container/README.md b/src/assets/templates/hello-world-python-container/README.md deleted file mode 100644 index 190d41163..000000000 --- a/src/assets/templates/hello-world-python-container/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# hello-world - -An AgentCore Runtime agent built with the [Strands](https://strandsagents.com) -SDK. Scaffolded by `agentcore project create`. - -## Layout - -- `main.py` — the agent: a `BedrockAgentCoreApp` entrypoint that streams - responses from a Strands `Agent`. -- `pyproject.toml` — dependencies, installed with [uv](https://docs.astral.sh/uv/). - -## Develop - -Run the agent locally from the project root: - -```bash -agentcore project dev -``` - -Environment variables for local development go in `agentcore/.env.local` -(gitignored). - -## Deploy - -```bash -agentcore project deploy -``` - -Invoke the deployed Runtime with its native payload: - -```bash -agentcore project invoke runtime --payload '{"prompt":"Hello!"}' -``` diff --git a/src/assets/templates/hello-world-python-container/main.py b/src/assets/templates/hello-world-python-container/main.py deleted file mode 100644 index 182bfd57e..000000000 --- a/src/assets/templates/hello-world-python-container/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from bedrock_agentcore.runtime import BedrockAgentCoreApp -from strands import Agent - -app = BedrockAgentCoreApp() -agent = Agent(system_prompt="You are a helpful assistant.") - - -@app.entrypoint -async def invoke(payload, context): - """Stream the agent's response to the caller's prompt.""" - prompt = payload.get("prompt", "Hello!") - async for event in agent.stream_async(prompt): - yield event - - -if __name__ == "__main__": - app.run() diff --git a/src/assets/templates/hello-world-python-container/pyproject.toml b/src/assets/templates/hello-world-python-container/pyproject.toml deleted file mode 100644 index c352cc800..000000000 --- a/src/assets/templates/hello-world-python-container/pyproject.toml +++ /dev/null @@ -1,19 +0,0 @@ -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project] -name = "hello-world" -version = "0.1.0" -description = "AgentCore Runtime application using the Strands SDK" -readme = "README.md" -requires-python = ">=3.10" -dependencies = [ - "aws-opentelemetry-distro ~= 0.18.0", - "bedrock-agentcore ~= 1.9.1", - "botocore[crt] ~= 1.43.0", - "strands-agents ~= 1.15.0", -] - -[tool.hatch.build.targets.wheel] -packages = ["."] diff --git a/src/assets/templates/hello-world-python/README.md b/src/assets/templates/hello-world-python/README.md deleted file mode 100644 index d2cadd33d..000000000 --- a/src/assets/templates/hello-world-python/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# hello-world - -A minimal AgentCore Runtime agent built with the -[Strands Agents SDK](https://strandsagents.com) — our recommended framework -for building agents on AWS Bedrock AgentCore. - -## What's here - -- `main.py` — the agent. A `BedrockAgentCoreApp` wraps a Strands `Agent`; - the `@app.entrypoint` function receives each invocation payload and streams - the agent's response back to the caller. -- `pyproject.toml` — Python dependencies, managed with - [uv](https://docs.astral.sh/uv/). `agentcore project create` has already run - `uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready. - -## Run it locally - -```bash -uv run main.py -``` - -The app listens on http://localhost:8080. Invoke it: - -```bash -curl -X POST http://localhost:8080/invocations \ - -H "Content-Type: application/json" \ - -d '{"prompt": "Hello!"}' -``` - -## Build your agent - -Start in `main.py`: - -- Change the `system_prompt` to shape your agent's behavior. -- Give it tools — Strands ships ready-made ones and makes custom tools a - decorator away: - - ```python - from strands import Agent, tool - - @tool - def word_count(text: str) -> int: - """Count words in text.""" - return len(text.split()) - - agent = Agent(system_prompt="You are a helpful assistant.", tools=[word_count]) - ``` - -- Add dependencies with `uv add `. - -See the [Strands documentation](https://strandsagents.com/latest/documentation/docs/) -for multi-agent patterns, MCP tools, and model configuration. - -## Deploy - -Deploy from the project root with the AgentCore CLI; the CDK app under -`agentcore/cdk` provisions the Runtime that hosts this agent. - -```bash -agentcore project deploy -agentcore project invoke runtime --payload '{"prompt":"Hello!"}' -``` diff --git a/src/assets/templates/hello-world-python/main.py b/src/assets/templates/hello-world-python/main.py deleted file mode 100644 index 182bfd57e..000000000 --- a/src/assets/templates/hello-world-python/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from bedrock_agentcore.runtime import BedrockAgentCoreApp -from strands import Agent - -app = BedrockAgentCoreApp() -agent = Agent(system_prompt="You are a helpful assistant.") - - -@app.entrypoint -async def invoke(payload, context): - """Stream the agent's response to the caller's prompt.""" - prompt = payload.get("prompt", "Hello!") - async for event in agent.stream_async(prompt): - yield event - - -if __name__ == "__main__": - app.run() From 833e01797594d6f3aa82e321998104822b5103ce Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 17:25:29 +0000 Subject: [PATCH 2/6] refactor: rename runtime templates to a consistent naming convention --- README.md | 2 +- .../Dockerfile.template | 0 .../README.md | 0 .../dockerignore.template | 0 .../gitignore.template | 0 .../main.py | 0 .../memory/__init__.py | 0 .../memory/session.py | 0 .../model}/__init__.py | 0 .../model/load.py | 0 .../pyproject.toml | 0 .../Dockerfile.template | 0 .../README.md | 0 .../dockerignore.template | 0 .../gitignore.template | 0 .../main.py | 0 .../mcp_client}/__init__.py | 0 .../mcp_client/client.py | 0 .../memory/__init__.py | 0 .../memory/session.py | 0 .../model/__init__.py | 0 .../model/load.py | 0 .../model/mantle_compat.py | 0 .../pyproject.toml | 0 .../skills/fetcher.py | 0 .../Dockerfile.template | 0 .../README.md | 0 .../dockerignore.template | 0 .../gitignore.template | 0 .../main.ts | 0 .../mcp_client/client.ts | 0 .../memory/memory.ts | 0 .../model/load.ts | 0 .../package.json | 0 .../tsconfig.json | 0 .../Dockerfile.template | 0 .../README.md | 0 .../dockerignore.template | 0 .../gitignore.template | 0 .../main.py | 0 .../pyproject.toml | 0 src/core/project/manager.export.test.ts | 2 +- src/core/project/manager.test.ts | 18 +- src/core/project/templates/export.ts | 2 +- src/core/project/templates/runtime.ts | 24 +-- .../project/add/gateway-test-support.ts | 2 +- .../project/add/online-eval/index.test.ts | 2 +- .../project/add/online-insight/index.test.ts | 2 +- .../project/add/payment-test-support.ts | 2 +- .../project/add/runtime/index.test.ts | 158 +++++++++--------- src/handlers/project/add/runtime/index.ts | 2 +- .../project/create/create.screen.test.tsx | 30 ++-- src/handlers/project/create/screen.tsx | 33 ++-- src/handlers/project/export/harness.test.ts | 2 +- src/handlers/project/project.test.ts | 51 ++---- src/handlers/project/remove/index.test.ts | 2 +- src/handlers/project/shortcuts.ts | 18 +- 57 files changed, 162 insertions(+), 190 deletions(-) rename src/assets/templates/{python-mcp => a2a-python-strands}/Dockerfile.template (100%) rename src/assets/templates/{strands-py-a2a => a2a-python-strands}/README.md (100%) rename src/assets/templates/{python-mcp => a2a-python-strands}/dockerignore.template (100%) rename src/assets/templates/{python-mcp => a2a-python-strands}/gitignore.template (100%) rename src/assets/templates/{strands-py-a2a => a2a-python-strands}/main.py (100%) rename src/assets/templates/{strands-http-python => a2a-python-strands}/memory/__init__.py (100%) rename src/assets/templates/{strands-http-python => a2a-python-strands}/memory/session.py (100%) rename src/assets/templates/{strands-http-python/mcp_client => a2a-python-strands/model}/__init__.py (100%) rename src/assets/templates/{strands-py-a2a => a2a-python-strands}/model/load.py (100%) rename src/assets/templates/{strands-py-a2a => a2a-python-strands}/pyproject.toml (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/Dockerfile.template (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/README.md (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/dockerignore.template (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/gitignore.template (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/main.py (100%) rename src/assets/templates/{strands-http-python/model => agent-python-strands/mcp_client}/__init__.py (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/mcp_client/client.py (100%) rename src/assets/templates/{strands-py-a2a => agent-python-strands}/memory/__init__.py (100%) rename src/assets/templates/{strands-py-a2a => agent-python-strands}/memory/session.py (100%) rename src/assets/templates/{strands-py-a2a => agent-python-strands}/model/__init__.py (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/model/load.py (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/model/mantle_compat.py (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/pyproject.toml (100%) rename src/assets/templates/{strands-http-python => agent-python-strands}/skills/fetcher.py (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/Dockerfile.template (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/README.md (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/dockerignore.template (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/gitignore.template (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/main.ts (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/mcp_client/client.ts (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/memory/memory.ts (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/model/load.ts (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/package.json (100%) rename src/assets/templates/{strands-http-typescript => agent-typescript-strands}/tsconfig.json (100%) rename src/assets/templates/{strands-py-a2a => mcp-python-fastmcp}/Dockerfile.template (100%) rename src/assets/templates/{python-mcp => mcp-python-fastmcp}/README.md (100%) rename src/assets/templates/{strands-py-a2a => mcp-python-fastmcp}/dockerignore.template (100%) rename src/assets/templates/{strands-py-a2a => mcp-python-fastmcp}/gitignore.template (100%) rename src/assets/templates/{python-mcp => mcp-python-fastmcp}/main.py (100%) rename src/assets/templates/{python-mcp => mcp-python-fastmcp}/pyproject.toml (100%) diff --git a/README.md b/README.md index 155abc14b..6b7f37f70 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ cd MyAssistant && agentcore project deploy agentcore harness invoke --id --prompt "hello" # Scaffold runtime code instead (pass a template or framework flags). -agentcore project create --name MyAgent --template strands-python +agentcore project create --name MyAgent --template agent-python-strands # Translate an existing Amazon Bedrock Agent version into editable runtime code. # The selected alias identifies the immutable source version; generated code diff --git a/src/assets/templates/python-mcp/Dockerfile.template b/src/assets/templates/a2a-python-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/python-mcp/Dockerfile.template rename to src/assets/templates/a2a-python-strands/Dockerfile.template diff --git a/src/assets/templates/strands-py-a2a/README.md b/src/assets/templates/a2a-python-strands/README.md similarity index 100% rename from src/assets/templates/strands-py-a2a/README.md rename to src/assets/templates/a2a-python-strands/README.md diff --git a/src/assets/templates/python-mcp/dockerignore.template b/src/assets/templates/a2a-python-strands/dockerignore.template similarity index 100% rename from src/assets/templates/python-mcp/dockerignore.template rename to src/assets/templates/a2a-python-strands/dockerignore.template diff --git a/src/assets/templates/python-mcp/gitignore.template b/src/assets/templates/a2a-python-strands/gitignore.template similarity index 100% rename from src/assets/templates/python-mcp/gitignore.template rename to src/assets/templates/a2a-python-strands/gitignore.template diff --git a/src/assets/templates/strands-py-a2a/main.py b/src/assets/templates/a2a-python-strands/main.py similarity index 100% rename from src/assets/templates/strands-py-a2a/main.py rename to src/assets/templates/a2a-python-strands/main.py diff --git a/src/assets/templates/strands-http-python/memory/__init__.py b/src/assets/templates/a2a-python-strands/memory/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/memory/__init__.py rename to src/assets/templates/a2a-python-strands/memory/__init__.py diff --git a/src/assets/templates/strands-http-python/memory/session.py b/src/assets/templates/a2a-python-strands/memory/session.py similarity index 100% rename from src/assets/templates/strands-http-python/memory/session.py rename to src/assets/templates/a2a-python-strands/memory/session.py diff --git a/src/assets/templates/strands-http-python/mcp_client/__init__.py b/src/assets/templates/a2a-python-strands/model/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/mcp_client/__init__.py rename to src/assets/templates/a2a-python-strands/model/__init__.py diff --git a/src/assets/templates/strands-py-a2a/model/load.py b/src/assets/templates/a2a-python-strands/model/load.py similarity index 100% rename from src/assets/templates/strands-py-a2a/model/load.py rename to src/assets/templates/a2a-python-strands/model/load.py diff --git a/src/assets/templates/strands-py-a2a/pyproject.toml b/src/assets/templates/a2a-python-strands/pyproject.toml similarity index 100% rename from src/assets/templates/strands-py-a2a/pyproject.toml rename to src/assets/templates/a2a-python-strands/pyproject.toml diff --git a/src/assets/templates/strands-http-python/Dockerfile.template b/src/assets/templates/agent-python-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-http-python/Dockerfile.template rename to src/assets/templates/agent-python-strands/Dockerfile.template diff --git a/src/assets/templates/strands-http-python/README.md b/src/assets/templates/agent-python-strands/README.md similarity index 100% rename from src/assets/templates/strands-http-python/README.md rename to src/assets/templates/agent-python-strands/README.md diff --git a/src/assets/templates/strands-http-python/dockerignore.template b/src/assets/templates/agent-python-strands/dockerignore.template similarity index 100% rename from src/assets/templates/strands-http-python/dockerignore.template rename to src/assets/templates/agent-python-strands/dockerignore.template diff --git a/src/assets/templates/strands-http-python/gitignore.template b/src/assets/templates/agent-python-strands/gitignore.template similarity index 100% rename from src/assets/templates/strands-http-python/gitignore.template rename to src/assets/templates/agent-python-strands/gitignore.template diff --git a/src/assets/templates/strands-http-python/main.py b/src/assets/templates/agent-python-strands/main.py similarity index 100% rename from src/assets/templates/strands-http-python/main.py rename to src/assets/templates/agent-python-strands/main.py diff --git a/src/assets/templates/strands-http-python/model/__init__.py b/src/assets/templates/agent-python-strands/mcp_client/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/model/__init__.py rename to src/assets/templates/agent-python-strands/mcp_client/__init__.py diff --git a/src/assets/templates/strands-http-python/mcp_client/client.py b/src/assets/templates/agent-python-strands/mcp_client/client.py similarity index 100% rename from src/assets/templates/strands-http-python/mcp_client/client.py rename to src/assets/templates/agent-python-strands/mcp_client/client.py diff --git a/src/assets/templates/strands-py-a2a/memory/__init__.py b/src/assets/templates/agent-python-strands/memory/__init__.py similarity index 100% rename from src/assets/templates/strands-py-a2a/memory/__init__.py rename to src/assets/templates/agent-python-strands/memory/__init__.py diff --git a/src/assets/templates/strands-py-a2a/memory/session.py b/src/assets/templates/agent-python-strands/memory/session.py similarity index 100% rename from src/assets/templates/strands-py-a2a/memory/session.py rename to src/assets/templates/agent-python-strands/memory/session.py diff --git a/src/assets/templates/strands-py-a2a/model/__init__.py b/src/assets/templates/agent-python-strands/model/__init__.py similarity index 100% rename from src/assets/templates/strands-py-a2a/model/__init__.py rename to src/assets/templates/agent-python-strands/model/__init__.py diff --git a/src/assets/templates/strands-http-python/model/load.py b/src/assets/templates/agent-python-strands/model/load.py similarity index 100% rename from src/assets/templates/strands-http-python/model/load.py rename to src/assets/templates/agent-python-strands/model/load.py diff --git a/src/assets/templates/strands-http-python/model/mantle_compat.py b/src/assets/templates/agent-python-strands/model/mantle_compat.py similarity index 100% rename from src/assets/templates/strands-http-python/model/mantle_compat.py rename to src/assets/templates/agent-python-strands/model/mantle_compat.py diff --git a/src/assets/templates/strands-http-python/pyproject.toml b/src/assets/templates/agent-python-strands/pyproject.toml similarity index 100% rename from src/assets/templates/strands-http-python/pyproject.toml rename to src/assets/templates/agent-python-strands/pyproject.toml diff --git a/src/assets/templates/strands-http-python/skills/fetcher.py b/src/assets/templates/agent-python-strands/skills/fetcher.py similarity index 100% rename from src/assets/templates/strands-http-python/skills/fetcher.py rename to src/assets/templates/agent-python-strands/skills/fetcher.py diff --git a/src/assets/templates/strands-http-typescript/Dockerfile.template b/src/assets/templates/agent-typescript-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-http-typescript/Dockerfile.template rename to src/assets/templates/agent-typescript-strands/Dockerfile.template diff --git a/src/assets/templates/strands-http-typescript/README.md b/src/assets/templates/agent-typescript-strands/README.md similarity index 100% rename from src/assets/templates/strands-http-typescript/README.md rename to src/assets/templates/agent-typescript-strands/README.md diff --git a/src/assets/templates/strands-http-typescript/dockerignore.template b/src/assets/templates/agent-typescript-strands/dockerignore.template similarity index 100% rename from src/assets/templates/strands-http-typescript/dockerignore.template rename to src/assets/templates/agent-typescript-strands/dockerignore.template diff --git a/src/assets/templates/strands-http-typescript/gitignore.template b/src/assets/templates/agent-typescript-strands/gitignore.template similarity index 100% rename from src/assets/templates/strands-http-typescript/gitignore.template rename to src/assets/templates/agent-typescript-strands/gitignore.template diff --git a/src/assets/templates/strands-http-typescript/main.ts b/src/assets/templates/agent-typescript-strands/main.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/main.ts rename to src/assets/templates/agent-typescript-strands/main.ts diff --git a/src/assets/templates/strands-http-typescript/mcp_client/client.ts b/src/assets/templates/agent-typescript-strands/mcp_client/client.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/mcp_client/client.ts rename to src/assets/templates/agent-typescript-strands/mcp_client/client.ts diff --git a/src/assets/templates/strands-http-typescript/memory/memory.ts b/src/assets/templates/agent-typescript-strands/memory/memory.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/memory/memory.ts rename to src/assets/templates/agent-typescript-strands/memory/memory.ts diff --git a/src/assets/templates/strands-http-typescript/model/load.ts b/src/assets/templates/agent-typescript-strands/model/load.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/model/load.ts rename to src/assets/templates/agent-typescript-strands/model/load.ts diff --git a/src/assets/templates/strands-http-typescript/package.json b/src/assets/templates/agent-typescript-strands/package.json similarity index 100% rename from src/assets/templates/strands-http-typescript/package.json rename to src/assets/templates/agent-typescript-strands/package.json diff --git a/src/assets/templates/strands-http-typescript/tsconfig.json b/src/assets/templates/agent-typescript-strands/tsconfig.json similarity index 100% rename from src/assets/templates/strands-http-typescript/tsconfig.json rename to src/assets/templates/agent-typescript-strands/tsconfig.json diff --git a/src/assets/templates/strands-py-a2a/Dockerfile.template b/src/assets/templates/mcp-python-fastmcp/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-py-a2a/Dockerfile.template rename to src/assets/templates/mcp-python-fastmcp/Dockerfile.template diff --git a/src/assets/templates/python-mcp/README.md b/src/assets/templates/mcp-python-fastmcp/README.md similarity index 100% rename from src/assets/templates/python-mcp/README.md rename to src/assets/templates/mcp-python-fastmcp/README.md diff --git a/src/assets/templates/strands-py-a2a/dockerignore.template b/src/assets/templates/mcp-python-fastmcp/dockerignore.template similarity index 100% rename from src/assets/templates/strands-py-a2a/dockerignore.template rename to src/assets/templates/mcp-python-fastmcp/dockerignore.template diff --git a/src/assets/templates/strands-py-a2a/gitignore.template b/src/assets/templates/mcp-python-fastmcp/gitignore.template similarity index 100% rename from src/assets/templates/strands-py-a2a/gitignore.template rename to src/assets/templates/mcp-python-fastmcp/gitignore.template diff --git a/src/assets/templates/python-mcp/main.py b/src/assets/templates/mcp-python-fastmcp/main.py similarity index 100% rename from src/assets/templates/python-mcp/main.py rename to src/assets/templates/mcp-python-fastmcp/main.py diff --git a/src/assets/templates/python-mcp/pyproject.toml b/src/assets/templates/mcp-python-fastmcp/pyproject.toml similarity index 100% rename from src/assets/templates/python-mcp/pyproject.toml rename to src/assets/templates/mcp-python-fastmcp/pyproject.toml diff --git a/src/core/project/manager.export.test.ts b/src/core/project/manager.export.test.ts index 1c54253cd..6ba6099f7 100644 --- a/src/core/project/manager.export.test.ts +++ b/src/core/project/manager.export.test.ts @@ -61,7 +61,7 @@ async function projectWithHarness( name: "orders", skipInstall: true, skipGit: true, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("hello-world-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python"), }), ); project = await drain( diff --git a/src/core/project/manager.test.ts b/src/core/project/manager.test.ts index a9aa4f9e1..6c01ef979 100644 --- a/src/core/project/manager.test.ts +++ b/src/core/project/manager.test.ts @@ -25,12 +25,14 @@ import { import { createSilentLogger, TestIdentityClient } from "../../testing"; import type { DeployBackendInput, ProjectBackend } from "./backends/types"; -const HELLO_WORLD_PYTHON = resolveRuntimeTemplateShortcut("hello-world-python"); -const HELLO_WORLD_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("hello-world-python-container"); -const STRANDS_PYTHON = resolveRuntimeTemplateShortcut("strands-python"); -const STRANDS_TS = resolveRuntimeTemplateShortcut("strands-ts"); -const STRANDS_PY_A2A = resolveRuntimeTemplateShortcut("strands-py-a2a"); -const STRANDS_PY_A2A_CONTAINER = resolveRuntimeTemplateShortcut("strands-py-a2a", { +const HELLO_WORLD_PYTHON = resolveRuntimeTemplateShortcut("agent-python"); +const HELLO_WORLD_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("agent-python", { + build: "Container", +}); +const STRANDS_PYTHON = resolveRuntimeTemplateShortcut("agent-python-strands"); +const STRANDS_TS = resolveRuntimeTemplateShortcut("agent-typescript-strands"); +const STRANDS_PY_A2A = resolveRuntimeTemplateShortcut("a2a-python-strands"); +const STRANDS_PY_A2A_CONTAINER = resolveRuntimeTemplateShortcut("a2a-python-strands", { build: "Container", }); @@ -289,12 +291,12 @@ describe("FsProjectManager.create", () => { test.each([ [ "Python", - resolveRuntimeTemplateShortcut("strands-python", { build: "Container" }), + resolveRuntimeTemplateShortcut("agent-python-strands", { build: "Container" }), ["uv", "lock"], ], [ "TypeScript", - resolveRuntimeTemplateShortcut("strands-ts", { build: "Container" }), + resolveRuntimeTemplateShortcut("agent-typescript-strands", { build: "Container" }), ["npm", "install", "--package-lock-only"], ], ])( diff --git a/src/core/project/templates/export.ts b/src/core/project/templates/export.ts index fd882b04a..fb0c37d0e 100644 --- a/src/core/project/templates/export.ts +++ b/src/core/project/templates/export.ts @@ -53,7 +53,7 @@ export interface HarnessExportInput { /** The pure mapping result; the project manager executes it against the filesystem. */ export interface HarnessExportPlan { - /** Handlebars context for rendering the strands-http-python template. */ + /** Handlebars context for rendering the export-harness-python template. */ context: Record; /** The runtimes[] entry to append to agentcore.json. */ runtime: ProjectRuntime; diff --git a/src/core/project/templates/runtime.ts b/src/core/project/templates/runtime.ts index b3fc98117..ddfd9fd86 100644 --- a/src/core/project/templates/runtime.ts +++ b/src/core/project/templates/runtime.ts @@ -90,16 +90,18 @@ const importBedrockAgentResolver = () => async (input: RuntimeResourceConfig) => const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: TemplateRenderer) => ({ [buildResolverKey("none", "Python", "HTTP")]: async (input: RuntimeResourceConfig) => { if (input.scaffoldRuntimeInput.memory !== undefined) - throw new InputValidationError(`memory is not supported with the hello-world template`); + throw new InputValidationError(`memory is not supported with the agent-python template`); + const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, + { assetDir: "templates/agent-python" }, { - assetDir: - input.scaffoldRuntimeInput.build === "Container" - ? "templates/hello-world-python-container" - : "templates/hello-world-python", + rootDirName: input.name, + filter: (name) => { + if (name === "Dockerfile" || name === ".dockerignore") return isContainer; + return true; + }, }, - { rootDirName: input.name }, ); return { tree, spec: { runtimes: [buildRuntimeSpec(input)] } }; }, @@ -145,7 +147,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-http-python" }, + { assetDir: "templates/agent-python-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -166,7 +168,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa }, [buildResolverKey("strands", "TypeScript", "HTTP")]: async (input: RuntimeResourceConfig) => { if (input.protocol !== undefined && input.protocol !== "HTTP") - throw new InputValidationError("the strands-ts template only supports HTTP"); + throw new InputValidationError("the agent-typescript-strands template only supports HTTP"); const memory = input.scaffoldRuntimeInput.memory; // The TypeScript strands SDK's createAgentCoreMemoryStores requires at least one @@ -190,7 +192,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-http-typescript" }, + { assetDir: "templates/agent-typescript-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -241,7 +243,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/python-mcp" }, + { assetDir: "templates/mcp-python-fastmcp" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -292,7 +294,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-py-a2a" }, + { assetDir: "templates/a2a-python-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), diff --git a/src/handlers/project/add/gateway-test-support.ts b/src/handlers/project/add/gateway-test-support.ts index 9a422baff..e60f9976c 100644 --- a/src/handlers/project/add/gateway-test-support.ts +++ b/src/handlers/project/add/gateway-test-support.ts @@ -45,7 +45,7 @@ export function createGatewayProjectTestHarness(directoryPrefix: string) { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/online-eval/index.test.ts b/src/handlers/project/add/online-eval/index.test.ts index 10ca3dd73..62dd4d96b 100644 --- a/src/handlers/project/add/online-eval/index.test.ts +++ b/src/handlers/project/add/online-eval/index.test.ts @@ -47,7 +47,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/online-insight/index.test.ts b/src/handlers/project/add/online-insight/index.test.ts index 69f943cc5..03ba7c4ea 100644 --- a/src/handlers/project/add/online-insight/index.test.ts +++ b/src/handlers/project/add/online-insight/index.test.ts @@ -47,7 +47,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/payment-test-support.ts b/src/handlers/project/add/payment-test-support.ts index 66665c647..0e2322802 100644 --- a/src/handlers/project/add/payment-test-support.ts +++ b/src/handlers/project/add/payment-test-support.ts @@ -33,7 +33,7 @@ export function createPaymentProjectTestHarness(directoryPrefix: string) { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/runtime/index.test.ts b/src/handlers/project/add/runtime/index.test.ts index b0bcf0e42..17869ac44 100644 --- a/src/handlers/project/add/runtime/index.test.ts +++ b/src/handlers/project/add/runtime/index.test.ts @@ -78,7 +78,7 @@ function translatedImportPlan( } describe("project add runtime", () => { - const template = ["--template", "hello-world-python"]; + const template = ["--template", "agent-python"]; const allScaffoldingFlags = [ "--build", @@ -125,18 +125,15 @@ describe("project add runtime", () => { build: "Container", dockerfile: "Dockerfile", }, - "container template build override to CodeZip": { - build: "CodeZip", - }, "strands template overrides to Container": { build: "Container", dockerfile: "Dockerfile", }, - "py-mcp template preset": { + "mcp-python-fastmcp template preset": { build: "CodeZip", protocol: "MCP", }, - "py-mcp overrides to Container": { + "mcp-python-fastmcp overrides to Container": { build: "Container", dockerfile: "Dockerfile", protocol: "MCP", @@ -145,11 +142,11 @@ describe("project add runtime", () => { build: "CodeZip", protocol: "MCP", }, - "strands-py-a2a template preset": { + "a2a-python-strands template preset": { build: "CodeZip", protocol: "A2A", }, - "strands-py-a2a overrides to Container": { + "a2a-python-strands overrides to Container": { build: "Container", dockerfile: "Dockerfile", protocol: "A2A", @@ -188,17 +185,16 @@ describe("project add runtime", () => { test.each<[string, string[]]>([ ["template preset", ["--name", "my_agent", ...template]], [ - "container template preset", - ["--name", "my_agent", "--template", "hello-world-python-container"], + "agent-python-strands template preset", + ["--name", "my_agent", "--template", "agent-python-strands"], ], - ["strands-python template preset", ["--name", "my_agent", "--template", "strands-python"]], [ "template overrides to Container", [ "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", "--build", "Container", "--model-provider", @@ -208,22 +204,24 @@ describe("project add runtime", () => { ], ], [ - "container template build override to CodeZip", - ["--name", "my_agent", "--template", "hello-world-python-container", "--build", "CodeZip"], + "strands template overrides to Container", + ["--name", "my_agent", "--template", "agent-python-strands", "--build", "Container"], ], [ - "strands template overrides to Container", - ["--name", "my_agent", "--template", "strands-python", "--build", "Container"], + "mcp-python-fastmcp template preset", + ["--name", "my_mcp", "--template", "mcp-python-fastmcp"], ], - ["py-mcp template preset", ["--name", "my_mcp", "--template", "py-mcp"]], [ - "py-mcp overrides to Container", - ["--name", "my_mcp", "--template", "py-mcp", "--build", "Container"], + "mcp-python-fastmcp overrides to Container", + ["--name", "my_mcp", "--template", "mcp-python-fastmcp", "--build", "Container"], ], - ["strands-py-a2a template preset", ["--name", "my_a2a", "--template", "strands-py-a2a"]], [ - "strands-py-a2a overrides to Container", - ["--name", "my_a2a", "--template", "strands-py-a2a", "--build", "Container"], + "a2a-python-strands template preset", + ["--name", "my_a2a", "--template", "a2a-python-strands"], + ], + [ + "a2a-python-strands overrides to Container", + ["--name", "my_a2a", "--template", "a2a-python-strands", "--build", "Container"], ], [ "custom A2A runtime", @@ -245,12 +243,12 @@ describe("project add runtime", () => { ], ], [ - "strands-python with session, EFS, and S3 mounts", + "agent-python-strands with session, EFS, and S3 mounts", [ "--name", "fs_agent", "--template", - "strands-python", + "agent-python-strands", "--network-mode", "VPC", "--network-config", @@ -260,12 +258,12 @@ describe("project add runtime", () => { ], ], [ - "py-mcp with session, EFS, and S3 mounts", + "mcp-python-fastmcp with session, EFS, and S3 mounts", [ "--name", "fs_mcp", "--template", - "py-mcp", + "mcp-python-fastmcp", "--network-mode", "VPC", "--network-config", @@ -275,12 +273,12 @@ describe("project add runtime", () => { ], ], [ - "strands-py-a2a with session, EFS, and S3 mounts", + "a2a-python-strands with session, EFS, and S3 mounts", [ "--name", "fs_a2a", "--template", - "strands-py-a2a", + "a2a-python-strands", "--network-mode", "VPC", "--network-config", @@ -467,10 +465,7 @@ describe("project add runtime", () => { expect(runtime).toMatchObject({ entrypoint: "main.py", ...expectedSpecByLabel[label] }); expect(await Bun.file(join(projectRoot, "app", name, "main.py")).exists()).toBe(true); const buildFlagIndex = flags.indexOf("--build"); - const isContainer = - buildFlagIndex >= 0 - ? flags[buildFlagIndex + 1] === "Container" - : flags.includes("hello-world-python-container"); + const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "PYTHON_3_14"); expect(await Bun.file(join(projectRoot, "app", name, "Dockerfile")).exists()).toBe(isContainer); expect(await Bun.file(join(projectRoot, "app", name, ".dockerignore")).exists()).toBe( @@ -525,15 +520,15 @@ describe("project add runtime", () => { test.each<[string, string[], string[]]>([ [ "template preset defaults to long and short-term memory", - ["--name", "my_a2a", "--template", "strands-py-a2a"], + ["--name", "my_a2a", "--template", "a2a-python-strands"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], [ "template preset with --memory none", - ["--name", "my_a2a", "--template", "strands-py-a2a", "--memory", "none"], + ["--name", "my_a2a", "--template", "a2a-python-strands", "--memory", "none"], [], ], - ])("strands-py-a2a %s", async (_label, flags, expectedStrategies) => { + ])("a2a-python-strands %s", async (_label, flags, expectedStrategies) => { const projectRoot = await inProject(); await run(["add", "runtime", ...flags]); @@ -556,7 +551,7 @@ describe("project add runtime", () => { test.each<[string, string[], string[]]>([ [ "template preset", - ["--name", "my_agent", "--template", "strands-ts"], + ["--name", "my_agent", "--template", "agent-typescript-strands"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], [ @@ -579,43 +574,46 @@ describe("project add runtime", () => { ], [ "template overrides to Container", - ["--name", "my_agent", "--template", "strands-ts", "--build", "Container"], + ["--name", "my_agent", "--template", "agent-typescript-strands", "--build", "Container"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], - ])("strands-ts %s scaffolds a TypeScript agent", async (_label, flags, expectedStrategies) => { - const projectRoot = await inProject(); - await run(["add", "runtime", ...flags]); - - const buildFlagIndex = flags.indexOf("--build"); - const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; - - const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); - const runtime = spec.runtimes.find( - (candidate: { name: string }) => candidate.name === "my_agent", - ); - expect(runtime).toMatchObject({ - entrypoint: "main.js", - ...(isContainer - ? { build: "Container", dockerfile: "Dockerfile" } - : { build: "CodeZip", runtimeVersion: "NODE_22" }), - }); - expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "NODE_22"); - expect(await Bun.file(join(projectRoot, "app", "my_agent", "Dockerfile")).exists()).toBe( - isContainer, - ); - expect(await Bun.file(join(projectRoot, "app", "my_agent", ".dockerignore")).exists()).toBe( - isContainer, - ); - - const memory = (spec.memories ?? []).find( - (candidate: { name: string }) => candidate.name === "my_agentMemory", - ); - const strategies = memory?.strategies.map(({ type }: { type: string }) => type) ?? []; - expect(strategies).toEqual(expectedStrategies); - }); + ])( + "agent-typescript-strands %s scaffolds a TypeScript agent", + async (_label, flags, expectedStrategies) => { + const projectRoot = await inProject(); + await run(["add", "runtime", ...flags]); + + const buildFlagIndex = flags.indexOf("--build"); + const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; + + const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); + const runtime = spec.runtimes.find( + (candidate: { name: string }) => candidate.name === "my_agent", + ); + expect(runtime).toMatchObject({ + entrypoint: "main.js", + ...(isContainer + ? { build: "Container", dockerfile: "Dockerfile" } + : { build: "CodeZip", runtimeVersion: "NODE_22" }), + }); + expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "NODE_22"); + expect(await Bun.file(join(projectRoot, "app", "my_agent", "Dockerfile")).exists()).toBe( + isContainer, + ); + expect(await Bun.file(join(projectRoot, "app", "my_agent", ".dockerignore")).exists()).toBe( + isContainer, + ); + + const memory = (spec.memories ?? []).find( + (candidate: { name: string }) => candidate.name === "my_agentMemory", + ); + const strategies = memory?.strategies.map(({ type }: { type: string }) => type) ?? []; + expect(strategies).toEqual(expectedStrategies); + }, + ); test.each<[string, string[]]>([ - ["missing --name", ["--template", "hello-world-python"]], + ["missing --name", ["--template", "agent-python"]], [ "missing --build without --template", [ @@ -632,8 +630,8 @@ describe("project add runtime", () => { ], ], [ - "--protocol cannot override the strands-python template", - ["--name", "my_agent", "--template", "strands-python", "--protocol", "MCP"], + "--protocol cannot override the agent-python-strands template", + ["--name", "my_agent", "--template", "agent-python-strands", "--protocol", "MCP"], ], [ "TypeScript without a strands template has no resolver", @@ -651,7 +649,7 @@ describe("project add runtime", () => { ], ], [ - "strands-ts rejects short-term-only memory", + "agent-typescript-strands rejects short-term-only memory", [ "--name", "my_agent", @@ -672,12 +670,12 @@ describe("project add runtime", () => { ["--name", "my_agent", ...template, "--network-config", "{bad}"], ], [ - "--protocol cannot override the hello-world-python template", - ["--name", "my_agent", "--template", "hello-world-python", "--protocol", "MCP"], + "--protocol cannot override the agent-python template", + ["--name", "my_agent", "--template", "agent-python", "--protocol", "MCP"], ], [ - "py-mcp does not support memory", - ["--name", "my_agent", "--template", "py-mcp", "--memory", "shortTerm"], + "mcp-python-fastmcp does not support memory", + ["--name", "my_agent", "--template", "mcp-python-fastmcp", "--memory", "shortTerm"], ], [ "--protocol alone requires --framework and --language", @@ -685,7 +683,7 @@ describe("project add runtime", () => { ], [ "--protocol cannot override a template", - ["--name", "my_agent", "--template", "py-mcp", "--protocol", "MCP"], + ["--name", "my_agent", "--template", "mcp-python-fastmcp", "--protocol", "MCP"], ], [ "custom MCP runtime does not support memory", @@ -758,7 +756,7 @@ describe("project add runtime", () => { "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", `--${flagName}`, value, ]), @@ -777,7 +775,7 @@ describe("project add runtime", () => { "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", "--api-key", `file://${apiKeyPath}`, ]), @@ -925,7 +923,7 @@ describe("project add runtime --type import", () => { const core = new TestCoreClient(); core.bedrockAgentImportPlans["A1B2C3D4E5/TSTALIASID"] = translatedImportPlan(); await expect(run([...importArgs, "--framework", "strands"], { core })).resolves.toBeDefined(); - await expect(run([...importArgs, "--template", "hello-world-python"])).rejects.toThrow( + await expect(run([...importArgs, "--template", "agent-python"])).rejects.toThrow( /--template cannot be combined/, ); await expect(run([...importArgs, "--build", "Container"])).rejects.toThrow( diff --git a/src/handlers/project/add/runtime/index.ts b/src/handlers/project/add/runtime/index.ts index f3148e219..4f629e7c5 100644 --- a/src/handlers/project/add/runtime/index.ts +++ b/src/handlers/project/add/runtime/index.ts @@ -226,7 +226,7 @@ export const createAddRuntimeHandler = (config: AddProjectResourceConfig) => ? LANGUAGE_VERSION_DEFAULTS[flags.language ?? "Python"] : undefined, }) - : resolveRuntimeTemplateShortcut("hello-world-python", { runtimeName: flags.name }); + : resolveRuntimeTemplateShortcut("agent-python", { runtimeName: flags.name }); const inputEnvironmentVariables = parseJsonFlag>( "environment-variables", diff --git a/src/handlers/project/create/create.screen.test.tsx b/src/handlers/project/create/create.screen.test.tsx index 10cb73945..a1356cddb 100644 --- a/src/handlers/project/create/create.screen.test.tsx +++ b/src/handlers/project/create/create.screen.test.tsx @@ -282,14 +282,14 @@ describe("project create wizard", () => { await waitForText(r.lastFrame, "● scaffolded agent code"); await r.press("return"); - // Template step: the three refactor-supported templates are offered. + // Template step: the supported templates are offered. await waitForText(r.lastFrame, "choose a template"); - expect(r.lastFrame()).toContain("hello-world-python"); - expect(r.lastFrame()).toContain("hello-world-python-container"); - expect(r.lastFrame()).toContain("● strands-python (recommended)"); + expect(r.lastFrame()).toContain("mcp-python-fastmcp"); + expect(r.lastFrame()).toContain("a2a-python-strands"); + expect(r.lastFrame()).toContain("● agent-python-strands (recommended)"); const templateFrame = r.lastFrame() ?? ""; - expect(templateFrame.indexOf("strands-python")).toBeLessThan( - templateFrame.indexOf("hello-world-python"), + expect(templateFrame.indexOf("agent-python-strands")).toBeLessThan( + templateFrame.indexOf("mcp-python-fastmcp"), ); await r.press("return"); @@ -306,18 +306,18 @@ describe("project create wizard", () => { line.includes("this project will be created"), ); expect(reviewLines[reviewHeading + 1] ?? "").toContain("─"); - expect(r.lastFrame()).toContain("strands-python"); + expect(r.lastFrame()).toContain("agent-python-strands"); expect(r.lastFrame()).toContain("long and short-term"); await r.press("return"); await waitForText(r.lastFrame, "project created in ./StrandsApp", 5000); - // Identical to the flag-driven `--template strands-python` input. + // Identical to the flag-driven `--template agent-python-strands` input. expect(inputs).toEqual([ { name: "StrandsApp", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("strands-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python-strands"), }, ]); @@ -344,7 +344,7 @@ describe("project create wizard", () => { await r.press("down"); await r.press("return"); await waitForText(r.lastFrame, "choose a template"); - await r.press("return"); // strands-python is preselected + await r.press("return"); // agent-python-strands is preselected await waitForText(r.lastFrame, "choose a memory configuration"); await r.press("down"); // none await waitForText(r.lastFrame, "● none"); @@ -357,7 +357,9 @@ describe("project create wizard", () => { name: "BareStrands", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("strands-python", { memory: "none" }), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python-strands", { + memory: "none", + }), }); r.unmount(); }, 10000); @@ -375,8 +377,8 @@ describe("project create wizard", () => { await r.press("down"); await r.press("return"); await waitForText(r.lastFrame, "choose a template"); - await r.press("down"); // hello-world-python - await waitForText(r.lastFrame, "● hello-world-python "); + await r.press("down"); // agent-python + await waitForText(r.lastFrame, "● agent-python "); await r.press("return"); // Straight to review: hello-world does not support memory. @@ -389,7 +391,7 @@ describe("project create wizard", () => { name: "HelloApp", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("hello-world-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python"), }); r.unmount(); }, 10000); diff --git a/src/handlers/project/create/screen.tsx b/src/handlers/project/create/screen.tsx index bb31f661f..55048312a 100644 --- a/src/handlers/project/create/screen.tsx +++ b/src/handlers/project/create/screen.tsx @@ -99,7 +99,7 @@ function emptyCreateProjectForm(): CreateProjectFormValues { name: "", kind: "harness", model: emptyProjectModel(), - template: "strands-python", + template: "agent-python-strands", memory: "longAndShortTerm", }; } @@ -123,28 +123,23 @@ const TEMPLATE_OPTIONS: { description: string; }[] = [ { - template: "strands-python", - label: "strands-python (recommended)", + template: "agent-python-strands", + label: "agent-python-strands (recommended)", description: "Strands agent on Bedrock with memory (CodeZip build)", }, { - template: "hello-world-python", - label: "hello-world-python", + template: "agent-python", + label: "agent-python", description: "minimal Python agent on Bedrock, no framework (CodeZip build)", }, { - template: "hello-world-python-container", - label: "hello-world-python-container", - description: "the hello-world agent packaged as a container image", - }, - { - template: "py-mcp", - label: "py-mcp", + template: "mcp-python-fastmcp", + label: "mcp-python-fastmcp", description: "MCP server exposing tools via FastMCP (CodeZip build)", }, { - template: "strands-py-a2a", - label: "strands-py-a2a", + template: "a2a-python-strands", + label: "a2a-python-strands", description: "Strands agent speaking the A2A protocol on Bedrock (CodeZip build)", }, ]; @@ -195,9 +190,9 @@ export function buildCreateInput(values: CreateProjectFormValues): CreateProject skipGit: false, scaffoldRuntimeInput: resolveRuntimeTemplateShortcut( values.template, - // Memory is a strands question; the hello-world templates keep their own + // Memory is a strands question; the non-strands templates keep their own // (memory-less) defaults, exactly like `--template` without `--memory`. - values.template === "strands-python" ? { memory: values.memory } : undefined, + values.template === "agent-python-strands" ? { memory: values.memory } : undefined, ), }; } @@ -219,7 +214,7 @@ function summaryOf(values: CreateProjectFormValues): Record { }; } const withTemplate = { ...base, type: "agent code", template: values.template }; - return values.template === "strands-python" + return values.template === "agent-python-strands" ? { ...withTemplate, memory: MEMORY_OPTIONS.find((option) => option.memory === values.memory)!.label, @@ -263,7 +258,9 @@ export function ProjectCreateScreen({ core }: ScreenProps) { ? [{ key: "model", title: "model" }] : [ { key: "template", title: "template" }, - ...(values.template === "strands-python" ? [{ key: "memory", title: "memory" }] : []), + ...(values.template === "agent-python-strands" + ? [{ key: "memory", title: "memory" }] + : []), ]; return [ { key: "name", title: "name" }, diff --git a/src/handlers/project/export/harness.test.ts b/src/handlers/project/export/harness.test.ts index c3e2f9000..04627710b 100644 --- a/src/handlers/project/export/harness.test.ts +++ b/src/handlers/project/export/harness.test.ts @@ -65,7 +65,7 @@ async function inProjectWithHarness( "--name", "orders", "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/project.test.ts b/src/handlers/project/project.test.ts index 74c185ce1..546c39b92 100644 --- a/src/handlers/project/project.test.ts +++ b/src/handlers/project/project.test.ts @@ -241,23 +241,16 @@ describe("project create", () => { run(["create", "--name", "MyAgent", "--framework", "strands", "--model-id", "x"]), ).rejects.toThrow(/Cannot mix runtime scaffolding flags \(--framework\)/); await expect( - run(["create", "--name", "MyAgent", "--template", "hello-world-python", "--timeout", "9"]), + run(["create", "--name", "MyAgent", "--template", "agent-python", "--timeout", "9"]), ).rejects.toThrow(/harness-only flags \(--timeout\)/); await expect( - run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - "--no-harness-memory", - ]), + run(["create", "--name", "MyAgent", "--template", "agent-python", "--no-harness-memory"]), ).rejects.toThrow(/harness-only flags \(--no-harness-memory\)/); }); test("--defaults is ignored when a runtime path flag routes to scaffolding", async () => { const directory = await inTempDirectory(); - await run(["create", "--name", "MyAgent", "--defaults", "--template", "hello-world-python"]); + await run(["create", "--name", "MyAgent", "--defaults", "--template", "agent-python"]); const spec = await Bun.file(join(directory, "MyAgent", "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ name: "hello_world" }); @@ -368,13 +361,7 @@ describe("project create", () => { test("runs the post-scaffold steps and reports progress on stderr", async () => { const directory = await inTempDirectory(); - const { io, core } = await run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - ]); + const { io, core } = await run(["create", "--name", "MyAgent", "--template", "agent-python"]); const projectRoot = join(directory, "MyAgent"); expect(core.projectCommands).toEqual([ @@ -402,15 +389,7 @@ describe("project create", () => { ])("rejects --%s as a template override", async (flagName, value) => { await inTempDirectory(); await expect( - run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - `--${flagName}`, - value, - ]), + run(["create", "--name", "MyAgent", "--template", "agent-python", `--${flagName}`, value]), ).rejects.toThrow(`--${flagName} cannot override a template`); }); @@ -421,7 +400,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--runtime-name", "custom_agent", "--build", @@ -453,7 +432,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--model-provider", "open_ai", ]), @@ -468,7 +447,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--build", "Container", "--skip-install", @@ -496,7 +475,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--skip-install", "--skip-git", ]); @@ -513,7 +492,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--build", "Container", "--skip-install", @@ -526,14 +505,14 @@ describe("project create", () => { }); }); - test("scaffolds an MCP server from the py-mcp template (CodeZip default)", async () => { + test("scaffolds an MCP server from the mcp-python-fastmcp template (CodeZip default)", async () => { const directory = await inTempDirectory(); await run([ "create", "--name", "MyProject", "--template", - "py-mcp", + "mcp-python-fastmcp", "--skip-install", "--skip-git", ]); @@ -554,14 +533,14 @@ describe("project create", () => { expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(false); }); - test("scaffolds a Container MCP server from the py-mcp template", async () => { + test("scaffolds a Container MCP server from the mcp-python-fastmcp template", async () => { const directory = await inTempDirectory(); await run([ "create", "--name", "MyProject", "--template", - "py-mcp", + "mcp-python-fastmcp", "--build", "Container", "--skip-install", @@ -768,7 +747,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "hello-world-python", + "agent-python", "--api-key", "-", "--skip-install", diff --git a/src/handlers/project/remove/index.test.ts b/src/handlers/project/remove/index.test.ts index 137b88a20..d5c769c94 100644 --- a/src/handlers/project/remove/index.test.ts +++ b/src/handlers/project/remove/index.test.ts @@ -56,7 +56,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/shortcuts.ts b/src/handlers/project/shortcuts.ts index 5a783fd5e..aa63b9078 100644 --- a/src/handlers/project/shortcuts.ts +++ b/src/handlers/project/shortcuts.ts @@ -50,7 +50,7 @@ type RuntimeTemplateShortcut = Omit & { }; export const RUNTIME_TEMPLATE_SHORTCUTS = { - "hello-world-python": { + "agent-python": { runtimeName: "hello_world", build: "CodeZip", language: "Python", @@ -59,15 +59,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "none", runtimeVersion: "PYTHON_3_14", }, - "hello-world-python-container": { - runtimeName: "hello_world", - build: "Container", - language: "Python", - framework: "none", - modelProvider: "Bedrock", - memory: "none", - }, - "strands-python": { + "agent-python-strands": { runtimeName: "strands_agent", build: "CodeZip", language: "Python", @@ -76,7 +68,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "longAndShortTerm", runtimeVersion: "PYTHON_3_14", }, - "strands-ts": { + "agent-typescript-strands": { runtimeName: "strands_agent", build: "CodeZip", language: "TypeScript", @@ -85,7 +77,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "longAndShortTerm", runtimeVersion: "NODE_22", }, - "py-mcp": { + "mcp-python-fastmcp": { runtimeName: "mcp_server", build: "CodeZip", language: "Python", @@ -95,7 +87,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "none", runtimeVersion: "PYTHON_3_14", }, - "strands-py-a2a": { + "a2a-python-strands": { runtimeName: "a2a_agent", build: "CodeZip", language: "Python", From 3bd4052060cd29b7127dd86faffe3051ffe712ca Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 18:18:14 +0000 Subject: [PATCH 3/6] refactor: rename template test constants to match new names --- src/core/project/manager.test.ts | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/core/project/manager.test.ts b/src/core/project/manager.test.ts index 6c01ef979..a7c17503b 100644 --- a/src/core/project/manager.test.ts +++ b/src/core/project/manager.test.ts @@ -25,14 +25,14 @@ import { import { createSilentLogger, TestIdentityClient } from "../../testing"; import type { DeployBackendInput, ProjectBackend } from "./backends/types"; -const HELLO_WORLD_PYTHON = resolveRuntimeTemplateShortcut("agent-python"); -const HELLO_WORLD_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("agent-python", { +const AGENT_PYTHON = resolveRuntimeTemplateShortcut("agent-python"); +const AGENT_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("agent-python", { build: "Container", }); -const STRANDS_PYTHON = resolveRuntimeTemplateShortcut("agent-python-strands"); -const STRANDS_TS = resolveRuntimeTemplateShortcut("agent-typescript-strands"); -const STRANDS_PY_A2A = resolveRuntimeTemplateShortcut("a2a-python-strands"); -const STRANDS_PY_A2A_CONTAINER = resolveRuntimeTemplateShortcut("a2a-python-strands", { +const AGENT_PYTHON_STRANDS = resolveRuntimeTemplateShortcut("agent-python-strands"); +const AGENT_TYPESCRIPT_STRANDS = resolveRuntimeTemplateShortcut("agent-typescript-strands"); +const A2A_PYTHON_STRANDS = resolveRuntimeTemplateShortcut("a2a-python-strands"); +const A2A_PYTHON_STRANDS_CONTAINER = resolveRuntimeTemplateShortcut("a2a-python-strands", { build: "Container", }); @@ -99,7 +99,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const projectRoot = join(directory, "example"); @@ -110,7 +110,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON_STRANDS, }); const projectRoot = join(directory, "example"); @@ -126,7 +126,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_TS, + scaffoldRuntimeInput: AGENT_TYPESCRIPT_STRANDS, }); const projectRoot = join(directory, "example"); @@ -142,7 +142,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS, }); const projectRoot = join(directory, "example"); @@ -158,7 +158,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS, }); const spec = await Bun.file(join(directory, "example", "agentcore", "agentcore.json")).json(); @@ -175,7 +175,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A_CONTAINER, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS_CONTAINER, }); const appDir = join(directory, "example", "app", "a2a_agent"); @@ -194,7 +194,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const configDir = join(directory, "example", "agentcore"); @@ -216,7 +216,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON_CONTAINER, + scaffoldRuntimeInput: AGENT_PYTHON_CONTAINER, }); const appDir = join(directory, "example", "app", "hello_world"); @@ -233,7 +233,7 @@ describe("FsProjectManager.create", () => { await inTempDirectory(); const input: CreateProjectInput = { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }; await runCreate(manager().manager, input); @@ -265,7 +265,7 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const projectRoot = join(directory, "example"); @@ -281,7 +281,7 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipInstall: true, }); @@ -322,7 +322,7 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipGit: true, }); @@ -333,7 +333,7 @@ describe("FsProjectManager.create", () => { await inTempDirectory(); const { events, project } = await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); expect(events.flatMap((event) => (event.type === "step" ? [event.message] : []))).toEqual([ @@ -359,7 +359,7 @@ describe("FsProjectManager.create", () => { }); await expect( - runCreate(failing, { name: "example", scaffoldRuntimeInput: HELLO_WORLD_PYTHON }), + runCreate(failing, { name: "example", scaffoldRuntimeInput: AGENT_PYTHON }), ).rejects.toThrow("npm exploded"); expect(await Bun.file(join(directory, "example", "agentcore", "agentcore.json")).exists()).toBe( true, @@ -370,14 +370,14 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "root", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); process.chdir(join(directory, "root")); await expect( runCreate(manager().manager, { name: "child", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }), ).rejects.toBeInstanceOf(ProjectStateError); }); @@ -393,7 +393,7 @@ describe("FsProjectManager.build", () => { ): Promise { const { project } = await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipInstall: true, skipGit: true, }); @@ -774,7 +774,7 @@ describe("FsProjectManager.resolve", () => { const subject = manager().manager; await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); // Resolve from a nested path to prove the walk-up to the project root. @@ -845,7 +845,7 @@ describe("FsProjectManager removal", () => { const subject = manager().manager; const { project } = await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); return { subject, project }; } From 1b82f68da3ce492d3a366e1106f9a8228b93a3dd Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 18:20:56 +0000 Subject: [PATCH 4/6] docs: reword agent-python entrypoint docstring --- src/assets/templates/agent-python/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/templates/agent-python/main.py b/src/assets/templates/agent-python/main.py index 9882ec785..4bf4e2213 100644 --- a/src/assets/templates/agent-python/main.py +++ b/src/assets/templates/agent-python/main.py @@ -5,7 +5,7 @@ @app.entrypoint def invoke(payload, context): - """Return a fixed greeting for every invocation.""" + """Add agent logic here""" return {"message": "Hello, world!"} From a5d337d8859a6e5886429f5cb5e451327680dcb2 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 18:32:06 +0000 Subject: [PATCH 5/6] refactor: default runtime names to match template names --- .../__snapshots__/manager.test.ts.snap | 80 +++++++++---------- src/core/project/manager.test.ts | 24 +++--- .../project/add/gateway-target/index.test.ts | 6 +- .../project/add/online-eval/index.test.ts | 10 +-- .../project/add/online-insight/index.test.ts | 16 ++-- .../project/create/create.screen.test.tsx | 2 +- src/handlers/project/export/harness.test.ts | 4 +- src/handlers/project/project.test.ts | 28 +++---- src/handlers/project/remove/index.test.ts | 8 +- src/handlers/project/shortcuts.ts | 10 +-- 10 files changed, 95 insertions(+), 93 deletions(-) diff --git a/src/core/project/__snapshots__/manager.test.ts.snap b/src/core/project/__snapshots__/manager.test.ts.snap index a75e5b8d7..93418d3d4 100644 --- a/src/core/project/__snapshots__/manager.test.ts.snap +++ b/src/core/project/__snapshots__/manager.test.ts.snap @@ -17,9 +17,9 @@ exports[`FsProjectManager.create scaffolds the expected file tree into a fresh d "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/hello_world/README.md", - "app/hello_world/main.py", - "app/hello_world/pyproject.toml", + "app/agent_python/README.md", + "app/agent_python/main.py", + "app/agent_python/pyproject.toml", ] `; @@ -41,23 +41,23 @@ exports[`FsProjectManager.create snapshots the Strands project manifest and runt "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/strands_agent/.gitignore", - "app/strands_agent/README.md", - "app/strands_agent/main.py", - "app/strands_agent/mcp_client/__init__.py", - "app/strands_agent/mcp_client/client.py", - "app/strands_agent/memory/__init__.py", - "app/strands_agent/memory/session.py", - "app/strands_agent/model/__init__.py", - "app/strands_agent/model/load.py", - "app/strands_agent/model/mantle_compat.py", - "app/strands_agent/pyproject.toml", - "app/strands_agent/skills/fetcher.py", + "app/agent_python_strands/.gitignore", + "app/agent_python_strands/README.md", + "app/agent_python_strands/main.py", + "app/agent_python_strands/mcp_client/__init__.py", + "app/agent_python_strands/mcp_client/client.py", + "app/agent_python_strands/memory/__init__.py", + "app/agent_python_strands/memory/session.py", + "app/agent_python_strands/model/__init__.py", + "app/agent_python_strands/model/load.py", + "app/agent_python_strands/model/mantle_compat.py", + "app/agent_python_strands/pyproject.toml", + "app/agent_python_strands/skills/fetcher.py", ], "memories": [ { "eventExpiryDuration": 30, - "name": "strands_agentMemory", + "name": "agent_python_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -92,9 +92,9 @@ exports[`FsProjectManager.create snapshots the Strands project manifest and runt "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/strands_agent", + "codeLocation": "app/agent_python_strands", "entrypoint": "main.py", - "name": "strands_agent", + "name": "agent_python_strands", "protocol": "HTTP", "runtimeVersion": "PYTHON_3_14", }, @@ -120,19 +120,19 @@ exports[`FsProjectManager.create snapshots the Strands TypeScript project manife "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/strands_agent/.gitignore", - "app/strands_agent/README.md", - "app/strands_agent/main.ts", - "app/strands_agent/mcp_client/client.ts", - "app/strands_agent/memory/memory.ts", - "app/strands_agent/model/load.ts", - "app/strands_agent/package.json", - "app/strands_agent/tsconfig.json", + "app/agent_typescript_strands/.gitignore", + "app/agent_typescript_strands/README.md", + "app/agent_typescript_strands/main.ts", + "app/agent_typescript_strands/mcp_client/client.ts", + "app/agent_typescript_strands/memory/memory.ts", + "app/agent_typescript_strands/model/load.ts", + "app/agent_typescript_strands/package.json", + "app/agent_typescript_strands/tsconfig.json", ], "memories": [ { "eventExpiryDuration": 30, - "name": "strands_agentMemory", + "name": "agent_typescript_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -167,9 +167,9 @@ exports[`FsProjectManager.create snapshots the Strands TypeScript project manife "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/strands_agent", + "codeLocation": "app/agent_typescript_strands", "entrypoint": "main.js", - "name": "strands_agent", + "name": "agent_typescript_strands", "protocol": "HTTP", "runtimeVersion": "NODE_22", }, @@ -195,19 +195,19 @@ exports[`FsProjectManager.create snapshots the Strands A2A project manifest and "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/a2a_agent/.gitignore", - "app/a2a_agent/README.md", - "app/a2a_agent/main.py", - "app/a2a_agent/memory/__init__.py", - "app/a2a_agent/memory/session.py", - "app/a2a_agent/model/__init__.py", - "app/a2a_agent/model/load.py", - "app/a2a_agent/pyproject.toml", + "app/a2a_python_strands/.gitignore", + "app/a2a_python_strands/README.md", + "app/a2a_python_strands/main.py", + "app/a2a_python_strands/memory/__init__.py", + "app/a2a_python_strands/memory/session.py", + "app/a2a_python_strands/model/__init__.py", + "app/a2a_python_strands/model/load.py", + "app/a2a_python_strands/pyproject.toml", ], "memories": [ { "eventExpiryDuration": 30, - "name": "a2a_agentMemory", + "name": "a2a_python_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -242,9 +242,9 @@ exports[`FsProjectManager.create snapshots the Strands A2A project manifest and "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/a2a_agent", + "codeLocation": "app/a2a_python_strands", "entrypoint": "main.py", - "name": "a2a_agent", + "name": "a2a_python_strands", "protocol": "A2A", "runtimeVersion": "PYTHON_3_14", }, diff --git a/src/core/project/manager.test.ts b/src/core/project/manager.test.ts index a7c17503b..47b11e5fa 100644 --- a/src/core/project/manager.test.ts +++ b/src/core/project/manager.test.ts @@ -163,12 +163,12 @@ describe("FsProjectManager.create", () => { const spec = await Bun.file(join(directory, "example", "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "a2a_agent", + name: "a2a_python_strands", build: "CodeZip", protocol: "A2A", entrypoint: "main.py", }); - expect(spec.memories).toMatchObject([{ name: "a2a_agentMemory" }]); + expect(spec.memories).toMatchObject([{ name: "a2a_python_strandsMemory" }]); }); test("scaffolds the Strands A2A runtime as a container with --build Container", async () => { @@ -178,7 +178,7 @@ describe("FsProjectManager.create", () => { scaffoldRuntimeInput: A2A_PYTHON_STRANDS_CONTAINER, }); - const appDir = join(directory, "example", "app", "a2a_agent"); + const appDir = join(directory, "example", "app", "a2a_python_strands"); expect(await Bun.file(join(appDir, "Dockerfile")).exists()).toBe(true); expect(await Bun.file(join(appDir, ".dockerignore")).exists()).toBe(true); @@ -202,10 +202,10 @@ describe("FsProjectManager.create", () => { expect(spec.name).toBe("example"); expect(spec.runtimes).toEqual([ { - name: "hello_world", + name: "agent_python", build: "CodeZip", entrypoint: "main.py", - codeLocation: "app/hello_world", + codeLocation: "app/agent_python", runtimeVersion: "PYTHON_3_14", }, ]); @@ -219,7 +219,7 @@ describe("FsProjectManager.create", () => { scaffoldRuntimeInput: AGENT_PYTHON_CONTAINER, }); - const appDir = join(directory, "example", "app", "hello_world"); + const appDir = join(directory, "example", "app", "agent_python"); // dockerignore.template must render to .dockerignore (the fsTree regex fix). expect(await Bun.file(join(appDir, ".dockerignore")).exists()).toBe(true); expect(await Bun.file(join(appDir, "dockerignore.template")).exists()).toBe(false); @@ -271,7 +271,7 @@ describe("FsProjectManager.create", () => { const projectRoot = join(directory, "example"); expect(commands).toEqual([ { command: ["npm", "install"], cwd: join(projectRoot, "agentcore", "cdk") }, - { command: ["uv", "sync"], cwd: join(projectRoot, "app", "hello_world") }, + { command: ["uv", "sync"], cwd: join(projectRoot, "app", "agent_python") }, { command: ["git", "init"], cwd: projectRoot }, ]); }); @@ -293,15 +293,17 @@ describe("FsProjectManager.create", () => { "Python", resolveRuntimeTemplateShortcut("agent-python-strands", { build: "Container" }), ["uv", "lock"], + "agent_python_strands", ], [ "TypeScript", resolveRuntimeTemplateShortcut("agent-typescript-strands", { build: "Container" }), ["npm", "install", "--package-lock-only"], + "agent_typescript_strands", ], ])( "skipInstall still generates the container lockfile for %s", - async (_label, scaffoldRuntimeInput, lockCommand) => { + async (_label, scaffoldRuntimeInput, lockCommand, runtimeName) => { const directory = await inTempDirectory(); const { manager: subject, commands } = manager(); await runCreate(subject, { @@ -312,7 +314,7 @@ describe("FsProjectManager.create", () => { }); expect(commands).toEqual([ - { command: lockCommand, cwd: join(directory, "example", "app", "strands_agent") }, + { command: lockCommand, cwd: join(directory, "example", "app", runtimeName) }, ]); }, ); @@ -812,10 +814,10 @@ describe("FsProjectManager.resolve", () => { version: 1, runtimes: [ { - name: "hello_world", + name: "agent_python", build: "CodeZip", entrypoint: "main.py", - codeLocation: "app/hello_world", + codeLocation: "app/agent_python", }, ], }), diff --git a/src/handlers/project/add/gateway-target/index.test.ts b/src/handlers/project/add/gateway-target/index.test.ts index 211b5c27d..747b8410c 100644 --- a/src/handlers/project/add/gateway-target/index.test.ts +++ b/src/handlers/project/add/gateway-target/index.test.ts @@ -58,7 +58,7 @@ describe("project add gateway-target", () => { "--name", "runtime", "--runtime", - "hello_world", + "agent_python", "--runtime-endpoint", "DEFAULT", ]); @@ -73,7 +73,7 @@ describe("project add gateway-target", () => { { name: "runtime", targetType: "httpRuntime", - httpRuntime: { runtime: "hello_world", runtimeEndpoint: "DEFAULT" }, + httpRuntime: { runtime: "agent_python", runtimeEndpoint: "DEFAULT" }, }, ]); }); @@ -253,7 +253,7 @@ describe("project add gateway-target", () => { ["no Target mode", ["--gateway", "tools", "--name", "target"], "specify exactly one"], [ "multiple Target modes", - [...endpointFlags(), "--runtime", "hello_world"], + [...endpointFlags(), "--runtime", "agent_python"], "specify exactly one", ], [ diff --git a/src/handlers/project/add/online-eval/index.test.ts b/src/handlers/project/add/online-eval/index.test.ts index 62dd4d96b..aa7154fe2 100644 --- a/src/handlers/project/add/online-eval/index.test.ts +++ b/src/handlers/project/add/online-eval/index.test.ts @@ -64,13 +64,13 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", "50", ], - { agent: "hello_world", evaluators: ["Builtin.Correctness"], samplingRate: 50 }, + { agent: "agent_python", evaluators: ["Builtin.Correctness"], samplingRate: 50 }, ], [ "custom log-group source", @@ -92,7 +92,7 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--endpoint", "PROD", "--evaluator", @@ -100,7 +100,7 @@ describe("project add online-eval", () => { "--sampling-rate", "10", ], - { agent: "hello_world", endpoint: "PROD" }, + { agent: "agent_python", endpoint: "PROD" }, ], [ "service-name filter on a custom source", @@ -140,7 +140,7 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", diff --git a/src/handlers/project/add/online-insight/index.test.ts b/src/handlers/project/add/online-insight/index.test.ts index 03ba7c4ea..89551811f 100644 --- a/src/handlers/project/add/online-insight/index.test.ts +++ b/src/handlers/project/add/online-insight/index.test.ts @@ -62,8 +62,8 @@ describe("project add online-insight", () => { test.each<[string, string[], Record]>([ [ "minimal — agent source", - ["--name", "x", "--agent", "hello_world", "--insight", INSIGHT, "--sampling-rate", "50"], - { agent: "hello_world", insights: [INSIGHT], samplingRate: 50 }, + ["--name", "x", "--agent", "agent_python", "--insight", INSIGHT, "--sampling-rate", "50"], + { agent: "agent_python", insights: [INSIGHT], samplingRate: 50 }, ], [ "custom log-group source", @@ -85,7 +85,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--endpoint", "PROD", "--insight", @@ -93,7 +93,7 @@ describe("project add online-insight", () => { "--sampling-rate", "10", ], - { agent: "hello_world", endpoint: "PROD" }, + { agent: "agent_python", endpoint: "PROD" }, ], [ "clustering frequencies", @@ -101,7 +101,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -134,7 +134,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -163,7 +163,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -190,7 +190,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", diff --git a/src/handlers/project/create/create.screen.test.tsx b/src/handlers/project/create/create.screen.test.tsx index a1356cddb..c56259bed 100644 --- a/src/handlers/project/create/create.screen.test.tsx +++ b/src/handlers/project/create/create.screen.test.tsx @@ -325,7 +325,7 @@ describe("project create wizard", () => { join(directory, "StrandsApp", "agentcore", "agentcore.json"), ).json(); expect(spec.runtimes.map((runtime: { name: string }) => runtime.name)).toEqual([ - "strands_agent", + "agent_python_strands", ]); expect(spec.memories).toHaveLength(1); r.unmount(); diff --git a/src/handlers/project/export/harness.test.ts b/src/handlers/project/export/harness.test.ts index 04627710b..e2dcebe06 100644 --- a/src/handlers/project/export/harness.test.ts +++ b/src/handlers/project/export/harness.test.ts @@ -155,8 +155,8 @@ describe("project export harness handler", () => { // The scaffolded template runtime already owns its name. await expect( - subject.run(["--name", "exportme", "--target-agent-name", "hello_world"]), - ).rejects.toThrow(/runtime with name 'hello_world' already exists/); + subject.run(["--name", "exportme", "--target-agent-name", "agent_python"]), + ).rejects.toThrow(/runtime with name 'agent_python' already exists/); // A harness name is just as taken. await expect( subject.run(["--name", "exportme", "--target-agent-name", "exportme"]), diff --git a/src/handlers/project/project.test.ts b/src/handlers/project/project.test.ts index 546c39b92..200f55ce6 100644 --- a/src/handlers/project/project.test.ts +++ b/src/handlers/project/project.test.ts @@ -253,7 +253,7 @@ describe("project create", () => { await run(["create", "--name", "MyAgent", "--defaults", "--template", "agent-python"]); const spec = await Bun.file(join(directory, "MyAgent", "agentcore", "agentcore.json")).json(); - expect(spec.runtimes[0]).toMatchObject({ name: "hello_world" }); + expect(spec.runtimes[0]).toMatchObject({ name: "agent_python" }); expect(spec.harnesses).toBeUndefined(); }); @@ -366,7 +366,7 @@ describe("project create", () => { const projectRoot = join(directory, "MyAgent"); expect(core.projectCommands).toEqual([ { command: ["npm", "install"], cwd: join(projectRoot, "agentcore", "cdk") }, - { command: ["uv", "sync"], cwd: join(projectRoot, "app", "hello_world") }, + { command: ["uv", "sync"], cwd: join(projectRoot, "app", "agent_python") }, { command: ["git", "init"], cwd: projectRoot }, ]); expect(io.stderr()).toContain("Creating project tree"); @@ -457,13 +457,13 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "strands_agent", + name: "agent_python_strands", build: "Container", - codeLocation: "app/strands_agent", + codeLocation: "app/agent_python_strands", dockerfile: "Dockerfile", }); expect(spec.runtimes[0].runtimeVersion).toBeUndefined(); - const runtimeRoot = join(projectRoot, "app", "strands_agent"); + const runtimeRoot = join(projectRoot, "app", "agent_python_strands"); expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(true); expect(await Bun.file(join(runtimeRoot, ".dockerignore")).exists()).toBe(true); }); @@ -480,7 +480,7 @@ describe("project create", () => { "--skip-git", ]); - const runtimeRoot = join(directory, "MyProject", "app", "strands_agent"); + const runtimeRoot = join(directory, "MyProject", "app", "agent_python_strands"); expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(false); expect(await Bun.file(join(runtimeRoot, ".dockerignore")).exists()).toBe(false); }); @@ -501,7 +501,7 @@ describe("project create", () => { expect(core.projectCommands).toContainEqual({ command: ["uv", "lock"], - cwd: join(directory, "MyProject", "app", "strands_agent"), + cwd: join(directory, "MyProject", "app", "agent_python_strands"), }); }); @@ -520,13 +520,13 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "mcp_server", + name: "mcp_python_fastmcp", build: "CodeZip", protocol: "MCP", - codeLocation: "app/mcp_server", + codeLocation: "app/mcp_python_fastmcp", runtimeVersion: "PYTHON_3_14", }); - const runtimeRoot = join(projectRoot, "app", "mcp_server"); + const runtimeRoot = join(projectRoot, "app", "mcp_python_fastmcp"); const mainPy = await Bun.file(join(runtimeRoot, "main.py")).text(); expect(mainPy).toContain("FastMCP"); expect(mainPy).toContain('mcp.run(transport="streamable-http")'); @@ -550,15 +550,15 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "mcp_server", + name: "mcp_python_fastmcp", build: "Container", protocol: "MCP", dockerfile: "Dockerfile", }); expect(spec.runtimes[0].runtimeVersion).toBeUndefined(); - expect(await Bun.file(join(projectRoot, "app", "mcp_server", "Dockerfile")).exists()).toBe( - true, - ); + expect( + await Bun.file(join(projectRoot, "app", "mcp_python_fastmcp", "Dockerfile")).exists(), + ).toBe(true); }); test.each([ diff --git a/src/handlers/project/remove/index.test.ts b/src/handlers/project/remove/index.test.ts index d5c769c94..ef54af689 100644 --- a/src/handlers/project/remove/index.test.ts +++ b/src/handlers/project/remove/index.test.ts @@ -87,7 +87,7 @@ describe("project remove", () => { }, { label: "runtime", - commands: [["remove", "runtime", "--name", "hello_world"]], + commands: [["remove", "runtime", "--name", "agent_python"]], specKey: "runtimes", expectedRemaining: [], }, @@ -136,7 +136,7 @@ describe("project remove", () => { "--name", "quality", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", @@ -156,7 +156,7 @@ describe("project remove", () => { "--name", "failures", "--agent", - "hello_world", + "agent_python", "--insight", "Builtin.Insight.FailureAnalysis", "--sampling-rate", @@ -533,7 +533,7 @@ describe("project remove all", () => { expect(spec.managedBy).toBe(before.managedBy); // Removal stays spec-level: scaffolded code and the credential's env entry. - expect(existsSync(join(projectRoot, "app", "hello_world"))).toBe(true); + expect(existsSync(join(projectRoot, "app", "agent_python"))).toBe(true); expect(await Bun.file(envPath).text()).not.toContain(envKey); expect(io.stderr()).toContain(`removed '${envKey}' from ${ENV_LOCAL_RELATIVE_PATH}`); expect(io.stdout()).toContain("removed all resources from project"); diff --git a/src/handlers/project/shortcuts.ts b/src/handlers/project/shortcuts.ts index aa63b9078..72a6e08da 100644 --- a/src/handlers/project/shortcuts.ts +++ b/src/handlers/project/shortcuts.ts @@ -51,7 +51,7 @@ type RuntimeTemplateShortcut = Omit & { export const RUNTIME_TEMPLATE_SHORTCUTS = { "agent-python": { - runtimeName: "hello_world", + runtimeName: "agent_python", build: "CodeZip", language: "Python", framework: "none", @@ -60,7 +60,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { runtimeVersion: "PYTHON_3_14", }, "agent-python-strands": { - runtimeName: "strands_agent", + runtimeName: "agent_python_strands", build: "CodeZip", language: "Python", framework: "strands", @@ -69,7 +69,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { runtimeVersion: "PYTHON_3_14", }, "agent-typescript-strands": { - runtimeName: "strands_agent", + runtimeName: "agent_typescript_strands", build: "CodeZip", language: "TypeScript", framework: "strands", @@ -78,7 +78,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { runtimeVersion: "NODE_22", }, "mcp-python-fastmcp": { - runtimeName: "mcp_server", + runtimeName: "mcp_python_fastmcp", build: "CodeZip", language: "Python", framework: "none", @@ -88,7 +88,7 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { runtimeVersion: "PYTHON_3_14", }, "a2a-python-strands": { - runtimeName: "a2a_agent", + runtimeName: "a2a_python_strands", build: "CodeZip", language: "Python", framework: "strands", From 1425fec7bcc1cbc9731b56acc1e338aa66b0bdf3 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Wed, 2 Sep 2026 18:55:12 +0000 Subject: [PATCH 6/6] fix: use agent-typescript-strands in short-term-memory error message --- src/core/project/templates/runtime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/project/templates/runtime.ts b/src/core/project/templates/runtime.ts index ddfd9fd86..98c733ff8 100644 --- a/src/core/project/templates/runtime.ts +++ b/src/core/project/templates/runtime.ts @@ -176,7 +176,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa // https://github.com/aws/bedrock-agentcore-sdk-typescript/blob/v0.3.0/src/memory/integrations/strands/factory.ts#L130-L133 if (memory !== undefined && memory.strategies.length === 0) throw new InputValidationError( - "the strands-ts template does not support short-term-only memory; add long-term strategies or use --memory none", + "the agent-typescript-strands template does not support short-term-only memory; add long-term strategies or use --memory none", ); const context = {