@aws/agentcore 0.13.1 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/agent-inspector/index.css +1 -1
- package/dist/agent-inspector/index.js +79 -79
- package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +628 -10
- package/dist/assets/__tests__/__snapshots__/dockerfile-render.test.ts.snap +6 -2
- package/dist/assets/cdk/test/cdk.test.ts +0 -1
- package/dist/assets/container/python/Dockerfile +3 -1
- package/dist/assets/container/typescript/Dockerfile +25 -0
- package/dist/assets/container/typescript/dockerignore.template +24 -0
- package/dist/assets/python/a2a/googleadk/base/pyproject.toml +2 -2
- package/dist/assets/python/a2a/langchain_langgraph/base/pyproject.toml +1 -1
- package/dist/assets/python/a2a/strands/base/pyproject.toml +2 -2
- package/dist/assets/python/agui/googleadk/base/pyproject.toml +1 -1
- package/dist/assets/python/agui/strands/base/pyproject.toml +1 -1
- package/dist/assets/python/http/googleadk/base/pyproject.toml +1 -1
- package/dist/assets/python/http/strands/base/pyproject.toml +1 -1
- package/dist/assets/typescript/http/strands/base/README.md +37 -0
- package/dist/assets/typescript/http/strands/base/gitignore.template +22 -0
- package/dist/assets/typescript/http/strands/base/main.ts +66 -0
- package/dist/assets/typescript/http/strands/base/mcp_client/client.ts +11 -0
- package/dist/assets/typescript/http/strands/base/model/load.ts +102 -0
- package/dist/assets/typescript/http/strands/base/package.json +37 -0
- package/dist/assets/typescript/http/strands/base/tsconfig.json +19 -0
- package/dist/assets/typescript/http/vercelai/base/README.md +37 -0
- package/dist/assets/typescript/http/vercelai/base/gitignore.template +22 -0
- package/dist/assets/typescript/http/vercelai/base/main.ts +24 -0
- package/dist/assets/typescript/http/vercelai/base/model/load.ts +121 -0
- package/dist/assets/typescript/http/vercelai/base/package.json +35 -0
- package/dist/assets/typescript/http/vercelai/base/tsconfig.json +19 -0
- package/dist/cli/index.mjs +679 -540
- package/dist/lib/errors/index.d.ts +1 -1
- package/dist/lib/errors/index.d.ts.map +1 -1
- package/dist/lib/errors/index.js +1 -1
- package/dist/lib/errors/index.js.map +1 -1
- package/dist/lib/errors/types.d.ts +183 -0
- package/dist/lib/errors/types.d.ts.map +1 -0
- package/dist/lib/errors/types.js +284 -0
- package/dist/lib/errors/types.js.map +1 -0
- package/dist/lib/errors/zod.d.ts +8 -0
- package/dist/lib/errors/zod.d.ts.map +1 -0
- package/dist/lib/errors/{config.js → zod.js} +7 -80
- package/dist/lib/errors/zod.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +4 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/packaging/container.js +5 -5
- package/dist/lib/packaging/container.js.map +1 -1
- package/dist/lib/packaging/helpers.d.ts +16 -0
- package/dist/lib/packaging/helpers.d.ts.map +1 -1
- package/dist/lib/packaging/helpers.js +71 -9
- package/dist/lib/packaging/helpers.js.map +1 -1
- package/dist/lib/packaging/index.d.ts +0 -1
- package/dist/lib/packaging/index.d.ts.map +1 -1
- package/dist/lib/packaging/index.js +4 -19
- package/dist/lib/packaging/index.js.map +1 -1
- package/dist/lib/packaging/node.d.ts +2 -2
- package/dist/lib/packaging/node.d.ts.map +1 -1
- package/dist/lib/packaging/node.js +83 -38
- package/dist/lib/packaging/node.js.map +1 -1
- package/dist/lib/packaging/python.js +12 -12
- package/dist/lib/packaging/python.js.map +1 -1
- package/dist/lib/result.d.ts +29 -0
- package/dist/lib/result.d.ts.map +1 -0
- package/dist/lib/result.js +16 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemas/io/config-io.d.ts.map +1 -1
- package/dist/lib/schemas/io/config-io.js +2 -2
- package/dist/lib/schemas/io/config-io.js.map +1 -1
- package/dist/lib/schemas/io/index.d.ts +1 -1
- package/dist/lib/schemas/io/index.d.ts.map +1 -1
- package/dist/lib/schemas/io/index.js +1 -2
- package/dist/lib/schemas/io/index.js.map +1 -1
- package/dist/lib/schemas/io/path-resolver.d.ts +0 -6
- package/dist/lib/schemas/io/path-resolver.d.ts.map +1 -1
- package/dist/lib/schemas/io/path-resolver.js +3 -13
- package/dist/lib/schemas/io/path-resolver.js.map +1 -1
- package/dist/lib/time-constants.d.ts +5 -0
- package/dist/lib/time-constants.d.ts.map +1 -0
- package/dist/lib/time-constants.js +8 -0
- package/dist/lib/time-constants.js.map +1 -0
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.d.ts.map +1 -1
- package/dist/lib/utils/index.js +4 -1
- package/dist/lib/utils/index.js.map +1 -1
- package/dist/lib/utils/polling.d.ts +31 -0
- package/dist/lib/utils/polling.d.ts.map +1 -0
- package/dist/lib/utils/polling.js +61 -0
- package/dist/lib/utils/polling.js.map +1 -0
- package/dist/schema/constants.d.ts +7 -0
- package/dist/schema/constants.d.ts.map +1 -1
- package/dist/schema/constants.js +18 -3
- package/dist/schema/constants.js.map +1 -1
- package/dist/schema/schemas/agent-env.d.ts +12 -1
- package/dist/schema/schemas/agent-env.d.ts.map +1 -1
- package/dist/schema/schemas/agent-env.js +32 -5
- package/dist/schema/schemas/agent-env.js.map +1 -1
- package/dist/schema/schemas/agentcore-project.d.ts +9 -3
- package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
- package/dist/schema/schemas/agentcore-project.js +7 -2
- package/dist/schema/schemas/agentcore-project.js.map +1 -1
- package/dist/schema/schemas/primitives/evaluator.d.ts +8 -0
- package/dist/schema/schemas/primitives/evaluator.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/evaluator.js +17 -1
- package/dist/schema/schemas/primitives/evaluator.js.map +1 -1
- package/dist/schema/schemas/primitives/index.d.ts +1 -1
- package/dist/schema/schemas/primitives/index.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/index.js +3 -1
- package/dist/schema/schemas/primitives/index.js.map +1 -1
- package/dist/schema/schemas/primitives/memory.d.ts +22 -4
- package/dist/schema/schemas/primitives/memory.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/memory.js +57 -16
- package/dist/schema/schemas/primitives/memory.js.map +1 -1
- package/package.json +11 -9
- package/scripts/bump-version.ts +3 -3
- package/scripts/run-e2e-dev.sh +56 -0
- package/scripts/run-e2e-local.sh +1 -1
- package/dist/lib/errors/config.d.ts +0 -49
- package/dist/lib/errors/config.d.ts.map +0 -1
- package/dist/lib/errors/config.js.map +0 -1
- package/dist/lib/packaging/errors.d.ts +0 -16
- package/dist/lib/packaging/errors.d.ts.map +0 -1
- package/dist/lib/packaging/errors.js +0 -36
- package/dist/lib/packaging/errors.js.map +0 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`Dockerfile enableOtel rendering > renders opentelemetry-instrument CMD when enableOtel is true > Dockerfile-enableOtel-true 1`] = `
|
|
4
|
-
"FROM
|
|
4
|
+
"FROM public.ecr.aws/docker/library/python:3.12-slim-bookworm
|
|
5
|
+
|
|
6
|
+
RUN pip install --no-cache-dir uv
|
|
5
7
|
|
|
6
8
|
ARG UV_DEFAULT_INDEX
|
|
7
9
|
ARG UV_INDEX
|
|
@@ -39,7 +41,9 @@ CMD ["opentelemetry-instrument", "python", "-m", "main"]
|
|
|
39
41
|
`;
|
|
40
42
|
|
|
41
43
|
exports[`Dockerfile enableOtel rendering > renders plain python CMD when enableOtel is false > Dockerfile-enableOtel-false 1`] = `
|
|
42
|
-
"FROM
|
|
44
|
+
"FROM public.ecr.aws/docker/library/python:3.12-slim-bookworm
|
|
45
|
+
|
|
46
|
+
RUN pip install --no-cache-dir uv
|
|
43
47
|
|
|
44
48
|
ARG UV_DEFAULT_INDEX
|
|
45
49
|
ARG UV_INDEX
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
FROM public.ecr.aws/docker/library/node:22-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
ENV NODE_ENV=production \
|
|
6
|
+
DOCKER_CONTAINER=1
|
|
7
|
+
|
|
8
|
+
RUN userdel -r node 2>/dev/null || true
|
|
9
|
+
RUN useradd -m -u 1000 bedrock_agentcore
|
|
10
|
+
|
|
11
|
+
COPY package.json package-lock.json* ./
|
|
12
|
+
RUN npm ci --omit=dev || npm install --omit=dev
|
|
13
|
+
|
|
14
|
+
COPY --chown=bedrock_agentcore:bedrock_agentcore . .
|
|
15
|
+
|
|
16
|
+
USER bedrock_agentcore
|
|
17
|
+
|
|
18
|
+
# AgentCore Runtime service contract ports
|
|
19
|
+
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-service-contract.html
|
|
20
|
+
# 8080: HTTP Mode
|
|
21
|
+
# 8000: MCP Mode
|
|
22
|
+
# 9000: A2A Mode
|
|
23
|
+
EXPOSE 8080 8000 9000
|
|
24
|
+
|
|
25
|
+
CMD ["npx", "tsx", "main.ts"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Node
|
|
2
|
+
node_modules/
|
|
3
|
+
dist/
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
|
|
8
|
+
# IDE
|
|
9
|
+
.vscode/
|
|
10
|
+
.idea/
|
|
11
|
+
|
|
12
|
+
# Testing
|
|
13
|
+
coverage/
|
|
14
|
+
|
|
15
|
+
# Secrets and environment files
|
|
16
|
+
.env
|
|
17
|
+
.env.*
|
|
18
|
+
|
|
19
|
+
# Version control
|
|
20
|
+
.git/
|
|
21
|
+
|
|
22
|
+
# AgentCore build artifacts
|
|
23
|
+
.agentcore/artifacts/
|
|
24
|
+
*.zip
|
|
@@ -9,10 +9,10 @@ description = "AgentCore A2A Agent using Google ADK"
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"a2a-sdk >= 0.2.0",
|
|
12
|
+
"a2a-sdk >= 0.2.0, < 1.0.0",
|
|
13
13
|
"aws-opentelemetry-distro",
|
|
14
14
|
"bedrock-agentcore[a2a] >= 1.0.3",
|
|
15
|
-
"google-adk >= 1.0.0",
|
|
15
|
+
"google-adk >= 1.0.0, < 2.0.0",
|
|
16
16
|
"google-genai >= 1.0.0",
|
|
17
17
|
]
|
|
18
18
|
|
|
@@ -9,7 +9,7 @@ description = "AgentCore A2A Agent using LangChain + LangGraph"
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"a2a-sdk >= 0.2.0",
|
|
12
|
+
"a2a-sdk >= 0.2.0, < 1.0.0",
|
|
13
13
|
{{#if (eq modelProvider "Anthropic")}}"langchain-anthropic >= 0.3.0",
|
|
14
14
|
{{/if}}{{#if (eq modelProvider "Bedrock")}}"langchain-aws >= 0.2.0",
|
|
15
15
|
{{/if}}{{#if (eq modelProvider "Gemini")}}"langchain-google-genai >= 2.0.0",
|
|
@@ -10,9 +10,9 @@ readme = "README.md"
|
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
12
|
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
|
|
13
|
-
{{/if}}"a2a-sdk[all] >= 0.2.0",
|
|
13
|
+
{{/if}}"a2a-sdk[all] >= 0.2.0, < 1.0.0",
|
|
14
14
|
"aws-opentelemetry-distro",
|
|
15
|
-
"bedrock-agentcore[a2a] >= 1.
|
|
15
|
+
"bedrock-agentcore[a2a] >= 1.9.1",
|
|
16
16
|
"botocore[crt] >= 1.35.0",
|
|
17
17
|
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
|
|
18
18
|
{{/if}}{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
|
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
|
13
13
|
{{/if}}"ag-ui-strands >= 0.1.7",
|
|
14
14
|
"ag-ui-protocol >= 0.1.10",
|
|
15
15
|
"aws-opentelemetry-distro",
|
|
16
|
-
"bedrock-agentcore >= 1.
|
|
16
|
+
"bedrock-agentcore >= 1.9.1",
|
|
17
17
|
"botocore[crt] >= 1.35.0",
|
|
18
18
|
"fastapi >= 0.115.12",
|
|
19
19
|
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
|
|
@@ -11,7 +11,7 @@ requires-python = ">=3.10"
|
|
|
11
11
|
dependencies = [
|
|
12
12
|
"opentelemetry-distro",
|
|
13
13
|
"opentelemetry-exporter-otlp",
|
|
14
|
-
"google-adk >= 1.17.0",
|
|
14
|
+
"google-adk >= 1.17.0, < 2.0.0",
|
|
15
15
|
"bedrock-agentcore >= 1.0.3",
|
|
16
16
|
"botocore[crt] >= 1.35.0",
|
|
17
17
|
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
@@ -11,7 +11,7 @@ requires-python = ">=3.10"
|
|
|
11
11
|
dependencies = [
|
|
12
12
|
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
|
|
13
13
|
{{/if}}"aws-opentelemetry-distro",
|
|
14
|
-
"bedrock-agentcore >= 1.
|
|
14
|
+
"bedrock-agentcore >= 1.9.1",
|
|
15
15
|
"botocore[crt] >= 1.35.0",
|
|
16
16
|
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
|
|
17
17
|
{{/if}}"mcp >= 1.19.0",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
This is a project generated by the AgentCore CLI!
|
|
2
|
+
|
|
3
|
+
# Layout
|
|
4
|
+
|
|
5
|
+
The generated application code lives at the agent root directory. At the root, there is a `.gitignore` file, an
|
|
6
|
+
`agentcore/` folder which represents the configurations and state associated with this project. Other `agentcore`
|
|
7
|
+
commands like `deploy`, `dev`, and `invoke` rely on the configuration stored here.
|
|
8
|
+
|
|
9
|
+
## Agent Root
|
|
10
|
+
|
|
11
|
+
The main entrypoint to your app is defined in `main.ts`. Using the AgentCore SDK `BedrockAgentCoreApp`, this file
|
|
12
|
+
defines an HTTP server that streams tokens from your chosen Agent framework SDK.
|
|
13
|
+
|
|
14
|
+
`model/load.ts` instantiates your chosen model provider.
|
|
15
|
+
|
|
16
|
+
## Environment Variables
|
|
17
|
+
|
|
18
|
+
| Variable | Required | Description |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
{{#if hasIdentity}}| `{{identityProviders.[0].envVarName}}` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
21
|
+
{{/if}}| `LOCAL_DEV` | No | Set to `1` to use `.env.local` instead of AgentCore Identity |
|
|
22
|
+
|
|
23
|
+
# Developing locally
|
|
24
|
+
|
|
25
|
+
If installation was successful, `node_modules/` is already populated with dependencies.
|
|
26
|
+
|
|
27
|
+
`agentcore dev` will start a local server using `npx tsx watch main.ts` for hot reload. The port is logged to the terminal (default `8080`).
|
|
28
|
+
|
|
29
|
+
In a new terminal, you can invoke that server with:
|
|
30
|
+
|
|
31
|
+
`agentcore invoke --dev "What can you do"`
|
|
32
|
+
|
|
33
|
+
# Deployment
|
|
34
|
+
|
|
35
|
+
After providing credentials, `agentcore deploy` will deploy your project into Amazon Bedrock AgentCore.
|
|
36
|
+
|
|
37
|
+
Use `agentcore invoke` to invoke your deployed agent.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
|
|
2
|
+
import { Agent, McpClient, tool, type ToolList } from '@strands-agents/sdk';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { loadModel } from './model/load.js';
|
|
5
|
+
import { getStreamableHttpMcpClient } from './mcp_client/client.js';
|
|
6
|
+
|
|
7
|
+
// Define a collection of MCP clients (filter out anything that failed to initialize)
|
|
8
|
+
const mcpClients: McpClient[] = [getStreamableHttpMcpClient()].filter(
|
|
9
|
+
(client): client is McpClient => Boolean(client)
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
// Define a collection of tools used by the model
|
|
13
|
+
const tools: ToolList = [];
|
|
14
|
+
|
|
15
|
+
// Define a simple function tool — the Zod schema gives us type inference and runtime validation for free
|
|
16
|
+
const addNumbers = tool({
|
|
17
|
+
name: 'add_numbers',
|
|
18
|
+
description: 'Return the sum of two numbers',
|
|
19
|
+
inputSchema: z.object({
|
|
20
|
+
a: z.number(),
|
|
21
|
+
b: z.number(),
|
|
22
|
+
}),
|
|
23
|
+
callback: async ({ a, b }) => a + b,
|
|
24
|
+
});
|
|
25
|
+
tools.push(addNumbers);
|
|
26
|
+
|
|
27
|
+
// Add MCP clients to tools
|
|
28
|
+
tools.push(...mcpClients);
|
|
29
|
+
|
|
30
|
+
const SYSTEM_PROMPT = `
|
|
31
|
+
You are a helpful assistant. Use tools when appropriate.
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
let cachedAgent: Agent | null = null;
|
|
35
|
+
|
|
36
|
+
async function getOrCreateAgent(): Promise<Agent> {
|
|
37
|
+
if (!cachedAgent) {
|
|
38
|
+
const model = await loadModel();
|
|
39
|
+
cachedAgent = new Agent({
|
|
40
|
+
model,
|
|
41
|
+
systemPrompt: SYSTEM_PROMPT,
|
|
42
|
+
tools,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return cachedAgent;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const app = new BedrockAgentCoreApp({
|
|
49
|
+
invocationHandler: {
|
|
50
|
+
async *process(payload: any, context: any) {
|
|
51
|
+
const agent = await getOrCreateAgent();
|
|
52
|
+
|
|
53
|
+
for await (const event of agent.stream(payload.prompt ?? '')) {
|
|
54
|
+
if (
|
|
55
|
+
event.type === 'modelStreamUpdateEvent' &&
|
|
56
|
+
event.event?.type === 'modelContentBlockDeltaEvent' &&
|
|
57
|
+
event.event.delta?.type === 'textDelta'
|
|
58
|
+
) {
|
|
59
|
+
yield { data: event.event.delta.text };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
app.run({ port: parseInt(process.env.PORT ?? '8080') });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { McpClient } from '@strands-agents/sdk';
|
|
2
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
3
|
+
|
|
4
|
+
// ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
|
|
5
|
+
const EXAMPLE_MCP_ENDPOINT = 'https://mcp.exa.ai/mcp';
|
|
6
|
+
|
|
7
|
+
export function getStreamableHttpMcpClient(): McpClient {
|
|
8
|
+
// to use an MCP server that supports bearer authentication, add a headers() callback to requestInit
|
|
9
|
+
const transport = new StreamableHTTPClientTransport(new URL(EXAMPLE_MCP_ENDPOINT));
|
|
10
|
+
return new McpClient({ transport });
|
|
11
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{{#if (eq modelProvider "Bedrock")}}
|
|
2
|
+
import { BedrockModel } from '@strands-agents/sdk/models/bedrock';
|
|
3
|
+
|
|
4
|
+
export function loadModel(): BedrockModel {
|
|
5
|
+
return new BedrockModel({ modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0' });
|
|
6
|
+
}
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if (eq modelProvider "Anthropic")}}
|
|
9
|
+
import { AnthropicModel } from '@strands-agents/sdk/models/anthropic';
|
|
10
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
11
|
+
|
|
12
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
13
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
14
|
+
|
|
15
|
+
async function getApiKey(): Promise<string> {
|
|
16
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
17
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.ANTHROPIC_API_KEY;
|
|
18
|
+
if (!apiKey) {
|
|
19
|
+
throw new Error(`${IDENTITY_ENV_VAR} or ANTHROPIC_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
20
|
+
}
|
|
21
|
+
return apiKey;
|
|
22
|
+
}
|
|
23
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let _model: AnthropicModel | undefined;
|
|
27
|
+
|
|
28
|
+
export async function loadModel(): Promise<AnthropicModel> {
|
|
29
|
+
if (!_model) {
|
|
30
|
+
const apiKey = await getApiKey();
|
|
31
|
+
_model = new AnthropicModel({
|
|
32
|
+
apiKey,
|
|
33
|
+
modelId: 'claude-sonnet-4-5-20250929',
|
|
34
|
+
maxTokens: 5000,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return _model;
|
|
38
|
+
}
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{#if (eq modelProvider "OpenAI")}}
|
|
41
|
+
import { OpenAIModel } from '@strands-agents/sdk/models/openai';
|
|
42
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
43
|
+
|
|
44
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
45
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
46
|
+
|
|
47
|
+
async function getApiKey(): Promise<string> {
|
|
48
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
49
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.OPENAI_API_KEY;
|
|
50
|
+
if (!apiKey) {
|
|
51
|
+
throw new Error(`${IDENTITY_ENV_VAR} or OPENAI_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
52
|
+
}
|
|
53
|
+
return apiKey;
|
|
54
|
+
}
|
|
55
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let _model: OpenAIModel | undefined;
|
|
59
|
+
|
|
60
|
+
export async function loadModel(): Promise<OpenAIModel> {
|
|
61
|
+
if (!_model) {
|
|
62
|
+
const apiKey = await getApiKey();
|
|
63
|
+
_model = new OpenAIModel({
|
|
64
|
+
api: 'chat',
|
|
65
|
+
apiKey,
|
|
66
|
+
modelId: 'gpt-4.1',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return _model;
|
|
70
|
+
}
|
|
71
|
+
{{/if}}
|
|
72
|
+
{{#if (eq modelProvider "Gemini")}}
|
|
73
|
+
import { GoogleModel } from '@strands-agents/sdk/models/google';
|
|
74
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
75
|
+
|
|
76
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
77
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
78
|
+
|
|
79
|
+
async function getApiKey(): Promise<string> {
|
|
80
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
81
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.GEMINI_API_KEY;
|
|
82
|
+
if (!apiKey) {
|
|
83
|
+
throw new Error(`${IDENTITY_ENV_VAR} or GEMINI_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
84
|
+
}
|
|
85
|
+
return apiKey;
|
|
86
|
+
}
|
|
87
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let _model: GoogleModel | undefined;
|
|
91
|
+
|
|
92
|
+
export async function loadModel(): Promise<GoogleModel> {
|
|
93
|
+
if (!_model) {
|
|
94
|
+
const apiKey = await getApiKey();
|
|
95
|
+
_model = new GoogleModel({
|
|
96
|
+
apiKey,
|
|
97
|
+
modelId: 'gemini-2.5-flash',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return _model;
|
|
101
|
+
}
|
|
102
|
+
{{/if}}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AgentCore Runtime Application using Strands TypeScript SDK",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"start": "node dist/main.js",
|
|
10
|
+
"dev": "tsx watch main.ts"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
{{#if (eq modelProvider "Anthropic")}}
|
|
14
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if (eq modelProvider "OpenAI")}}
|
|
17
|
+
"openai": "^6.7.0",
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{#if (eq modelProvider "Gemini")}}
|
|
20
|
+
"@google/genai": "^1.40.0",
|
|
21
|
+
{{/if}}
|
|
22
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
23
|
+
"@strands-agents/sdk": "1.0.0-rc.4",
|
|
24
|
+
"bedrock-agentcore": "^0.2.4",
|
|
25
|
+
"tsx": "^4.19.0",
|
|
26
|
+
"zod": "^4.4.3"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.0.0",
|
|
30
|
+
"typescript": "^5.6.0"
|
|
31
|
+
},
|
|
32
|
+
"overrides": {
|
|
33
|
+
"bedrock-agentcore": {
|
|
34
|
+
"@strands-agents/sdk": "$@strands-agents/sdk"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"declaration": false,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
"outDir": "dist",
|
|
14
|
+
"rootDir": ".",
|
|
15
|
+
"types": ["node"]
|
|
16
|
+
},
|
|
17
|
+
"include": ["**/*.ts"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
This is a project generated by the AgentCore CLI!
|
|
2
|
+
|
|
3
|
+
# Layout
|
|
4
|
+
|
|
5
|
+
The generated application code lives at the agent root directory. At the root, there is a `.gitignore` file, an
|
|
6
|
+
`agentcore/` folder which represents the configurations and state associated with this project. Other `agentcore`
|
|
7
|
+
commands like `deploy`, `dev`, and `invoke` rely on the configuration stored here.
|
|
8
|
+
|
|
9
|
+
## Agent Root
|
|
10
|
+
|
|
11
|
+
The main entrypoint to your app is defined in `main.ts`. Using the AgentCore SDK `BedrockAgentCoreApp`, this file
|
|
12
|
+
defines an HTTP app that streams tokens using the Vercel AI SDK's `streamText` API.
|
|
13
|
+
|
|
14
|
+
`model/load.ts` instantiates your chosen model provider.
|
|
15
|
+
|
|
16
|
+
## Environment Variables
|
|
17
|
+
|
|
18
|
+
| Variable | Required | Description |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
{{#if hasIdentity}}| `{{identityProviders.[0].envVarName}}` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
21
|
+
{{/if}}| `LOCAL_DEV` | No | Set to `1` to use `.env.local` instead of AgentCore Identity |
|
|
22
|
+
|
|
23
|
+
# Developing locally
|
|
24
|
+
|
|
25
|
+
If installation was successful, `node_modules/` is already populated with dependencies.
|
|
26
|
+
|
|
27
|
+
`agentcore dev` will start a local server using `npx tsx watch main.ts` for hot reload. The port is logged to the terminal (default `8080`).
|
|
28
|
+
|
|
29
|
+
In a new terminal, you can invoke that server with:
|
|
30
|
+
|
|
31
|
+
`agentcore invoke --dev "What can you do"`
|
|
32
|
+
|
|
33
|
+
# Deployment
|
|
34
|
+
|
|
35
|
+
After providing credentials, `agentcore deploy` will deploy your project into Amazon Bedrock AgentCore.
|
|
36
|
+
|
|
37
|
+
Use `agentcore invoke` to invoke your deployed agent.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
|
|
2
|
+
import { streamText } from 'ai';
|
|
3
|
+
import { loadModel } from './model/load.js';
|
|
4
|
+
|
|
5
|
+
const SYSTEM_PROMPT = `You are a helpful assistant.`;
|
|
6
|
+
|
|
7
|
+
const app = new BedrockAgentCoreApp({
|
|
8
|
+
invocationHandler: {
|
|
9
|
+
async *process(payload: any, context: any) {
|
|
10
|
+
const model = await loadModel();
|
|
11
|
+
const result = streamText({
|
|
12
|
+
model,
|
|
13
|
+
system: SYSTEM_PROMPT,
|
|
14
|
+
prompt: payload.prompt ?? '',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
for await (const chunk of result.textStream) {
|
|
18
|
+
yield { data: chunk };
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
app.run({ port: parseInt(process.env.PORT ?? '8080') });
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{{#if (eq modelProvider "Bedrock")}}
|
|
2
|
+
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
|
|
3
|
+
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
|
|
4
|
+
|
|
5
|
+
const provider = fromNodeProviderChain();
|
|
6
|
+
|
|
7
|
+
const bedrock = createAmazonBedrock({
|
|
8
|
+
region: process.env.AWS_REGION ?? 'us-east-1',
|
|
9
|
+
credentialProvider: async () => {
|
|
10
|
+
const creds = await provider();
|
|
11
|
+
return {
|
|
12
|
+
accessKeyId: creds.accessKeyId,
|
|
13
|
+
secretAccessKey: creds.secretAccessKey,
|
|
14
|
+
sessionToken: creds.sessionToken,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export function loadModel() {
|
|
20
|
+
return bedrock('us.anthropic.claude-sonnet-4-5-20250929-v1:0');
|
|
21
|
+
}
|
|
22
|
+
{{/if}}
|
|
23
|
+
{{#if (eq modelProvider "Anthropic")}}
|
|
24
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
25
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
26
|
+
|
|
27
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
28
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
29
|
+
|
|
30
|
+
async function getApiKey(): Promise<string> {
|
|
31
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
32
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.ANTHROPIC_API_KEY;
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
throw new Error(`${IDENTITY_ENV_VAR} or ANTHROPIC_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
35
|
+
}
|
|
36
|
+
return apiKey;
|
|
37
|
+
}
|
|
38
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let _anthropic: ReturnType<typeof createAnthropic> | undefined;
|
|
42
|
+
|
|
43
|
+
async function getProvider() {
|
|
44
|
+
if (!_anthropic) {
|
|
45
|
+
const apiKey = await getApiKey();
|
|
46
|
+
_anthropic = createAnthropic({ apiKey });
|
|
47
|
+
}
|
|
48
|
+
return _anthropic;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function loadModel() {
|
|
52
|
+
const anthropic = await getProvider();
|
|
53
|
+
return anthropic('claude-sonnet-4-5-20250929');
|
|
54
|
+
}
|
|
55
|
+
{{/if}}
|
|
56
|
+
{{#if (eq modelProvider "OpenAI")}}
|
|
57
|
+
import { createOpenAI } from '@ai-sdk/openai';
|
|
58
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
59
|
+
|
|
60
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
61
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
62
|
+
|
|
63
|
+
async function getApiKey(): Promise<string> {
|
|
64
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
65
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.OPENAI_API_KEY;
|
|
66
|
+
if (!apiKey) {
|
|
67
|
+
throw new Error(`${IDENTITY_ENV_VAR} or OPENAI_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
68
|
+
}
|
|
69
|
+
return apiKey;
|
|
70
|
+
}
|
|
71
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let _openai: ReturnType<typeof createOpenAI> | undefined;
|
|
75
|
+
|
|
76
|
+
async function getProvider() {
|
|
77
|
+
if (!_openai) {
|
|
78
|
+
const apiKey = await getApiKey();
|
|
79
|
+
_openai = createOpenAI({ apiKey });
|
|
80
|
+
}
|
|
81
|
+
return _openai;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function loadModel() {
|
|
85
|
+
const openai = await getProvider();
|
|
86
|
+
return openai('gpt-4.1');
|
|
87
|
+
}
|
|
88
|
+
{{/if}}
|
|
89
|
+
{{#if (eq modelProvider "Gemini")}}
|
|
90
|
+
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
91
|
+
import { withApiKey } from 'bedrock-agentcore/identity';
|
|
92
|
+
|
|
93
|
+
const IDENTITY_PROVIDER_NAME = '{{identityProviders.[0].name}}';
|
|
94
|
+
const IDENTITY_ENV_VAR = '{{identityProviders.[0].envVarName}}';
|
|
95
|
+
|
|
96
|
+
async function getApiKey(): Promise<string> {
|
|
97
|
+
if (process.env.LOCAL_DEV === '1') {
|
|
98
|
+
const apiKey = process.env[IDENTITY_ENV_VAR] ?? process.env.GEMINI_API_KEY;
|
|
99
|
+
if (!apiKey) {
|
|
100
|
+
throw new Error(`${IDENTITY_ENV_VAR} or GEMINI_API_KEY not found. Add your key to agentcore/.env.local`);
|
|
101
|
+
}
|
|
102
|
+
return apiKey;
|
|
103
|
+
}
|
|
104
|
+
return withApiKey({ providerName: IDENTITY_PROVIDER_NAME })(async (apiKey: string) => apiKey)();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let _google: ReturnType<typeof createGoogleGenerativeAI> | undefined;
|
|
108
|
+
|
|
109
|
+
async function getProvider() {
|
|
110
|
+
if (!_google) {
|
|
111
|
+
const apiKey = await getApiKey();
|
|
112
|
+
_google = createGoogleGenerativeAI({ apiKey });
|
|
113
|
+
}
|
|
114
|
+
return _google;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function loadModel() {
|
|
118
|
+
const google = await getProvider();
|
|
119
|
+
return google('gemini-2.5-flash');
|
|
120
|
+
}
|
|
121
|
+
{{/if}}
|