Skip to content

feat(templates): support rendering strands http template. - #2099

Merged
Hweinstock merged 23 commits into
aws:refactorfrom
Hweinstock:refactor-templates-pt2
Aug 27, 2026
Merged

feat(templates): support rendering strands http template. #2099
Hweinstock merged 23 commits into
aws:refactorfrom
Hweinstock:refactor-templates-pt2

Conversation

@Hweinstock

@Hweinstock Hweinstock commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Problem

We are not able to render real templates yet.

Solution

implement support for add runtime in core with the strands python http template as an example.

  • refactored addResources to modify an in-memory agentcore spec for stronger type safety and more flexibility in adding multiple resources.
  • refactored the template.ts file into its own directory to make it extensible to future templates.
  • define a TemplateRenderer interface that we can implement via handlebars.

Testing / Verification

create an agent from this template through create flow, and runtime add flow, then verify dev works for both:

bun run compile

./dist/bin/agentcore-linux-x64 project create --name testProject --template strands-python

cd testProject/

../dist/bin/agentcore-linux-x64 project add runtime --name agent2 --template strands-python

../dist/bin/agentcore-linux-x64 project dev

<seperate terminal>

 curl -X POST localhost:8080/invocations -H 'Content-type:
 application/json' -d '{ "prompt": "hello" }'

 curl -X POST localhost:8081/invocations -H 'Content-type:
 application/json' -d '{ "prompt": "hello" }'

we get responses on both

  • unit tests for all of this.

Future Work

This PR does not yet wire up support for memory, credentials for non-bedrock providers, or other templates. These will all be follow-ups, but their extension should be hopefully obvious based on the shape setup by the PR.

Also, we want to support overriding runtimeName on a template within the create flow (comment from previous PR that wasn't fully addressed here, but should be easy to support now with dynamic templates).

@github-actions github-actions Bot added the size/xl PR size: XL label Aug 25, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress and removed agentcore-harness-reviewing AgentCore Harness review in progress labels Aug 25, 2026
@codecov-commenter

codecov-commenter commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.78351% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.34%. Comparing base (9ab30d3) to head (917cc91).
⚠️ Report is 4 commits behind head on refactor.

Files with missing lines Patch % Lines
src/handlers/project/types.ts 70.58% 10 Missing ⚠️
src/core/project/templates/renderer.ts 83.72% 7 Missing ⚠️
src/core/project/templates/runtime.ts 93.26% 7 Missing ⚠️
src/core/project/templates/harness.ts 89.74% 4 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2099      +/-   ##
============================================
- Coverage     97.41%   97.34%   -0.07%     
============================================
  Files           453      456       +3     
  Lines         27637    27864     +227     
============================================
+ Hits          26922    27125     +203     
- Misses          715      739      +24     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 25, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 25, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 25, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 25, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@Hweinstock
Hweinstock force-pushed the refactor-templates-pt2 branch from dd846e3 to a622914 Compare August 26, 2026 01:27
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot added claude-security-reviewing Claude Code /security-review in progress and removed claude-security-reviewing Claude Code /security-review in progress labels Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
}

const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: TemplateRenderer) => ({
[buildResolverKey("none", "Python")]: async (input: RuntimeResourceConfig) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I tried agentcore project add runtime --name mcp_agent --template hello-world-python --protocol MCP. It succeeds and writes protocol: "MCP", but the generated main.py still runs BedrockAgentCoreApp HTTP. I think the none/Python resolver should reject non-HTTP protocols the same way strands-python does.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good catch, I wasn't really testing the hello world python since i wasn't sure if we were going to remove it, but we should fix this.


In a new terminal, you can invoke that server with:

`agentcore project invoke --dev "What can you do"`

@aidandaly24 aidandaly24 Aug 27, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: agentcore project invoke --dev is not registered on the refactor branch. We do have local invocation through the Inspector /invocations endpoint, so should this example use dev or the Agent Inspector instead? Deployed invocation will be the top-level agentcore project invoke command once #2115 lands. I can update this README.md in that PR or those commands could be included here too.

@Hweinstock Hweinstock Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let me remove for now and we can add back once we know what the command will look like.

Comment on lines +38 to +40
In a new terminal, you can invoke that server with:

`agentcore project invoke --dev "What can you do"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Did we implement this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed, we can re-add once its implemented.

@@ -0,0 +1,714 @@
from typing import Any

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's discuss this today, but we've been back and forth on what the right mix is between human readable templates and flexibility to compose different features on the fly

const outputPath = join(project.rootPath, "app", input.resourceConfig.name);
scaffoldedPaths.push(outputPath);

const spec = await this.scaffoldRuntimeResources(outputPath, input.resourceConfig);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we generate uv.lock during this runtime scaffold? hello-world-python-container emits a Dockerfile that copies uv.lock and runs uv sync --frozen, but this path never creates the lockfile. A new container runtime fails on the next project dev or deploy unless the user runs uv sync first.

build-backend = "hatchling.build"

[project]
name = "{{ name }}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we normalize the runtime name before using it as the package name here? The CLI accepts names such as agent_, but uv rejects that value in [project].name, so uv lock and uv sync fail after the add command succeeds.

"system-prompt.md",
async () => systemPrompt ?? DEFAULT_SYSTEM_PROMPT,
),
...(spec.dockerfile ? [FsTreeNode.fromTextFile("Dockerfile", spec.dockerfile)] : []),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we load or validate the Dockerfile before returning this tree? fromTextFile is not read until tree.write, after harness.json and system-prompt.md have already been written. A missing --dockerfile then leaves a partial harness directory behind even though the command fails.

@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 27, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 27, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the schema was widened to ["strands", "none"] and the resolver is registered, but both flag declarations still say z.enum(["none"]).

so --framework strands is rejected and --help only lists none. is --template the only scope for this PR?

Comment thread src/core/project/templates/harness.ts Outdated
return {
tree,
spec: {
harnesses: [{ name: parsed.name, path: join("app", parsed.name) }],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

join("app", name) uses the platform separator, and the result is written into agentcore.json, which gets committed and shared.

on Windows that's "path": "app\\h1". if that is pulled down on macOS or Linux CI, it resolves that to a single filename with a backslash in it, and cdk deploy breaks for everyone except the author. can we always emit / and convert to platform separators only when touching the filesystem?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

there is an edge case that when scaffolding fails, cleanup runs rm -rf app/<name>. But that's the whole directory, not just the files this command created. If the user already had something there, it's gone.

is there a way to track the files actually written and delete only those. can be a followup

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This might take some work to get right, lets do it as a follow-up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sounds good to me!

@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 27, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@notgitika notgitika left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for addressing the comments!

@@ -0,0 +1,116 @@
import os

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I feel like we could use Strand's tools from folder feature to simplify this process here

@tejaskash tejaskash left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verified the requested fixes on the current head. Runtime additions now generate uv.lock, Python names are normalized before rendering, and missing Dockerfiles fail before any harness files are written. Focused tests and the full current-base merge validation passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants