Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/assets/templates/agent-typescript-vercel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
This is a project generated by the AgentCore CLI!

# Layout

The generated application code lives at the agent root directory. At the root, there is a `.gitignore` file, an
`agentcore/` folder which represents the configurations and state associated with this project. Other `agentcore`
commands like `deploy`, `dev`, and `invoke` rely on the configuration stored here.

## Agent Root

The main entrypoint to your app is defined in `main.ts`. Using the AgentCore SDK `BedrockAgentCoreApp`, this file
defines an HTTP server that streams tokens from Amazon Bedrock via the Vercel AI SDK's `streamText` API.

# Developing locally

If installation was successful, `node_modules/` is already populated with dependencies.

`agentcore project dev` will start a local server using `tsx watch main.ts` for hot reload on 0.0.0.0:8080.

# Deployment

After providing credentials, `agentcore project deploy` will deploy your project into Amazon Bedrock AgentCore.
22 changes: 22 additions & 0 deletions src/assets/templates/agent-typescript-vercel/gitignore.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Environment variables
.env
.env.*

# Node
node_modules/
dist/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db
35 changes: 35 additions & 0 deletions src/assets/templates/agent-typescript-vercel/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { streamText } from 'ai';
import { z } from 'zod';

const SYSTEM_PROMPT = `You are a helpful assistant.`;

const bedrock = createAmazonBedrock({
region: process.env.AWS_REGION ?? 'us-east-1',
credentialProvider: fromNodeProviderChain(),
});

const requestSchema = z.object({
prompt: z.string().default(''),
});

const app = new BedrockAgentCoreApp({
invocationHandler: {
requestSchema,
async *process(payload) {
const result = streamText({
model: bedrock('global.anthropic.claude-sonnet-4-5-20250929-v1:0'),
system: SYSTEM_PROMPT,
prompt: payload.prompt,
});

for await (const chunk of result.textStream) {
yield { data: chunk };
}
},
},
});

app.run({ port: parseInt(process.env.PORT ?? '8080') });
24 changes: 24 additions & 0 deletions src/assets/templates/agent-typescript-vercel/package.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "{{name}}",
"version": "0.1.0",
"description": "AgentCore Runtime Application using the Vercel AI SDK",
"private": true,
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/main.js",
"dev": "tsx watch main.ts"
},
"dependencies": {
"@ai-sdk/amazon-bedrock": "~4.0.0",
"@aws-sdk/credential-providers": "~3.1126.0",
"ai": "~6.0.0",
"bedrock-agentcore": "~0.3.0",
"tsx": "~4.19.0",
"zod": "~4.4.3"
},
"devDependencies": {
"@types/node": "~22.0.0",
"typescript": "~5.6.0"
}
}
19 changes: 19 additions & 0 deletions src/assets/templates/agent-typescript-vercel/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": false,
"sourceMap": true,
"outDir": "dist",
"rootDir": ".",
"types": ["node"]
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "dist"]
}
17 changes: 17 additions & 0 deletions src/core/project/templates/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,23 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa
...(modelScaffold.envEntries.length > 0 && { envEntries: modelScaffold.envEntries }),
};
},
[buildResolverKey("vercelai", "TypeScript", "HTTP")]: async (input: RuntimeResourceConfig) => {
if (input.protocol !== undefined && input.protocol !== "HTTP")
throw new InputValidationError("the agent-typescript-vercel template only supports HTTP");
const context = { name: toNpmPackageName(input.name) };
const tree = await FsTreeNode.fromAssetSource(
{ assetSource },
{ assetDir: "templates/agent-typescript-vercel" },
{
rootDirName: input.name,
transformContent: (raw) => templateRenderer.render(raw, context),
},
);
return {
tree,
spec: { runtimes: [{ ...buildRuntimeSpec(input), protocol: "HTTP" as const }] },
};
},
[buildResolverKey("none", "Python", "MCP")]: async (input: RuntimeResourceConfig) => {
if (input.scaffoldRuntimeInput.modelProvider !== undefined)
throw new InputValidationError("an MCP runtime does not use a model provider");
Expand Down
29 changes: 29 additions & 0 deletions src/handlers/project/add/runtime/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ describe("project add runtime", () => {
["agent-python-strands", ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"]],
["a2a-python-strands", ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"]],
["agent-python-minimal", []],
["agent-typescript-vercel", []],
["mcp-python-fastmcp", []],
["agui-python-strands", ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"]],
])("%s ships with its pre-configured memory", async (templateName, expectedStrategies) => {
Expand Down Expand Up @@ -349,6 +350,23 @@ describe("project add runtime", () => {
]);
});

test("agent-typescript-vercel scaffolds a memory-free TypeScript runtime", async () => {
const projectRoot = await inProject();
await run(["add", "runtime", "--name", "my_agent", "--template", "agent-typescript-vercel"]);

const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json();
expect(spec.runtimes).toContainEqual(
expect.objectContaining({
name: "my_agent",
entrypoint: "main.js",
build: "CodeZip",
runtimeVersion: "NODE_22",
protocol: "HTTP",
}),
);
expect(spec.memories ?? []).toEqual([]);
});

test.each<[string, string]>([
["anthropic", "Anthropic"],
["OpenAI", "OpenAI"],
Expand Down Expand Up @@ -397,6 +415,17 @@ describe("project add runtime", () => {
"--api-key is not valid with the agent-python-minimal template",
["--name", "my_agent", "--template", "agent-python-minimal", "--api-key", "secret-key"],
],
[
"--model-provider is not valid with the agent-typescript-vercel template",
[
"--name",
"my_agent",
"--template",
"agent-typescript-vercel",
"--model-provider",
"Anthropic",
],
],
[
"--model-provider without a template requires agent-python-strands",
["--name", "my_agent", "--model-provider", "Anthropic"],
Expand Down
5 changes: 5 additions & 0 deletions src/handlers/project/create/screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ const TEMPLATE_OPTIONS: {
label: "agent-typescript-strands",
description: "Strands agent on Bedrock with memory, in TypeScript (CodeZip build)",
},
{
template: "agent-typescript-vercel",
label: "agent-typescript-vercel",
description: "minimal Vercel AI SDK agent on Bedrock, in TypeScript (CodeZip build)",
},
{
template: "mcp-python-fastmcp",
label: "mcp-python-fastmcp",
Expand Down
10 changes: 10 additions & 0 deletions src/handlers/project/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = {
supportsModelProviderOverride: false,
runtimeVersion: "NODE_22",
},
"agent-typescript-vercel": {
runtimeName: "agent_typescript_vercel",
build: "CodeZip",
language: "TypeScript",
framework: "vercelai",
modelProvider: "Bedrock",
includesMemory: false,
supportsModelProviderOverride: false,
runtimeVersion: "NODE_22",
},
"mcp-python-fastmcp": {
runtimeName: "mcp_python_fastmcp",
build: "CodeZip",
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/project/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const ScaffoldRuntimeInputSchema = z
runtimeName: AgentNameSchema,
build: BuildTypeSchema,
language: z.enum(["Python", "TypeScript"]),
framework: z.enum(["strands", "none"]),
framework: z.enum(["strands", "vercelai", "none"]),
protocol: ProtocolModeSchema.optional(),
modelProvider: ModelProviderSchema.optional(),
apiKey: z.string().min(1).optional(),
Expand Down
Loading