@aws/nx-plugin-mcp 0.120.0 → 0.121.0
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/bin/aws-nx-mcp.js +23 -35
- package/docs/guides/astro-docs.mdx +142 -0
- package/docs/guides/connection/py-agent-a2a.mdx +105 -0
- package/docs/guides/connection/py-agent-mcp.mdx +147 -0
- package/docs/guides/connection/react-agui.mdx +240 -0
- package/docs/guides/connection/react-fastapi.mdx +1476 -0
- package/docs/guides/connection/react-py-agent.mdx +198 -0
- package/docs/guides/connection/react-smithy.mdx +1355 -0
- package/docs/guides/connection/react-trpc.mdx +447 -0
- package/docs/guides/connection/react-ts-agent.mdx +198 -0
- package/docs/guides/connection/smithy-rdb.mdx +161 -0
- package/docs/guides/connection/trpc-rdb.mdx +127 -0
- package/docs/guides/connection/ts-agent-a2a.mdx +106 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +144 -0
- package/docs/guides/connection/ts-agent-rdb.mdx +141 -0
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +135 -0
- package/docs/guides/connection.mdx +126 -0
- package/docs/guides/docker-bundling.mdx +403 -0
- package/docs/guides/fastapi.mdx +509 -0
- package/docs/guides/license.mdx +293 -0
- package/docs/guides/nx-generator.mdx +588 -0
- package/docs/guides/py-agent.mdx +483 -0
- package/docs/guides/py-mcp-server.mdx +161 -0
- package/docs/guides/python-lambda-function.mdx +207 -0
- package/docs/guides/python-project.mdx +228 -0
- package/docs/guides/react-website-auth.mdx +216 -0
- package/docs/guides/react-website.mdx +421 -0
- package/docs/guides/runtime-config.mdx +312 -0
- package/docs/guides/terraform-project.mdx +317 -0
- package/docs/guides/trpc.mdx +816 -0
- package/docs/guides/ts-agent.mdx +436 -0
- package/docs/guides/ts-lambda-function.mdx +218 -0
- package/docs/guides/ts-mcp-server.mdx +169 -0
- package/docs/guides/ts-nx-plugin.mdx +159 -0
- package/docs/guides/ts-rdb.mdx +759 -0
- package/docs/guides/ts-smithy-api.mdx +661 -0
- package/docs/guides/typescript-infrastructure.mdx +408 -0
- package/docs/guides/typescript-project.mdx +312 -0
- package/docs/guides/workspace.mdx +181 -0
- package/docs/snippets/agent/architecture.mdx +72 -0
- package/docs/snippets/agent/bedrock-deployment.mdx +172 -0
- package/docs/snippets/agent/runtime-arn.mdx +64 -0
- package/docs/snippets/api/api-architecture.mdx +93 -0
- package/docs/snippets/api/api-choice-note.mdx +6 -0
- package/docs/snippets/api/cors-configuration-cdk-note.mdx +25 -0
- package/docs/snippets/api/cors-configuration-terraform-note.mdx +28 -0
- package/docs/snippets/api/shared-constructs.mdx +38 -0
- package/docs/snippets/api/type-safe-api-integrations.mdx +643 -0
- package/docs/snippets/api/waf-configuration.mdx +37 -0
- package/docs/snippets/connection/a2a-infrastructure.mdx +63 -0
- package/docs/snippets/connection/lambda-rdb-ssl-requirements.mdx +40 -0
- package/docs/snippets/connection/mcp-server-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +72 -0
- package/docs/snippets/connection/react-agent-infrastructure.mdx +61 -0
- package/docs/snippets/connection/strands-agent-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/lambda-function/architecture.mdx +36 -0
- package/docs/snippets/lambda-function/deploying-your-function.mdx +118 -0
- package/docs/snippets/mcp/architecture.mdx +58 -0
- package/docs/snippets/mcp/assistant-docs.mdx +10 -0
- package/docs/snippets/mcp/bedrock-deployment.mdx +167 -0
- package/docs/snippets/mcp/config.mdx +13 -0
- package/docs/snippets/mcp/configuration-py.mdx +42 -0
- package/docs/snippets/mcp/configuration-ts.mdx +53 -0
- package/docs/snippets/mcp/observability.mdx +8 -0
- package/docs/snippets/mcp/shared-constructs.mdx +32 -0
- package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +602 -0
- package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +915 -0
- package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +161 -0
- package/docs/snippets/pdk-migration/example/04-deploy.mdx +229 -0
- package/docs/snippets/pdk-migration/faq/aws-arch.mdx +17 -0
- package/docs/snippets/pdk-migration/faq/cdk-graph.mdx +29 -0
- package/docs/snippets/pdk-migration/faq/infrastructure-python-java.mdx +19 -0
- package/docs/snippets/pdk-migration/faq/pdk-nag.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/pipeline.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +310 -0
- package/docs/snippets/pdk-migration/faq/use-of-projen.mdx +15 -0
- package/docs/snippets/prerequisites.mdx +20 -0
- package/docs/snippets/required-prerequisites.mdx +12 -0
- package/docs/snippets/shared-constructs.mdx +40 -0
- package/docs/snippets/tools/acurl.mdx +73 -0
- package/docs/snippets/ts-bundle.mdx +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TypeScript Agent
|
|
3
|
+
description: Generate a TypeScript Agent for building AI agents with tools and deploy to Amazon Bedrock AgentCore Runtime
|
|
4
|
+
generator: ts#agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
|
|
8
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
9
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
10
|
+
import Link from '@components/link.astro';
|
|
11
|
+
import Snippet from '@components/snippet.astro';
|
|
12
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
13
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
14
|
+
import PackageManagerExecCommand from '@components/package-manager-exec-command.astro';
|
|
15
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
16
|
+
|
|
17
|
+
Generate a TypeScript [Strands Agent](https://strandsagents.com/) for building AI agents with tools, and optionally deploy it to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/). By default, the generator uses [tRPC](https://trpc.io/) over WebSocket to leverage [AgentCore's bidirectional streaming support](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-get-started-websocket.html) for real-time, type-safe communication. Alternatively, you can choose the [Agent-to-Agent (A2A)](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-a2a.html) protocol for interoperability with other A2A-compatible agents, or the [AG-UI](https://docs.ag-ui.com/) protocol for direct frontend integration via [CopilotKit](https://docs.copilotkit.ai/aws-strands).
|
|
18
|
+
|
|
19
|
+
## What is Strands?
|
|
20
|
+
|
|
21
|
+
[Strands](https://strandsagents.com/docs/user-guide/quickstart/overview/) is a lightweight framework for building AI agents. Key features include:
|
|
22
|
+
|
|
23
|
+
- **Lightweight and customizable**: Simple agent loop that gets out of your way
|
|
24
|
+
- **Production ready**: Full observability, tracing, and deployment options for scale
|
|
25
|
+
- **Model and provider agnostic**: Supports many different models from various providers
|
|
26
|
+
- **Community-driven tools**: Powerful set of community-contributed tools
|
|
27
|
+
- **Multi-agent support**: Advanced techniques like agent teams and autonomous agents
|
|
28
|
+
- **Flexible interaction modes**: Conversational, streaming, and non-streaming support
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
### Generate an Agent
|
|
33
|
+
|
|
34
|
+
You can generate a TypeScript Agent in two ways:
|
|
35
|
+
|
|
36
|
+
<RunGenerator generator="ts#agent" />
|
|
37
|
+
|
|
38
|
+
:::tip[Project Prerequisite]
|
|
39
|
+
First use the <Link path="/guides/typescript-project">`ts#project`</Link> generator to create a project to add your Agent to.
|
|
40
|
+
:::
|
|
41
|
+
|
|
42
|
+
### Options
|
|
43
|
+
|
|
44
|
+
<GeneratorParameters generator="ts#agent" />
|
|
45
|
+
|
|
46
|
+
## Generator Output
|
|
47
|
+
|
|
48
|
+
The generator will add the following files to your existing TypeScript project. The files generated depend on the chosen `protocol`:
|
|
49
|
+
|
|
50
|
+
<OptionFilter when={{ protocol: 'HTTP' }} description="tRPC-over-WebSocket layout">
|
|
51
|
+
### HTTP Protocol (default)
|
|
52
|
+
|
|
53
|
+
<FileTree>
|
|
54
|
+
- your-project/
|
|
55
|
+
- src/
|
|
56
|
+
- agent/ (or custom name if specified)
|
|
57
|
+
- index.ts Entry point for Bedrock AgentCore Runtime (tRPC/WebSocket server)
|
|
58
|
+
- init.ts tRPC initialization
|
|
59
|
+
- router.ts tRPC router with agent procedures
|
|
60
|
+
- agent.ts Main agent definition with sample tools
|
|
61
|
+
- client.ts Vended client for invoking your agent
|
|
62
|
+
- agent-core-trpc-client.ts Client factory for connecting to agents on AgentCore Runtime
|
|
63
|
+
- Dockerfile Entry point for hosting your agent (excluded when `computeType` is set to `None`)
|
|
64
|
+
- package.json Updated with Strands dependencies
|
|
65
|
+
- project.json Updated with agent serve targets
|
|
66
|
+
</FileTree>
|
|
67
|
+
</OptionFilter>
|
|
68
|
+
|
|
69
|
+
<OptionFilter when={{ protocol: 'A2A' }} description="Strands A2A Express server layout">
|
|
70
|
+
### A2A Protocol
|
|
71
|
+
|
|
72
|
+
The entry point uses the [Strands A2A Express Server](https://strandsagents.com/docs/user-guide/concepts/multi-agent/agent-to-agent) instead of tRPC:
|
|
73
|
+
|
|
74
|
+
<FileTree>
|
|
75
|
+
- your-project/
|
|
76
|
+
- src/
|
|
77
|
+
- agent/ (or custom name if specified)
|
|
78
|
+
- index.ts A2A Express server entry point
|
|
79
|
+
- agent.ts Main agent definition with sample tools
|
|
80
|
+
- Dockerfile Entry point for hosting your agent (excluded when `computeType` is set to `None`)
|
|
81
|
+
- package.json Updated with Strands and Express dependencies
|
|
82
|
+
- project.json Updated with agent serve targets
|
|
83
|
+
</FileTree>
|
|
84
|
+
</OptionFilter>
|
|
85
|
+
|
|
86
|
+
<OptionFilter when={{ protocol: 'AG-UI' }} description="AG-UI SSE-over-POST server layout">
|
|
87
|
+
### AG-UI Protocol
|
|
88
|
+
|
|
89
|
+
The entry point uses [`@ag-ui/aws-strands`](https://www.npmjs.com/package/@ag-ui/aws-strands) to expose the agent via the [AG-UI protocol](https://docs.ag-ui.com/) (SSE over POST), compatible with [CopilotKit](https://docs.copilotkit.ai/aws-strands):
|
|
90
|
+
|
|
91
|
+
<FileTree>
|
|
92
|
+
- your-project/
|
|
93
|
+
- src/
|
|
94
|
+
- agent/ (or custom name if specified)
|
|
95
|
+
- index.ts AG-UI server entry point (Express + SSE)
|
|
96
|
+
- agent.ts Main agent definition with sample tools
|
|
97
|
+
- Dockerfile Entry point for hosting your agent (excluded when `computeType` is set to `None`)
|
|
98
|
+
- package.json Updated with Strands and AG-UI dependencies
|
|
99
|
+
- project.json Updated with agent serve targets
|
|
100
|
+
</FileTree>
|
|
101
|
+
</OptionFilter>
|
|
102
|
+
|
|
103
|
+
### Infrastructure
|
|
104
|
+
|
|
105
|
+
<OptionFilter when={{ computeType: 'BedrockAgentCoreRuntime' }} description="Bedrock AgentCore Runtime deployment">
|
|
106
|
+
<Snippet name="shared-constructs" />
|
|
107
|
+
|
|
108
|
+
For deploying your Agent, the following files are generated:
|
|
109
|
+
|
|
110
|
+
<Infrastructure>
|
|
111
|
+
<Fragment slot="cdk">
|
|
112
|
+
<FileTree>
|
|
113
|
+
- packages/common/constructs/src
|
|
114
|
+
- app
|
|
115
|
+
- agents
|
|
116
|
+
- \<project-name>
|
|
117
|
+
- \<project-name>.ts CDK construct for deploying your agent
|
|
118
|
+
</FileTree>
|
|
119
|
+
</Fragment>
|
|
120
|
+
<Fragment slot="terraform">
|
|
121
|
+
<FileTree>
|
|
122
|
+
- packages/common/terraform/src
|
|
123
|
+
- app
|
|
124
|
+
- agents
|
|
125
|
+
- \<project-name>
|
|
126
|
+
- \<project-name>.tf Module for deploying your agent
|
|
127
|
+
- core
|
|
128
|
+
- agent-core
|
|
129
|
+
- runtime.tf Generic module for deploying to Bedrock AgentCore Runtime
|
|
130
|
+
</FileTree>
|
|
131
|
+
</Fragment>
|
|
132
|
+
</Infrastructure>
|
|
133
|
+
</OptionFilter>
|
|
134
|
+
|
|
135
|
+
<OptionFilter when={{ computeType: 'None' }} description="No infrastructure is vended for computeType=None">
|
|
136
|
+
If you selected `None` for `computeType`, no CDK constructs or Terraform modules are generated — the Agent can only be run locally. The `auth` option is ignored in this mode since there is no hosted endpoint to authenticate.
|
|
137
|
+
</OptionFilter>
|
|
138
|
+
|
|
139
|
+
#### Architecture
|
|
140
|
+
|
|
141
|
+
<Snippet name="agent/architecture" />
|
|
142
|
+
|
|
143
|
+
## Working with Your Agent
|
|
144
|
+
|
|
145
|
+
### Protocol
|
|
146
|
+
|
|
147
|
+
Your agent's server protocol determines how it communicates. You can choose between:
|
|
148
|
+
|
|
149
|
+
- **HTTP** (default): Uses [tRPC](https://trpc.io/) over WebSocket for real-time, type-safe communication. Best for custom client integrations and fine-grained control over the agent's API.
|
|
150
|
+
- **A2A**: Uses the [Agent-to-Agent (A2A)](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-a2a.html) protocol for standardized inter-agent communication. Best when your agent needs to be discoverable and invokable by other A2A-compatible agents.
|
|
151
|
+
- **AG-UI**: Uses the [AG-UI protocol](https://docs.ag-ui.com/) (SSE over POST) via [`@ag-ui/aws-strands`](https://www.npmjs.com/package/@ag-ui/aws-strands) for direct frontend integration with [CopilotKit](https://docs.copilotkit.ai/aws-strands). Best when you want a rich chat UI with streaming, tool-call visualization, and state management.
|
|
152
|
+
|
|
153
|
+
The protocol is set in the CDK/Terraform infrastructure, and the application code is generated accordingly.
|
|
154
|
+
|
|
155
|
+
<OptionFilter when={{ protocol: 'HTTP' }} description="tRPC over WebSocket details">
|
|
156
|
+
### tRPC over WebSocket (HTTP protocol)
|
|
157
|
+
|
|
158
|
+
The TypeScript Agent uses [tRPC](https://trpc.io/) over WebSocket, leveraging [AgentCore's bidirectional streaming support](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-get-started-websocket.html) to enable real-time, type-safe communication between clients and your agent.
|
|
159
|
+
|
|
160
|
+
Since tRPC supports Query, Mutation and Subscription procedures over WebSocket, you can define any number of procedures. By default, a single subscription procedure named `invoke` is defined for you in `router.ts`.
|
|
161
|
+
</OptionFilter>
|
|
162
|
+
|
|
163
|
+
### Adding Tools
|
|
164
|
+
|
|
165
|
+
Tools are functions that the AI agent can call to perform actions. You can add new tools in the `agent.ts` file:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { Agent, tool } from '@strands-agents/sdk';
|
|
169
|
+
import { z } from 'zod';
|
|
170
|
+
|
|
171
|
+
const letterCounter = tool({
|
|
172
|
+
name: 'letter_counter',
|
|
173
|
+
description: 'Count occurrences of a specific letter in a word',
|
|
174
|
+
inputSchema: z.object({
|
|
175
|
+
word: z.string().describe('The input word to search in'),
|
|
176
|
+
letter: z.string().length(1).describe('The specific letter to count'),
|
|
177
|
+
}),
|
|
178
|
+
callback: (input) => {
|
|
179
|
+
const { word, letter } = input;
|
|
180
|
+
const count = word.toLowerCase().split(letter.toLowerCase()).length - 1;
|
|
181
|
+
return `The letter '${letter}' appears ${count} time(s) in '${word}'`;
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Add tools to your agent
|
|
186
|
+
export const getAgent = async (sessionId: string) => {
|
|
187
|
+
return new Agent({
|
|
188
|
+
systemPrompt: 'You are a helpful assistant with access to various tools.',
|
|
189
|
+
tools: [letterCounter],
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The Strands framework automatically handles:
|
|
195
|
+
- Input validation using Zod schemas
|
|
196
|
+
- JSON schema generation for tool calling
|
|
197
|
+
- Error handling and response formatting
|
|
198
|
+
|
|
199
|
+
### Model Configuration
|
|
200
|
+
|
|
201
|
+
By default, Strands agents use Claude 4 Sonnet, but you can easily switch between model providers:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { Agent } from '@strands-agents/sdk';
|
|
205
|
+
import { BedrockModel } from '@strands-agents/sdk/models/bedrock';
|
|
206
|
+
import { OpenAIModel } from '@strands-agents/sdk/models/openai';
|
|
207
|
+
|
|
208
|
+
// Use Bedrock
|
|
209
|
+
const bedrockModel = new BedrockModel({
|
|
210
|
+
modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
|
|
211
|
+
});
|
|
212
|
+
let agent = new Agent({ model: bedrockModel });
|
|
213
|
+
let response = await agent.invoke('What can you help me with?');
|
|
214
|
+
|
|
215
|
+
// Alternatively, use OpenAI by just switching model provider
|
|
216
|
+
const openaiModel = new OpenAIModel({
|
|
217
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
218
|
+
modelId: 'gpt-4o',
|
|
219
|
+
});
|
|
220
|
+
agent = new Agent({ model: openaiModel });
|
|
221
|
+
response = await agent.invoke('What can you help me with?');
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
See the [Strands documentation on model providers](https://strandsagents.com/docs/user-guide/concepts/model-providers/) for more configuration options.
|
|
225
|
+
|
|
226
|
+
### Consuming MCP Servers
|
|
227
|
+
|
|
228
|
+
You can [add tools from MCP servers](https://strandsagents.com/docs/user-guide/concepts/tools/mcp-tools/) to your Strands agent.
|
|
229
|
+
|
|
230
|
+
For consuming MCP Servers which you have created using the <Link path="/guides/py-mcp-server">`py#mcp-server`</Link> or <Link path="/guides/ts-mcp-server">`ts#mcp-server`</Link> generators you can make use of the <Link path="/guides/connection/ts-agent-mcp">`connection` generator</Link>.
|
|
231
|
+
|
|
232
|
+
<RunGenerator generator="connection" />
|
|
233
|
+
|
|
234
|
+
Refer to the <Link path="/guides/connection/ts-agent-mcp">`connection` generator guide</Link> for details about how the connection is set up.
|
|
235
|
+
|
|
236
|
+
For other MCP servers, please refer to the [Strands Documentation](https://strandsagents.com/docs/user-guide/concepts/tools/mcp-tools/).
|
|
237
|
+
|
|
238
|
+
### More
|
|
239
|
+
|
|
240
|
+
For a more in-depth guide to writing Strands agents, refer to the [Strands documentation](https://strandsagents.com/docs/user-guide/quickstart/overview/).
|
|
241
|
+
|
|
242
|
+
<OptionFilter when={{ protocol: 'A2A' }} description="A2A Express server details">
|
|
243
|
+
## A2A Server (A2A protocol)
|
|
244
|
+
|
|
245
|
+
The generated `index.ts` mounts the [Strands A2A Express Server](https://strandsagents.com/docs/user-guide/concepts/multi-agent/agent-to-agent) onto an Express app so the generated agent exposes the A2A protocol endpoints alongside a `/ping` health check. When deployed to AgentCore, the entry point resolves the runtime's public ARN from AppConfig and advertises it in the agent card.
|
|
246
|
+
|
|
247
|
+
Most users will not need to modify this file — edit `agent.ts` to change tools or the system prompt. A2A agents listen on port `9000` (vs `8080` for HTTP), which the generated Dockerfile and infrastructure are already configured for.
|
|
248
|
+
</OptionFilter>
|
|
249
|
+
|
|
250
|
+
<OptionFilter when={{ protocol: 'AG-UI' }} description="AG-UI server details">
|
|
251
|
+
## AG-UI Server (AG-UI protocol)
|
|
252
|
+
|
|
253
|
+
The generated `index.ts` wraps your Strands `Agent` in an [`@ag-ui/aws-strands`](https://www.npmjs.com/package/@ag-ui/aws-strands) `StrandsAgent` and creates an Express app via `createStrandsApp()`. The resulting app exposes a single POST endpoint that streams [AG-UI](https://docs.ag-ui.com/) events over Server-Sent Events (SSE), as well as `/ping` for the AgentCore runtime health check.
|
|
254
|
+
|
|
255
|
+
AG-UI agents are designed to be consumed directly by a frontend. Use the <Link path="/guides/connection/react-agui">`connection` generator</Link> to wire your React website up to the agent with a [CopilotKit](https://docs.copilotkit.ai/aws-strands) provider and [AG-UI HttpAgent](https://docs.ag-ui.com/) client.
|
|
256
|
+
|
|
257
|
+
Most users will not need to modify `index.ts` — edit `agent.ts` to change tools or the system prompt. AG-UI agents listen on port `8080` (same as HTTP), which the generated Dockerfile and infrastructure are already configured for.
|
|
258
|
+
</OptionFilter>
|
|
259
|
+
|
|
260
|
+
## Running Your Agent
|
|
261
|
+
|
|
262
|
+
### Local Development
|
|
263
|
+
|
|
264
|
+
The generator configures a target named `<your-agent-name>-serve`, which starts your Agent locally for development and testing.
|
|
265
|
+
|
|
266
|
+
<NxCommands commands={['agent-serve your-project']} />
|
|
267
|
+
|
|
268
|
+
This command uses `tsx --watch` to automatically restart the server when files change. The agent will be available at `http://localhost:8081` (or the assigned port if you have multiple agents).
|
|
269
|
+
|
|
270
|
+
### Chat with Your Agent
|
|
271
|
+
|
|
272
|
+
The generator configures a `<your-agent-name>-chat` Nx target that depends on `<your-agent-name>-serve-local`. Running it starts the agent locally and drops you into an interactive terminal chat:
|
|
273
|
+
|
|
274
|
+
<NxCommands commands={['run your-project:agent-chat']} />
|
|
275
|
+
|
|
276
|
+
For **HTTP** (tRPC over WebSocket) agents, the generator also emits a tiny `scripts/<your-agent-name>/chat.ts` that wraps the generated `<Agent>Client.local({ url })` so you can customize it as you evolve the agent's input shape.
|
|
277
|
+
|
|
278
|
+
<OptionFilter when={{ computeType: 'BedrockAgentCoreRuntime' }} description="Bedrock AgentCore Runtime deployment details">
|
|
279
|
+
## Deploying Your Agent to Bedrock AgentCore Runtime
|
|
280
|
+
|
|
281
|
+
<Snippet name="agent/bedrock-deployment" parentHeading="Deploying Your Agent to Bedrock AgentCore Runtime" />
|
|
282
|
+
|
|
283
|
+
### Bundle Target
|
|
284
|
+
|
|
285
|
+
<Snippet name="ts-bundle" />
|
|
286
|
+
|
|
287
|
+
The bundle target uses `index.ts` as the entrypoint for the WebSocket server to host on Bedrock AgentCore Runtime.
|
|
288
|
+
|
|
289
|
+
### Docker Target
|
|
290
|
+
|
|
291
|
+
The generator configures a `<your-agent-name>-docker` target which copies the `Dockerfile` from your agent source directory into the bundle output directory. This co-locates the `Dockerfile` with the bundled artifacts, allowing CDK to build the Docker image directly using `AgentRuntimeArtifact.fromAsset`.
|
|
292
|
+
|
|
293
|
+
A `docker` target is also generated which prepares the docker context for all agents if you have multiple defined.
|
|
294
|
+
|
|
295
|
+
### Observability
|
|
296
|
+
|
|
297
|
+
Your agent is automatically configured with observability using the [AWS Distro for Open Telemetry](https://aws.amazon.com/otel/) (ADOT), by configuring auto-instrumentation in your `Dockerfile`.
|
|
298
|
+
|
|
299
|
+
You can find traces in the CloudWatch AWS Console, by selecting "GenAI Observability" in the menu. Note that for traces to be populated you will need to enable [Transaction Search](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Transaction-Search.html).
|
|
300
|
+
|
|
301
|
+
For more details, refer to the [AgentCore documentation on observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-configure.html).
|
|
302
|
+
</OptionFilter>
|
|
303
|
+
|
|
304
|
+
## Invoking your Agent
|
|
305
|
+
|
|
306
|
+
Agent communication is transmitted via tRPC over WebSocket. As such, it's recommended to use the generated type-safe client factory in `client.ts`.
|
|
307
|
+
|
|
308
|
+
<OptionFilter when={{ protocol: 'HTTP' }} description="tRPC-over-WebSocket client factory invocation details">
|
|
309
|
+
### Invoke the Local Server
|
|
310
|
+
|
|
311
|
+
You can invoke a locally running agent using the `.local` factory method from the client factory.
|
|
312
|
+
|
|
313
|
+
You can, for example create a file named `scripts/test.ts` in your workspace which imports the client:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// scripts/test.ts
|
|
317
|
+
import { AgentClient } from '../packages/<project>/src/agent/client.js';
|
|
318
|
+
|
|
319
|
+
const client = AgentClient.local({ url: 'http://localhost:8081/ws' });
|
|
320
|
+
|
|
321
|
+
client.invoke.subscribe({ message: 'what is 1 plus 1?' }, { onData: console.log });
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
:::tip[Quick Testing]
|
|
325
|
+
Run with `tsx` as a quick way to test out your agent.
|
|
326
|
+
|
|
327
|
+
<PackageManagerExecCommand commands={['tsx scripts/test.ts']} />
|
|
328
|
+
:::
|
|
329
|
+
|
|
330
|
+
### Invoke the Deployed Agent
|
|
331
|
+
|
|
332
|
+
<Snippet name="agent/runtime-arn" parentHeading="Invoke the Deployed Agent" />
|
|
333
|
+
|
|
334
|
+
#### NodeJS
|
|
335
|
+
|
|
336
|
+
The generated `client.ts` file includes a type-safe client factory which can be used to invoke your deployed agent.
|
|
337
|
+
|
|
338
|
+
:::caution[HTTP Header Authentication]
|
|
339
|
+
The client factory uses HTTP headers in the WebSocket handshake to authenticate requests to Bedrock AgentCore Runtime. This is not possible in a browser, and therefore this client is not suitable for browser environments. Refer to the below "Browser" section for details regarding invocation from a browser.
|
|
340
|
+
:::
|
|
341
|
+
|
|
342
|
+
<Tabs syncKey="auth">
|
|
343
|
+
<TabItem label="IAM" _filter={{ auth: 'IAM' }}>
|
|
344
|
+
##### IAM Authentication
|
|
345
|
+
|
|
346
|
+
You can invoke your deployed agent by passing its ARN to the `withIamAuth` factory method:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { AgentClient } from './agent/client.js';
|
|
350
|
+
|
|
351
|
+
const client = AgentClient.withIamAuth({
|
|
352
|
+
agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
client.invoke.subscribe({ message: 'what is 1 plus 1?' }, {
|
|
356
|
+
onData: (message) => console.log(message),
|
|
357
|
+
onError: (error) => console.error(error),
|
|
358
|
+
onComplete: () => console.log('Done'),
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
:::note[AWS Credentials]
|
|
363
|
+
This will use the default AWS credential provider chain to authenticate requests, so the environment in which the above is run must have AWS credentials configured, with access to invoke the runtime.
|
|
364
|
+
:::
|
|
365
|
+
</TabItem>
|
|
366
|
+
|
|
367
|
+
<TabItem label="Cognito" _filter={{ auth: 'Cognito' }}>
|
|
368
|
+
##### JWT / Cognito Authentication
|
|
369
|
+
|
|
370
|
+
Use the `withJwtAuth` factory method to authenticate with the JWT / Cognito access token.
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
const client = AgentClient.withJwtAuth({
|
|
374
|
+
agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
|
|
375
|
+
accessTokenProvider: async () => `<access-token>`,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
client.invoke.subscribe({ message: 'what is 1 plus 1?' }, {
|
|
379
|
+
onData: console.log,
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
The `accessTokenProvider` must return the token used to authenticate the request. You can, for example, obtain a token within this method to ensure that fresh credentials are reused when tRPC restarts a WebSocket connection. The below demonstrates using the AWS SDK to obtain the token from Cognito:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import { CognitoIdentityProvider } from "@aws-sdk/client-cognito-identity-provider";
|
|
387
|
+
|
|
388
|
+
const cognito = new CognitoIdentityProvider();
|
|
389
|
+
|
|
390
|
+
const jwtClient = AgentClient.withJwtAuth({
|
|
391
|
+
agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
|
|
392
|
+
accessTokenProvider: async () => {
|
|
393
|
+
const response = await cognito.adminInitiateAuth({
|
|
394
|
+
UserPoolId: '<user-pool-id>',
|
|
395
|
+
ClientId: '<user-pool-client-id>',
|
|
396
|
+
AuthFlow: 'ADMIN_NO_SRP_AUTH',
|
|
397
|
+
AuthParameters: {
|
|
398
|
+
USERNAME: '<username>',
|
|
399
|
+
PASSWORD: '<password>',
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
return response.AuthenticationResult!.AccessToken!;
|
|
403
|
+
},
|
|
404
|
+
});
|
|
405
|
+
```
|
|
406
|
+
</TabItem>
|
|
407
|
+
</Tabs>
|
|
408
|
+
|
|
409
|
+
#### Browser / React Website
|
|
410
|
+
|
|
411
|
+
For invoking your Agent from a React website, you can make use of the <Link path="/guides/connection/react-ts-agent">`connection` generator</Link>, which automatically sets up a tRPC WebSocket client with the correct authentication (IAM or Cognito).
|
|
412
|
+
|
|
413
|
+
<RunGenerator generator="connection" />
|
|
414
|
+
|
|
415
|
+
Refer to the <Link path="/guides/connection/react-ts-agent">`connection` generator guide</Link> for details about how the connection is set up.
|
|
416
|
+
</OptionFilter>
|
|
417
|
+
|
|
418
|
+
<OptionFilter when={{ protocol: 'A2A' }} description="A2A delegation details">
|
|
419
|
+
### Invoking an A2A Agent as a Tool
|
|
420
|
+
|
|
421
|
+
To delegate work from this agent to a remote A2A agent (either <Link path="/guides/ts-agent">TypeScript</Link> or <Link path="/guides/py-agent">Python</Link>), use the <Link path="/guides/connection/ts-agent-a2a">`connection` generator</Link>. It vends a SigV4-authenticated client for the target agent and AST-transforms this agent's `agent.ts` to register the remote A2A agent as a Strands `tool`.
|
|
422
|
+
|
|
423
|
+
<RunGenerator generator="connection" />
|
|
424
|
+
|
|
425
|
+
Refer to the <Link path="/guides/connection/ts-agent-a2a">`connection` generator guide</Link> for details about how the connection is set up.
|
|
426
|
+
</OptionFilter>
|
|
427
|
+
|
|
428
|
+
<OptionFilter when={{ protocol: 'AG-UI' }} description="AG-UI / React connection details">
|
|
429
|
+
### Invoking an AG-UI Agent
|
|
430
|
+
|
|
431
|
+
To invoke your AG-UI agent from a React website, use the <Link path="/guides/connection/react-agui">`connection` generator</Link>, which wires up a [CopilotKit](https://docs.copilotkit.ai/aws-strands) client configured for your deployed agent with the correct authentication (IAM or Cognito).
|
|
432
|
+
|
|
433
|
+
<RunGenerator generator="connection" />
|
|
434
|
+
|
|
435
|
+
Refer to the <Link path="/guides/connection/react-agui">`connection` generator guide</Link> for details about how the connection is set up.
|
|
436
|
+
</OptionFilter>
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TypeScript Lambda Function
|
|
3
|
+
description: Generate a TypeScript lambda function
|
|
4
|
+
generator: ts#lambda-function
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
8
|
+
import Link from '@components/link.astro';
|
|
9
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
10
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
11
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
12
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
13
|
+
import Snippet from '@components/snippet.astro';
|
|
14
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
15
|
+
|
|
16
|
+
The TypeScript Lambda Function generator provides the ability to add a lambda function to an existing TypeScript project.
|
|
17
|
+
|
|
18
|
+
This generator creates a new TypeScript lambda handler with AWS CDK or Terraform infrastructure setup. The generated handler uses [AWS Lambda Powertools for TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/) for observability, including logging, AWS X-Ray tracing and CloudWatch Metrics, as well as optional type-safety for the event using the [Parser from AWS Lambda Powertools](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parser/)
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Generate a TypeScript lambda function
|
|
23
|
+
|
|
24
|
+
You can generate a lambda function in two ways:
|
|
25
|
+
|
|
26
|
+
<RunGenerator generator="ts#lambda-function" />
|
|
27
|
+
|
|
28
|
+
### Options
|
|
29
|
+
|
|
30
|
+
<GeneratorParameters generator="ts#lambda-function" />
|
|
31
|
+
|
|
32
|
+
## Generator Output
|
|
33
|
+
|
|
34
|
+
The generator will add the following files to your project:
|
|
35
|
+
|
|
36
|
+
<FileTree>
|
|
37
|
+
|
|
38
|
+
- \<project-name>
|
|
39
|
+
- src/
|
|
40
|
+
- \<lambda-function>.ts Function implementation
|
|
41
|
+
|
|
42
|
+
</FileTree>
|
|
43
|
+
|
|
44
|
+
If the `functionPath` option is provided, the generator will add the handler to the specified path within the project source directory:
|
|
45
|
+
|
|
46
|
+
<FileTree>
|
|
47
|
+
|
|
48
|
+
- \<project-name>
|
|
49
|
+
- src/
|
|
50
|
+
- \<custom-path>/
|
|
51
|
+
- \<function-name>.ts Function implementation
|
|
52
|
+
|
|
53
|
+
</FileTree>
|
|
54
|
+
|
|
55
|
+
### Infrastructure
|
|
56
|
+
|
|
57
|
+
<Snippet name="shared-constructs" />
|
|
58
|
+
|
|
59
|
+
The generator creates infrastructure as code for deploying your function based on your selected `iacProvider`:
|
|
60
|
+
|
|
61
|
+
<Infrastructure>
|
|
62
|
+
<Fragment slot="cdk">
|
|
63
|
+
The generator creates a CDK construct which can be used to deploy your function, which resides in the `packages/common/constructs/src/app/lambda-functions` directory.
|
|
64
|
+
</Fragment>
|
|
65
|
+
<Fragment slot="terraform">
|
|
66
|
+
The generator creates a Terraform module which can be used to deploy your function, which resides in the `packages/common/terraform/src/app/lambda-functions/<function-name>` directory.
|
|
67
|
+
</Fragment>
|
|
68
|
+
</Infrastructure>
|
|
69
|
+
|
|
70
|
+
#### Architecture
|
|
71
|
+
|
|
72
|
+
<Snippet name="lambda-function/architecture" />
|
|
73
|
+
|
|
74
|
+
## Implementing your Function
|
|
75
|
+
|
|
76
|
+
The main function implementation is in `<function-name>.ts`. Here's an example:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { parser } from '@aws-lambda-powertools/parser/middleware';
|
|
80
|
+
import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas';
|
|
81
|
+
import middy from '@middy/core';
|
|
82
|
+
import { Tracer } from '@aws-lambda-powertools/tracer';
|
|
83
|
+
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
|
|
84
|
+
import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware';
|
|
85
|
+
import { Logger } from '@aws-lambda-powertools/logger';
|
|
86
|
+
import { Metrics } from '@aws-lambda-powertools/metrics';
|
|
87
|
+
import { logMetrics } from '@aws-lambda-powertools/metrics/middleware';
|
|
88
|
+
import { z } from 'zod';
|
|
89
|
+
|
|
90
|
+
process.env.POWERTOOLS_METRICS_NAMESPACE = 'MyFunction';
|
|
91
|
+
process.env.POWERTOOLS_SERVICE_NAME = 'MyFunction';
|
|
92
|
+
|
|
93
|
+
const tracer = new Tracer();
|
|
94
|
+
const logger = new Logger();
|
|
95
|
+
const metrics = new Metrics();
|
|
96
|
+
|
|
97
|
+
export const myFunction = async (
|
|
98
|
+
event: z.infer<typeof EventBridgeSchema>,
|
|
99
|
+
): Promise<void> => {
|
|
100
|
+
logger.info('Received event', event);
|
|
101
|
+
|
|
102
|
+
// TODO: implement
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const handler = middy()
|
|
106
|
+
.use(captureLambdaHandler(tracer))
|
|
107
|
+
.use(injectLambdaContext(logger))
|
|
108
|
+
.use(logMetrics(metrics))
|
|
109
|
+
.use(parser({ schema: EventBridgeSchema }))
|
|
110
|
+
.handler(myFunction);
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The generator sets up several features automatically:
|
|
115
|
+
|
|
116
|
+
1. **Middy middleware stack** for enhanced Lambda functionality
|
|
117
|
+
2. **AWS Lambda Powertools integration** for observability
|
|
118
|
+
3. **Metrics collection** with CloudWatch
|
|
119
|
+
4. **Type-safety** using parser middleware
|
|
120
|
+
5. **Bundling with Rolldown** for optimized deployment packages
|
|
121
|
+
|
|
122
|
+
### Observability with AWS Lambda Powertools
|
|
123
|
+
|
|
124
|
+
#### Logging
|
|
125
|
+
|
|
126
|
+
The generator configures structured logging using AWS Lambda Powertools with automatic context injection via Middy middleware.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
export const handler = middy()
|
|
130
|
+
.use(injectLambdaContext(logger))
|
|
131
|
+
.handler(myFunction);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Tracing
|
|
135
|
+
|
|
136
|
+
AWS X-Ray tracing is configured automatically via the `captureLambdaHandler` middleware. You can add custom subsegments to your traces:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const tracer = new Tracer();
|
|
140
|
+
|
|
141
|
+
export const myFunction = async (
|
|
142
|
+
event: z.infer<typeof EventBridgeSchema>,
|
|
143
|
+
): Promise<void> => {
|
|
144
|
+
// Creates a new subsegment
|
|
145
|
+
const subsegment = tracer.getSegment()?.addNewSubsegment('custom-operation');
|
|
146
|
+
try {
|
|
147
|
+
// Your logic here
|
|
148
|
+
} catch (error) {
|
|
149
|
+
subsegment?.addError(error as Error);
|
|
150
|
+
throw error;
|
|
151
|
+
} finally {
|
|
152
|
+
subsegment?.close();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const handler = middy()
|
|
157
|
+
.use(captureLambdaHandler(tracer))
|
|
158
|
+
.handler(myFunction);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Metrics
|
|
162
|
+
|
|
163
|
+
CloudWatch metrics are collected automatically for each request via the `logMetrics` middleware. You can add custom metrics:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const metrics = new Metrics();
|
|
167
|
+
|
|
168
|
+
export const myFunction = async (
|
|
169
|
+
event: z.infer<typeof EventBridgeSchema>,
|
|
170
|
+
): Promise<void> => {
|
|
171
|
+
metrics.addMetric("CustomMetric", MetricUnit.Count, 1);
|
|
172
|
+
metrics.addMetric("ProcessingTime", MetricUnit.Milliseconds, processingTime);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const handler = middy()
|
|
176
|
+
.use(logMetrics(metrics))
|
|
177
|
+
.handler(myFunction);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Type Safety
|
|
181
|
+
|
|
182
|
+
<OptionFilter not when={{ eventSource: 'Any' }} description="eventSource provides a typed Zod schema for the incoming event">
|
|
183
|
+
If you chose an `eventSource` when generating your lambda function, your function is instrumented with the [`parser` middleware from AWS Lambda Powertools](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parser/). For example:
|
|
184
|
+
|
|
185
|
+
```typescript {4}
|
|
186
|
+
export const myFunction = async (
|
|
187
|
+
event: z.infer<typeof EventBridgeSchema>,
|
|
188
|
+
): Promise<void> => {
|
|
189
|
+
event.detail // <- type-safe with IDE autocompletion
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export const handler = middy()
|
|
193
|
+
.use(parser({ schema: EventBridgeSchema }))
|
|
194
|
+
.handler(myFunction);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This provides compile-time type safety and runtime validation for your Lambda events.
|
|
198
|
+
|
|
199
|
+
:::caution[Error Handling]
|
|
200
|
+
If you do not want your handler to throw an error when the event does not conform to the schema, you can use the [`safeParse` option](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parser/#safe-parsing).
|
|
201
|
+
:::
|
|
202
|
+
|
|
203
|
+
:::tip[Custom Event Data]
|
|
204
|
+
If you have custom data nested within an event, for example a DynamoDB stream or EventBridge event, you may benefit from using [Envelopes](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parser/#envelopes) to provide type-safety for that custom data.
|
|
205
|
+
:::
|
|
206
|
+
</OptionFilter>
|
|
207
|
+
|
|
208
|
+
<OptionFilter when={{ eventSource: 'Any' }} description="eventSource=Any — no parser middleware, event is typed as `any`">
|
|
209
|
+
If you selected `Any` for your `eventSource`, the `parser` middleware is not wired in and the `event` parameter is typed as `any`. Regenerate the function with a specific `eventSource` if you want compile-time type safety and runtime validation.
|
|
210
|
+
</OptionFilter>
|
|
211
|
+
|
|
212
|
+
## Bundling
|
|
213
|
+
|
|
214
|
+
<Snippet name="ts-bundle" />
|
|
215
|
+
|
|
216
|
+
## Deploying your Function
|
|
217
|
+
|
|
218
|
+
<Snippet name="lambda-function/deploying-your-function" parentHeading="Deploying your Function" />
|