feat(templates): support rendering strands http template. - #2099
Conversation
Codecov Report❌ Patch coverage is 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. 🚀 New features to boost your workflow:
|
|
Claude Security Review: no high-confidence findings. (run) |
|
Claude Security Review: no high-confidence findings. (run) |
dd846e3 to
a622914
Compare
|
Claude Security Review: no high-confidence findings. (run) |
|
Claude Security Review: no high-confidence findings. (run) |
| } | ||
|
|
||
| const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: TemplateRenderer) => ({ | ||
| [buildResolverKey("none", "Python")]: async (input: RuntimeResourceConfig) => { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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"` |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Let me remove for now and we can add back once we know what the command will look like.
| In a new terminal, you can invoke that server with: | ||
|
|
||
| `agentcore project invoke --dev "What can you do"` |
There was a problem hiding this comment.
removed, we can re-add once its implemented.
| @@ -0,0 +1,714 @@ | |||
| from typing import Any | |||
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 }}" |
There was a problem hiding this comment.
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)] : []), |
There was a problem hiding this comment.
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.
|
Claude Security Review: no high-confidence findings. (run) |
|
Claude Security Review: no high-confidence findings. (run) |
There was a problem hiding this comment.
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?
| return { | ||
| tree, | ||
| spec: { | ||
| harnesses: [{ name: parsed.name, path: join("app", parsed.name) }], |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
This might take some work to get right, lets do it as a follow-up.
|
Claude Security Review: no high-confidence findings. (run) |
|
Claude Security Review: no high-confidence findings. (run) |
|
Claude Security Review: no high-confidence findings. (run) |
notgitika
left a comment
There was a problem hiding this comment.
thanks for addressing the comments!
| @@ -0,0 +1,116 @@ | |||
| import os | |||
There was a problem hiding this comment.
I feel like we could use Strand's tools from folder feature to simplify this process here
tejaskash
left a comment
There was a problem hiding this comment.
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.
Problem
We are not able to render real templates yet.
Solution
implement support for
add runtimein core with the strands python http template as an example.template.tsfile into its own directory to make it extensible to future templates.TemplateRendererinterface 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:
we get responses on both
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).