Skip to content

refactor(project): simplify scaffolding templates (memory, providers, container, empty) - #24

Draft
Hweinstock wants to merge 17 commits into
refactorfrom
feat/simplify-templates
Draft

refactor(project): simplify scaffolding templates (memory, providers, container, empty)#24
Hweinstock wants to merge 17 commits into
refactorfrom
feat/simplify-templates

Conversation

@Hweinstock

@Hweinstock Hweinstock commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Simplifies the project scaffolding templates on the refactor line:

  • --memory flag removed from project create and project add runtime. Templates that support memory (agent-python-strands, agent-typescript-strands, a2a-python-strands, + their -container twins) now ship with longAndShortTerm memory pre-configured and hardcoded (all 4 strategies). agent-python-minimal and mcp-python-fastmcp remain memory-less.
  • --model-provider / --api-key restricted to agent-python-strands (+ agent-python-strands-container). a2a-python-strands and agent-typescript-strands are now Bedrock-only and reject those flags.
  • agent-python renamed to agent-python-minimal.
  • Only agent-python-strands offers a container build (agent-python-strands-container), resolved from the same source with conditional Dockerfile rendering (build: Container); every other template is CodeZip-only, and their Dockerfiles were removed.
  • empty template creates a project with no runtime and no harness.
  • Assets no longer render memory/provider via Handlebars where the option was removed — memory is inlined; a2a/typescript hardcode Bedrock in their model loaders.
  • --language / --protocol / --build removed; --framework remains only as the import strands/langgraph selector on add runtime.
  • project create surface reduced to --name, --template, --model-provider, --api-key, --skip-install, --skip-git. Import + harness-tuning flags removed from create; import stays on project add runtime. Passing only --name scaffolds the default harness (the only harness path).
  • TUI create wizard: the memory step is gone; the template picker lists all new templates including every -container variant and empty.

Spec

spec (click to expand)

Problem: On the refactor branch, simplify the templates in a few core areas.

Definition of Done:

  • The memory option is removed, including the flag on the public interface on both the runtime add and create flows. All templates that support it come with longAndShortTerm memory pre-configured.
  • Only agent-python-strands supports custom model providers and API keys from the existing flags.
  • The memory prompt in the TUI create flow is removed for all agent scaffolding flows.
  • The assets no longer render these via Handlebars, and instead have it hard coded.
  • The TypeScript template is simplified to not accept any options (no memory, or api-key), or any of the existing ones like file mounts.
  • The language, protocol, build flags are removed.
  • Container templates are now separate template shortcuts with a -container suffix. We still resolve the container templates from the same source code with conditional Dockerfile rendering.
  • Empty template is now supported.
  • Harness is only scaffolded on create when only the name flag is present, and only the default harness is available.

⚠️ Spec-example correction (confirmed with author): The spec's DoD says "only agent-python-strands supports custom model providers and api keys," but its example block showed --template agent-python-minimal-container --model-provider anthropic # Works. Those conflict. The author confirmed the example is wrongagent-python-minimal (and its -container twin) must not accept API-key credential providers. This PR implements the DoD: only agent-python-strands(+container) accepts --model-provider/--api-key.

Rebased onto latest refactor. Upstream added an agui-python-strands template (aws#2201/aws#2185); it is preserved here and brought in line with the same simplifications — CodeZip-only, Bedrock-only (no --model-provider/--api-key), and memory-less, following the a2a pattern.

Verification

agentcore project create --help

Usage: agentcore project create [options]

create a new AgentCore project

Options:
  --name <name>                      name of the project to create
  --template <template>              a preset of flags for scaffolding the runtime; compatible flags override preset values
  --model-provider <model-provider>  model provider: bedrock, open_ai, gemini, or lite_llm for harnesses; bedrock, anthropic, open_ai, or gemini for runtime code
  --api-key <api-key>                API key for non-Bedrock providers: '-' for stdin, 'file://path' for file
  --skip-install                     skip installing dependencies (npm install, uv sync) (default: false)
  --skip-git                         skip initializing a git repository (default: false)
  -h, --help                         display help for command

agentcore project add runtime --help keeps --type/--agent-id/--agent-alias-id (import), --template, --framework (import-only), --model-provider, --api-key, and all infra flags; --build/--language/--protocol/--memory are gone.

Example commands

$ agentcore project create --name EmptyProj --template empty
# Works: project scaffolded with no runtime and no harness (empty app/, no resources in agentcore.json)

$ agentcore project create --name StrandsAnthropic --template agent-python-strands \
    --model-provider anthropic --api-key file://key.txt
# Works: runtime + credential + pre-configured longAndShortTerm memory (4 strategies); API key written to agentcore/.env.local

$ agentcore project create --name MinBad --template agent-python-minimal --model-provider anthropic --api-key file://key.txt
# Error: --model-provider is not valid with the agent-python-minimal template

$ agentcore project create --name A2aBad --template a2a-python-strands --model-provider gemini --api-key file://key.txt
# Error: --model-provider is not valid with the a2a-python-strands template

$ agentcore project create --name TsBad --template agent-typescript-strands --model-provider gemini --api-key file://key.txt
# Error: --model-provider is not valid with the agent-typescript-strands template

$ agentcore project create --name LangBad --template agent-python-langchain
# Error: Invalid value for option '--template': expected one of "agent-python-minimal"|"agent-python-strands"|
#   "agent-python-strands-container"|"agent-typescript-strands"|"mcp-python-fastmcp"|"a2a-python-strands"|
#   "agui-python-strands"|"empty"

Strands + Gemini builds (both build types)

  • CodeZip (--template agent-python-strands --model-provider gemini): agentcore project build synthesizes CloudFormation successfully; generated Python (main.py + model/load.py rendering GeminiModel) imports cleanly under uv run. Runtime spec: build: CodeZip, runtimeVersion: PYTHON_3_14, no Dockerfile.
  • Container (--template agent-python-strands-container --model-provider gemini): runtime spec is build: Container with dockerfile: Dockerfile; docker build of the generated Dockerfile succeeds and python -c "import main; import model.load" inside the image loads the Gemini strands module. agentcore project build synthesizes successfully.

TUI

The interactive agentcore project create wizard steps are now name → type → (model | template) → reviewno memory step. The template picker lists all 11 templates including every -container variant and empty. Template picker — all 8 options: 7 runtime templates (only agent-python-strands has a -container variant) + empty:

TUI template picker

Create flow — no memory step (name → type → template → review):

TUI create flow

Template picker (transcribed from the screenshot):

✓ name — ✓ type — ● template — ○ review

  ● agent-python-strands (recommended)   Strands agent on Bedrock with memory (CodeZip build)
  ○ agent-python-strands-container       Strands agent on Bedrock with memory (container build)
  ○ agent-python-minimal                 minimal Python agent on Bedrock, no framework (CodeZip build)
  ○ agent-typescript-strands             Strands agent on Bedrock with memory, in TypeScript (CodeZip build)
  ○ mcp-python-fastmcp                   MCP server exposing tools via FastMCP (CodeZip build)
  ○ a2a-python-strands                   Strands agent speaking the A2A protocol on Bedrock (CodeZip build)
  ○ agui-python-strands                  Strands agent speaking the AG-UI protocol on Bedrock (CodeZip build)
  ○ empty                                an empty project with no runtime or harness

Checks

bun run typecheck, bun run lint:check, bun run format:check, and bun test (2801 pass / 0 fail) all clean.

End-to-end verification (dev → curl → deploy → invoke)

Every template was exercised through the full pattern, plus strands-python with a real Gemini key. Deploys were batched into one project (TmplMatrix) — a single ~7-min deploy of 8 runtimes + memories + Gemini credential + a container image — then invoked and torn down (stack + ECR verified gone).

Template local dev+curl deploy+invoke (AWS us-east-1)
agent-python-minimal Hello, world!
agent-python-strands (Bedrock) SSE stream
agent-python-strands-container (Bedrock) (deploy fork) ✅ container build + invoke
agent-typescript-strands (Bedrock) SSE stream
agent-python-strands + Gemini (real key) SSE stream ✅ codezip and container
mcp-python-fastmcp MCP initialize/tools/list
a2a-python-strands (Bedrock) message/send task completed
agui-python-strands (Bedrock, memory-less) AG-UI stream

Also validated: static checks (typecheck/oxlint/prettier) + bun test (0 failures); create/add --help; template enum; agui is Bedrock-only + memory-less + Dockerfile-less.

Review

Three independent reviews (flag/dispatch logic, resolver+assets, TUI+tests) found no blockers. Applied fixes: reworded the --template/--model-provider help; removed a now-dead bedrockAgentImporter dependency from the create handler; added agui-python-strands test coverage. Notes intentionally left as-is: the Python session.py actor-level summaries retrieval namespace (intended), and the pre-existing --api-key - stdin-before-rejection ordering (fixing it would couple the handler to shortcut internals). Separately noted (not this PR): naming a runtime literally mcp collides with the mcp PyPI dependency during uv sync.

How to reproduce

# from a clone of this branch
bun install

# static checks + tests
bun run typecheck && bun run lint:check && bun test

# help text
bun run src/index.ts project create --help
bun run src/index.ts project add runtime --help

# example commands (scaffold into a scratch dir; --skip-install --skip-git keep it fast)
bun run src/index.ts project create --name EmptyProj --template empty --skip-install --skip-git
bun run src/index.ts project create --name MinBad --template agent-python-minimal --model-provider anthropic --api-key file://key.txt   # errors
printf 'YOUR_GEMINI_KEY\n' > key.txt
bun run src/index.ts project create --name GemZip --template agent-python-strands --model-provider gemini --api-key file://key.txt      # CodeZip
bun run src/index.ts project create --name GemCtr --template agent-python-strands-container --model-provider gemini --api-key file://key.txt  # Container

# build both (from inside each project)
cd GemZip && bun run <path>/src/index.ts project build   # CDK synth
cd GemCtr/app/agent_python_strands && docker build --platform linux/amd64 -t gem-ctr .   # container image

# TUI (interactive terminal): the wizard has no memory step
bun run src/index.ts project create

);
expect(await Bun.file(join(projectRoot, "app", "my_agent", "main.ts")).exists()).toBe(true);

// The TypeScript template ships with longAndShortTerm memory pre-configured.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment.

Comment thread src/handlers/project/create/index.ts Outdated
// the agent-python-strands template accepts them (enforced by the shortcut
// resolver). Without a runtime template there is nothing for them to tune.
if (modelProviderFlag !== undefined || apiKeyFlag !== undefined) {
const offending = modelProviderFlag !== undefined ? "model-provider" : "api-key";

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use a list + filter to simplify this? Then just show the first one in the error..

["default", [], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"]],
["none", ["--memory", "none"], []],
["short", ["--memory", "shortTerm"], []],
test.each<[string, string, string[]]>([

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is each test here duplicating a paramter?

Comment thread src/handlers/project/shortcuts.ts Outdated
framework: ScaffoldRuntimeInput["framework"];
protocol?: ScaffoldRuntimeInput["protocol"];
modelProvider?: ModelProvider;
/** Ships with longAndShortTerm memory pre-configured. */

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets just say ships with memory.

Comment thread src/handlers/project/shortcuts.ts Outdated
* longAndShortTerm memory, the only memory configuration templates ship with:
* templates that support memory come with it pre-configured and non-overridable.
*/
function longAndShortTermMemory(runtimeName: string): Memory {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets simplify create to just say getDefaultMemorySpec and avoid mentioning templates in the comment.

Comment thread src/handlers/project/shortcuts.ts Outdated
/** Ships with longAndShortTerm memory pre-configured. */
memory: boolean;
/** Accepts --model-provider / --api-key overrides; Bedrock-only otherwise. */
supportsModelProvider: boolean;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be supportsModelProviderOverride

"agent-python": {
runtimeName: "agent_python",
build: "CodeZip",
/**

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets simplify this to just use the original templates list, and duplicate the entries with -container as explicit different entries, with a different build.

Comment thread src/handlers/project/shortcuts.ts Outdated
const CONTAINER_SUFFIX = "-container";

export type RuntimeTemplateShortcutName = keyof typeof RUNTIME_TEMPLATE_SHORTCUTS;
export type RuntimeTemplateShortcutName =

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unnecessary complexity, lets go back to the old approach.

Hweinstock added a commit that referenced this pull request Sep 3, 2026
Comment thread src/handlers/project/shortcuts.ts Outdated
export type TemplateName = RuntimeTemplateShortcutName | typeof EMPTY_TEMPLATE_NAME;

/** Every `--template` value: the runtime shortcuts plus the empty project template. */
export const TEMPLATE_NAMES = [

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename this to PROJECT_TEMPLATE_NAMES.

Comment thread src/handlers/project/shortcuts.ts Outdated
...(overrides?.apiKey !== undefined && { apiKey: overrides.apiKey }),
...(memory && { memory }),
runtimeVersion: build === "CodeZip" ? (template.runtimeVersion ?? "PYTHON_3_14") : undefined,
...(template.framework === "strands" && { memory: getDefaultMemorySpec(runtimeName) }),

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels fragile. if we re-introduce the doesSupportMemory flag, can we simplify this?

Comment thread src/handlers/project/shortcuts.ts Outdated
EMPTY_TEMPLATE_NAME,
] as unknown as readonly [TemplateName, ...TemplateName[]];

export function isRuntimeTemplateShortcutName(

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to inline this, or do we need it for the type assertion?

@Hweinstock
Hweinstock force-pushed the feat/simplify-templates branch from cd64e12 to 3ea14df Compare September 3, 2026 23:14
@Hweinstock
Hweinstock force-pushed the feat/simplify-templates branch from 3ea14df to c545c24 Compare September 3, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant