@ag-ui/aws-strands 0.1.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/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/agent-B2EYZvns.d.ts +310 -0
- package/dist/agent-B2EYZvns.d.ts.map +1 -0
- package/dist/agent-Dp45JIaO.d.mts +310 -0
- package/dist/agent-Dp45JIaO.d.mts.map +1 -0
- package/dist/index.d.mts +51 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.d.mts +136 -0
- package/dist/server.d.mts.map +1 -0
- package/dist/server.d.ts +136 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +2 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# AWS Strands Integration for AG-UI (TypeScript)
|
|
2
|
+
|
|
3
|
+
This package exposes a lightweight wrapper that lets any `@strands-agents/sdk` `Agent` speak the AG-UI protocol. It mirrors the developer experience of the other integrations: give us a Strands agent instance, plug it into `StrandsAgent`, and wire it to Express via `createStrandsApp` (or `addStrandsExpressEndpoint`).
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js 18+
|
|
8
|
+
- `pnpm` (recommended) or `npm`
|
|
9
|
+
- A Strands-compatible model key (e.g., AWS credentials for Bedrock, `OPENAI_API_KEY` for OpenAI)
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
The `examples/` package ships a "dojo" server that mounts every demo on a
|
|
14
|
+
single port, plus seven standalone servers — one per feature — that you can
|
|
15
|
+
run independently.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# from the repo root
|
|
19
|
+
pnpm install
|
|
20
|
+
pnpm --filter @ag-ui/aws-strands build
|
|
21
|
+
|
|
22
|
+
cd integrations/aws-strands/typescript/examples
|
|
23
|
+
pnpm dojo # all examples at http://localhost:8022
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or run any single example on its own port (default `8000`):
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm agentic-chat
|
|
30
|
+
pnpm agentic-chat-reasoning
|
|
31
|
+
pnpm agentic-chat-multimodal
|
|
32
|
+
pnpm backend-tool-rendering
|
|
33
|
+
pnpm shared-state
|
|
34
|
+
pnpm agentic-generative-ui
|
|
35
|
+
pnpm human-in-the-loop
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The dojo exposes:
|
|
39
|
+
|
|
40
|
+
| Route | Description |
|
|
41
|
+
| -------------------------- | ------------------------------------------------------------------------ |
|
|
42
|
+
| `/agentic-chat` | Baseline chat; frontend tools auto-registered from `RunAgentInput.tools` |
|
|
43
|
+
| `/agentic-chat-reasoning` | Reasoning / thinking event streaming |
|
|
44
|
+
| `/agentic-chat-multimodal` | Multimodal image / document analysis |
|
|
45
|
+
| `/backend-tool-rendering` | Backend-executed tools (`get_weather`, `render_chart`) |
|
|
46
|
+
| `/shared-state` | Shared recipe state (`stateFromArgs`) |
|
|
47
|
+
| `/agentic-generative-ui` | Async-generator tool streams `STATE_SNAPSHOT`s + `PredictState` |
|
|
48
|
+
| `/human-in-the-loop` | Frontend proxy tool with halt-after-call |
|
|
49
|
+
|
|
50
|
+
Each standalone file under `examples/server/api/*.ts` follows the same pattern: build a Strands `Agent`, wrap it in a `StrandsAgent`, hand it to `createStrandsApp`, listen.
|
|
51
|
+
|
|
52
|
+
## Architecture Overview
|
|
53
|
+
|
|
54
|
+
The integration has three main layers:
|
|
55
|
+
|
|
56
|
+
- **StrandsAgent** – wraps `Agent.stream()` from `@strands-agents/sdk`. It translates Strands streaming events into AG-UI events (text chunks, tool calls, PredictState, snapshots, reasoning/thinking, multi-agent steps, etc.).
|
|
57
|
+
- **Configuration** – `StrandsAgentConfig` + `ToolBehavior` + `PredictStateMapping` let you describe tool-specific quirks declaratively (skip message snapshots, emit state, stream args, etc.).
|
|
58
|
+
- **Transport helpers** – `createStrandsApp` and `addStrandsExpressEndpoint` expose the agent via SSE. They are thin shells over the shared `@ag-ui/encoder` `EventEncoder`. Imported from `@ag-ui/aws-strands/server` — kept off the main entry so client-side bundlers (Next.js, Vite) don't pull Express into the browser graph.
|
|
59
|
+
|
|
60
|
+
See [../ARCHITECTURE.md](../ARCHITECTURE.md) for diagrams and a deeper dive.
|
|
61
|
+
|
|
62
|
+
## Key Files
|
|
63
|
+
|
|
64
|
+
| File | Description |
|
|
65
|
+
| -------------------------- | ------------------------------------------------------------------------------- |
|
|
66
|
+
| `src/agent.ts` | Core wrapper translating Strands streams into AG-UI events |
|
|
67
|
+
| `src/config.ts` | Config primitives (`StrandsAgentConfig`, `ToolBehavior`, `PredictStateMapping`) |
|
|
68
|
+
| `src/server.ts` | `createStrandsApp` + Express transport (subpath: `@ag-ui/aws-strands/server`) |
|
|
69
|
+
| `src/endpoint.ts` | Express endpoint helpers (used by `server.ts`) |
|
|
70
|
+
| `src/utils.ts` | Multimodal content conversion |
|
|
71
|
+
| `src/client-proxy-tool.ts` | Dynamic frontend tool registration/deregistration |
|
|
72
|
+
| `examples/server/api/*.ts` | Ready-to-run demo apps |
|
|
73
|
+
|
|
74
|
+
## Amazon Bedrock AgentCore Considerations
|
|
75
|
+
|
|
76
|
+
If you are planning to deploy your agent into Amazon Bedrock AgentCore (AC), please note that AC expects the following:
|
|
77
|
+
|
|
78
|
+
- The server is running on port 8080.
|
|
79
|
+
- The path `/invocations - POST` is implemented and can be used for interacting with the agent.
|
|
80
|
+
- The path `/ping - GET` is implemented and can be used for verifying that the agent is operational and ready to handle requests.
|
|
81
|
+
|
|
82
|
+
To implement the paths mentioned above, you can use the helper function `createStrandsApp` and pass the agent interaction path and the ping path as shown below:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const app = await createStrandsApp(aguiAgent, {
|
|
86
|
+
path: "/invocations",
|
|
87
|
+
pingPath: "/ping",
|
|
88
|
+
});
|
|
89
|
+
app.listen(8080);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can also use the helper functions `addStrandsExpressEndpoint` and `addPing` for adding the mentioned paths to an Express app that you are creating separately:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import express from "express";
|
|
96
|
+
import cors from "cors";
|
|
97
|
+
import { addStrandsExpressEndpoint, addPing } from "@ag-ui/aws-strands/server";
|
|
98
|
+
|
|
99
|
+
const app = express();
|
|
100
|
+
app.use(cors());
|
|
101
|
+
app.use(express.json({ limit: "50mb" }));
|
|
102
|
+
addStrandsExpressEndpoint(app, aguiAgent, { path: "/invocations" });
|
|
103
|
+
addPing(app, "/ping");
|
|
104
|
+
app.listen(8080);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Requests to the AC endpoint must be authenticated. You can configure your agent runtime to accept JWT bearer tokens (via Amazon Cognito) or use SigV4. See [Set up authentication](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html) in the AgentCore documentation.
|
|
108
|
+
|
|
109
|
+
For details on how AgentCore handles AG-UI requests, event streaming, and error formatting, see the [AG-UI protocol contract](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui-protocol-contract.html).
|
|
110
|
+
|
|
111
|
+
To deploy, use the [AgentCore Starter Toolkit](https://github.com/awslabs/bedrock-agentcore-starter-toolkit):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install bedrock-agentcore-starter-toolkit
|
|
115
|
+
agentcore configure -e my_agui_server.ts --protocol AGUI
|
|
116
|
+
agentcore deploy
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For the complete deployment walkthrough, see [Deploy AG-UI servers in AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html).
|
|
120
|
+
|
|
121
|
+
## Supported AG-UI Events
|
|
122
|
+
|
|
123
|
+
The integration supports the following AG-UI event families:
|
|
124
|
+
|
|
125
|
+
- **Lifecycle**: `RUN_STARTED`, `RUN_FINISHED`, `RUN_ERROR`
|
|
126
|
+
- **Text streaming**: `TEXT_MESSAGE_START`, `TEXT_MESSAGE_CONTENT`, `TEXT_MESSAGE_END` (optionally collapsed into `TEXT_MESSAGE_CHUNK` via `StrandsAgentConfig.emitChunkEvents`)
|
|
127
|
+
- **Reasoning**: `REASONING_*` events for models with extended thinking (`REASONING_MESSAGE_CHUNK` when `emitChunkEvents` is on)
|
|
128
|
+
- **Tool calls**: `TOOL_CALL_START`, `TOOL_CALL_ARGS`, `TOOL_CALL_END`, `TOOL_CALL_RESULT` (or `TOOL_CALL_CHUNK` with `emitChunkEvents`)
|
|
129
|
+
- **State management**: `STATE_SNAPSHOT`
|
|
130
|
+
- **Multi-agent**: `STEP_STARTED`, `STEP_FINISHED`, and `MultiAgentHandoff` custom events
|
|
131
|
+
- **Generative UI**: `PredictState` custom events for optimistic UI updates
|
|
132
|
+
- **Multimodal**: Image, document, and video content in user messages (converted to Strands ContentBlock format)
|
|
133
|
+
|
|
134
|
+
The adapter advertises its full event / feature matrix at GET
|
|
135
|
+
`/capabilities` (enabled by default; override via `createStrandsApp({ capabilitiesPath, capabilities })` or mount manually with `addCapabilities(app, path, overrides)`).
|
|
136
|
+
|
|
137
|
+
## Passing tools to the Agent
|
|
138
|
+
|
|
139
|
+
The adapter clones the template `Agent`'s `tools` array onto every per-thread
|
|
140
|
+
clone. That means whatever the Strands SDK has resolved into `agent.tools` at
|
|
141
|
+
construction time is what the model sees — including for `McpClient`
|
|
142
|
+
instances. If you pass an **unconnected** `McpClient` directly, its tools
|
|
143
|
+
won't be in the resolved list and the model can't call them.
|
|
144
|
+
|
|
145
|
+
Connect MCP clients first and spread the resolved tools into `tools`:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { Agent } from "@strands-agents/sdk";
|
|
149
|
+
import { McpClient } from "@strands-agents/sdk/mcp";
|
|
150
|
+
|
|
151
|
+
const spellbook = new McpClient({
|
|
152
|
+
/* transport config */
|
|
153
|
+
});
|
|
154
|
+
await spellbook.connect();
|
|
155
|
+
const mcpTools = await spellbook.listTools();
|
|
156
|
+
|
|
157
|
+
const agent = new Agent({
|
|
158
|
+
model: "anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
159
|
+
tools: [...mcpTools, myLocalTool],
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const aguiAgent = new StrandsAgent({ agent });
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The adapter logs a warning at construction time if it spots an entry in
|
|
166
|
+
`tools` that looks like an unconnected client (has a `.connect()` method but
|
|
167
|
+
no `.name`).
|
|
168
|
+
|
|
169
|
+
## Human-in-the-loop interrupts
|
|
170
|
+
|
|
171
|
+
Two complementary patterns are supported:
|
|
172
|
+
|
|
173
|
+
- **Frontend tools.** The `/human-in-the-loop` example declares
|
|
174
|
+
`generate_task_steps` on the frontend via `useHumanInTheLoop` — the adapter
|
|
175
|
+
auto-registers it as a proxy tool, halts the run after the proxy resolves,
|
|
176
|
+
and hands control back to the UI for approval.
|
|
177
|
+
- **Native Strands interrupts (SDK 1.1.0+).** Backend hooks and tools can call
|
|
178
|
+
`event.interrupt(...)` / `context.interrupt(...)` to raise a
|
|
179
|
+
`stopReason: 'interrupt'`. The adapter forwards the outstanding interrupts
|
|
180
|
+
on `RUN_FINISHED`:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"type": "RUN_FINISHED",
|
|
185
|
+
"outcome": {
|
|
186
|
+
"type": "interrupt",
|
|
187
|
+
"interrupts": [
|
|
188
|
+
{ "id": "...", "reason": "...", "metadata": { "strandsName": "..." } }
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The next `RunAgentInput` carries `resume[]` entries keyed by those `id`s.
|
|
195
|
+
The adapter converts each entry into a Strands `InterruptResponseContent`
|
|
196
|
+
(forwarding `payload` for `resolved` and `{ status: "cancelled" }` for
|
|
197
|
+
`cancelled`) and hands them straight to `agent.stream(...)`. Unknown
|
|
198
|
+
`interruptId`s still short-circuit with
|
|
199
|
+
`RUN_ERROR { code: "UNKNOWN_INTERRUPT" }` per
|
|
200
|
+
[interrupts.mdx rule 4](https://docs.ag-ui.com/concepts/interrupts).
|
|
201
|
+
|
|
202
|
+
## Reasoning / extended thinking
|
|
203
|
+
|
|
204
|
+
The `/agentic-chat-reasoning` demo only emits `REASONING_*` events when the
|
|
205
|
+
underlying Strands model is configured with thinking / reasoning params. The
|
|
206
|
+
default `BedrockModel(...)` without `additional_request_fields` returns plain
|
|
207
|
+
text; for Claude extended thinking, configure the model like so:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
import { BedrockModel } from "@strands-agents/sdk/models/bedrock";
|
|
211
|
+
|
|
212
|
+
const model = new BedrockModel({
|
|
213
|
+
modelId: "global.anthropic.claude-sonnet-4-6",
|
|
214
|
+
additionalRequestFields: {
|
|
215
|
+
thinking: { type: "enabled", budget_tokens: 5000 },
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Install
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
pnpm add @ag-ui/aws-strands @strands-agents/sdk @ag-ui/core @ag-ui/encoder
|
|
224
|
+
# Server-side helpers (createStrandsApp / addStrandsExpressEndpoint) require express + cors:
|
|
225
|
+
pnpm add express cors
|
|
226
|
+
pnpm add -D @types/express @types/cors
|
|
227
|
+
# @modelcontextprotocol/sdk is loaded unconditionally by @strands-agents/sdk
|
|
228
|
+
# — required at runtime even for agents that don't use MCP:
|
|
229
|
+
pnpm add @modelcontextprotocol/sdk
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Server: Expose a Strands Agent via AG-UI
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { Agent } from "@strands-agents/sdk";
|
|
236
|
+
import { StrandsAgent } from "@ag-ui/aws-strands";
|
|
237
|
+
import { createStrandsApp } from "@ag-ui/aws-strands/server";
|
|
238
|
+
|
|
239
|
+
// `model` accepts either a Bedrock model ID string or a constructed
|
|
240
|
+
// Model instance (e.g. BedrockModel / AnthropicModel / OpenAIResponsesModel).
|
|
241
|
+
// Omitting it uses Strands' current Bedrock default.
|
|
242
|
+
const strandsAgent = new Agent({
|
|
243
|
+
systemPrompt: "You are a helpful assistant.",
|
|
244
|
+
tools: [],
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const aguiAgent = new StrandsAgent({
|
|
248
|
+
agent: strandsAgent,
|
|
249
|
+
name: "MyAgent",
|
|
250
|
+
description: "A Strands agent exposed via AG-UI",
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const app = await createStrandsApp(aguiAgent, { path: "/invocations" });
|
|
254
|
+
app.listen(8000);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Configuration
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
import {
|
|
261
|
+
StrandsAgent,
|
|
262
|
+
type StrandsAgentConfig,
|
|
263
|
+
type ToolBehavior,
|
|
264
|
+
} from "@ag-ui/aws-strands";
|
|
265
|
+
|
|
266
|
+
const config: StrandsAgentConfig = {
|
|
267
|
+
toolBehaviors: {
|
|
268
|
+
set_recipe: {
|
|
269
|
+
stateFromArgs: async (ctx) => ({ recipe: ctx.toolInput }),
|
|
270
|
+
predictState: [
|
|
271
|
+
{ stateKey: "recipe", tool: "set_recipe", toolArgument: "data" },
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
render_chart: {
|
|
275
|
+
stopStreamingAfterResult: true,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
sessionManagerProvider: async (input) => {
|
|
279
|
+
// Optional: vend a SessionManager per-thread from your own state store.
|
|
280
|
+
return undefined;
|
|
281
|
+
},
|
|
282
|
+
stateContextBuilder: (input, prompt) => {
|
|
283
|
+
// Optional: decorate the outgoing prompt with any server-side state.
|
|
284
|
+
return prompt;
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const agent = new StrandsAgent({ agent: strandsAgent, name: "x", config });
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Low-Level Transport
|
|
292
|
+
|
|
293
|
+
If you have an existing Express app, mount the endpoint directly instead of
|
|
294
|
+
using `createStrandsApp`:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import express from "express";
|
|
298
|
+
import cors from "cors";
|
|
299
|
+
import { addStrandsExpressEndpoint, addPing } from "@ag-ui/aws-strands/server";
|
|
300
|
+
|
|
301
|
+
const app = express();
|
|
302
|
+
app.use(cors());
|
|
303
|
+
app.use(express.json({ limit: "50mb" }));
|
|
304
|
+
addStrandsExpressEndpoint(app, aguiAgent, { path: "/invocations" });
|
|
305
|
+
addPing(app, "/ping");
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Development
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
pnpm install
|
|
312
|
+
pnpm build
|
|
313
|
+
pnpm test
|
|
314
|
+
```
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { Agent, AgentConfig, Plugin, SessionManager } from "@strands-agents/sdk";
|
|
2
|
+
import { BaseEvent, Message, RunAgentInput } from "@ag-ui/core";
|
|
3
|
+
|
|
4
|
+
//#region src/logger.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Injectable logger for the AWS Strands adapter.
|
|
7
|
+
*
|
|
8
|
+
* The Python sibling uses `logging.getLogger(__name__)` and emits warnings /
|
|
9
|
+
* errors to stderr at `WARNING` and up, with `DEBUG` opt-in. This module
|
|
10
|
+
* mirrors that behaviour: by default the adapter is silent below `warn`,
|
|
11
|
+
* surfaces warnings via `console.warn`, and lets callers redirect output by
|
|
12
|
+
* passing a `Logger` in `StrandsAgentConfig.logger`.
|
|
13
|
+
*
|
|
14
|
+
* Signature `(message: string, ...args: unknown[])` intentionally matches the
|
|
15
|
+
* `console` method shape so existing `vi.spyOn(console, "warn")` test
|
|
16
|
+
* scaffolding keeps working with the default logger in place, and so wiring
|
|
17
|
+
* in pino / winston / bunyan is a one-liner.
|
|
18
|
+
*/
|
|
19
|
+
interface Logger {
|
|
20
|
+
debug(message: string, ...args: unknown[]): void;
|
|
21
|
+
warn(message: string, ...args: unknown[]): void;
|
|
22
|
+
error(message: string, ...args: unknown[]): void;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/config.d.ts
|
|
26
|
+
type StatePayload = Record<string, unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* Free-form key/value map carried on `RunAgentInput.context[]` and
|
|
29
|
+
* `RunAgentInput.forwardedProps`. Exposed on hook contexts so behaviors can
|
|
30
|
+
* react to e.g. per-request auth tokens or locale without re-parsing
|
|
31
|
+
* `inputData`.
|
|
32
|
+
*
|
|
33
|
+
* TypeScript-only: the Python adapter passes `input_data` directly to hooks
|
|
34
|
+
* and callers pull these fields off themselves.
|
|
35
|
+
*/
|
|
36
|
+
interface ToolCallContextExtras {
|
|
37
|
+
/**
|
|
38
|
+
* `RunAgentInput.context[]` flattened by `description` → `value`.
|
|
39
|
+
* Duplicates: later entries overwrite earlier ones. Keys `__proto__`,
|
|
40
|
+
* `constructor`, and `prototype` are dropped to prevent prototype-pollution
|
|
41
|
+
* surprises in downstream `Object.assign(target, ctx.context)` usage.
|
|
42
|
+
*/
|
|
43
|
+
context: Readonly<Record<string, string>>;
|
|
44
|
+
/**
|
|
45
|
+
* `RunAgentInput.forwardedProps` as an opaque record. Shape is defined by
|
|
46
|
+
* the frontend; the adapter does not introspect it.
|
|
47
|
+
*/
|
|
48
|
+
forwardedProps: Readonly<Record<string, unknown>>;
|
|
49
|
+
}
|
|
50
|
+
/** Context passed to tool call hooks. */
|
|
51
|
+
interface ToolCallContext extends ToolCallContextExtras {
|
|
52
|
+
inputData: RunAgentInput;
|
|
53
|
+
toolName: string;
|
|
54
|
+
toolUseId: string;
|
|
55
|
+
toolInput: unknown;
|
|
56
|
+
argsStr: string;
|
|
57
|
+
}
|
|
58
|
+
/** Context passed to tool result hooks. */
|
|
59
|
+
interface ToolResultContext extends ToolCallContext {
|
|
60
|
+
resultData: unknown;
|
|
61
|
+
messageId: string;
|
|
62
|
+
}
|
|
63
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
64
|
+
type ArgsStreamer = (ctx: ToolCallContext) => AsyncIterable<string>;
|
|
65
|
+
type StateFromArgs = (ctx: ToolCallContext) => MaybePromise<StatePayload | null | undefined>;
|
|
66
|
+
type StateFromResult = (ctx: ToolResultContext) => MaybePromise<StatePayload | null | undefined>;
|
|
67
|
+
type CustomResultHandler = (ctx: ToolResultContext) => AsyncIterable<BaseEvent | null | undefined>;
|
|
68
|
+
type StateContextBuilder = (inputData: RunAgentInput, prompt: string, /** Convenience view over `inputData.context[]` + `inputData.forwardedProps`. */
|
|
69
|
+
|
|
70
|
+
extras?: ToolCallContextExtras) => string;
|
|
71
|
+
type SessionManagerProvider = (inputData: RunAgentInput) => MaybePromise<SessionManager | null | undefined>;
|
|
72
|
+
/** Declarative mapping telling the UI how to predict state from tool args. */
|
|
73
|
+
interface PredictStateMapping {
|
|
74
|
+
stateKey: string;
|
|
75
|
+
tool: string;
|
|
76
|
+
toolArgument: string;
|
|
77
|
+
}
|
|
78
|
+
/** Declarative configuration for tool-specific handling. */
|
|
79
|
+
interface ToolBehavior {
|
|
80
|
+
/**
|
|
81
|
+
* Suppress the `MessagesSnapshotEvent` that would normally follow this
|
|
82
|
+
* tool's `TOOL_CALL_END` / `TOOL_CALL_RESULT`. Useful when
|
|
83
|
+
* `customResultHandler` emits its own snapshot.
|
|
84
|
+
*/
|
|
85
|
+
skipMessagesSnapshot?: boolean;
|
|
86
|
+
/** Keep the stream alive after emitting a frontend tool call. */
|
|
87
|
+
continueAfterFrontendCall?: boolean;
|
|
88
|
+
/** Close text streaming and halt the agent after a tool result arrives. */
|
|
89
|
+
stopStreamingAfterResult?: boolean;
|
|
90
|
+
/** `PredictStateMapping[]` that inform the UI how to project tool args into state. */
|
|
91
|
+
predictState?: PredictStateMapping | Iterable<PredictStateMapping>;
|
|
92
|
+
/** Async generator controlling how tool arguments are streamed to the frontend. */
|
|
93
|
+
argsStreamer?: ArgsStreamer;
|
|
94
|
+
/** Derive a `StateSnapshotEvent` from the tool call arguments. */
|
|
95
|
+
stateFromArgs?: StateFromArgs;
|
|
96
|
+
/** Derive a `StateSnapshotEvent` from the tool result. */
|
|
97
|
+
stateFromResult?: StateFromResult;
|
|
98
|
+
/** Async iterator that can emit arbitrary AG-UI events in response to a result. */
|
|
99
|
+
customResultHandler?: CustomResultHandler;
|
|
100
|
+
}
|
|
101
|
+
/** Top-level configuration for the Strands agent adapter. */
|
|
102
|
+
interface StrandsAgentConfig {
|
|
103
|
+
/** Per-tool overrides keyed by the Strands tool name. */
|
|
104
|
+
toolBehaviors?: Record<string, ToolBehavior>;
|
|
105
|
+
/** Callable that enriches the outgoing prompt with the current shared state. */
|
|
106
|
+
stateContextBuilder?: StateContextBuilder;
|
|
107
|
+
/**
|
|
108
|
+
* Optional factory for creating per-thread `SessionManager` instances.
|
|
109
|
+
*
|
|
110
|
+
* Called exactly once per `threadId` the first time that thread is seen.
|
|
111
|
+
* Subsequent requests on the same thread reuse the cached agent (and its
|
|
112
|
+
* SessionManager). If the provider depends on per-request data (e.g. auth
|
|
113
|
+
* tokens in `forwardedProps`), only the first request's data is used.
|
|
114
|
+
*
|
|
115
|
+
* If the provider throws, the run yields `RUN_ERROR` and returns early;
|
|
116
|
+
* the thread is NOT cached so the provider will be retried on the next
|
|
117
|
+
* request.
|
|
118
|
+
*
|
|
119
|
+
* If the provider returns `null` or `undefined`, a warning is logged and
|
|
120
|
+
* the agent runs without session persistence; the thread IS cached.
|
|
121
|
+
*/
|
|
122
|
+
sessionManagerProvider?: SessionManagerProvider;
|
|
123
|
+
/**
|
|
124
|
+
* Emit `MessagesSnapshotEvent` at lifecycle boundaries (after the initial
|
|
125
|
+
* `STATE_SNAPSHOT`, after each `TOOL_CALL_END` / `TOOL_CALL_RESULT`, and
|
|
126
|
+
* after each terminal `TEXT_MESSAGE_END`).
|
|
127
|
+
*
|
|
128
|
+
* Required for CopilotKit v2 frontends; set to `false` for raw AG-UI
|
|
129
|
+
* consumers that reconstruct messages themselves. Default: `true`.
|
|
130
|
+
*/
|
|
131
|
+
emitMessagesSnapshot?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* When `true` (and the cached Strands agent has no `sessionManager`),
|
|
134
|
+
* reconcile the per-thread `Agent.messages` list with
|
|
135
|
+
* `RunAgentInput.messages` before invoking `stream()`.
|
|
136
|
+
*
|
|
137
|
+
* Prevents the LLM from re-firing frontend tools every turn because
|
|
138
|
+
* Strands' internal history was missing the tool result the frontend
|
|
139
|
+
* produced. Disable only if you manage Strands history yourself.
|
|
140
|
+
* Default: `true`.
|
|
141
|
+
*/
|
|
142
|
+
replayHistoryIntoStrands?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Emit the self-expanding AG-UI chunk events (`TEXT_MESSAGE_CHUNK`,
|
|
145
|
+
* `TOOL_CALL_CHUNK`, `REASONING_MESSAGE_CHUNK`) instead of the explicit
|
|
146
|
+
* `*_START` / `*_CONTENT` / `*_END` triples. Halves the event count on
|
|
147
|
+
* high-frequency deltas; useful for bandwidth-constrained transports.
|
|
148
|
+
* TypeScript-only. Default: `false`.
|
|
149
|
+
*/
|
|
150
|
+
emitChunkEvents?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Optional injectable logger. Mirrors the Python adapter's
|
|
153
|
+
* `logging.getLogger("ag_ui_strands")`: the default surfaces `warn` / `error`
|
|
154
|
+
* via the `console` and drops `debug`, matching Python's stdlib default
|
|
155
|
+
* (WARNING-and-up to stderr). Pass `{ debug: console.debug, warn:
|
|
156
|
+
* console.warn, error: console.error }` to enable verbose traces, `{ debug()
|
|
157
|
+
* {}, warn() {}, error() {} }` to silence everything, or wire in pino /
|
|
158
|
+
* winston / bunyan directly — the `Logger` shape matches the `console`
|
|
159
|
+
* methods.
|
|
160
|
+
*
|
|
161
|
+
* Debug messages match the Python adapter's message strings field-for-field
|
|
162
|
+
* (modulo camelCase / snake_case) so cross-SDK log diffs are straightforward.
|
|
163
|
+
*/
|
|
164
|
+
logger?: Logger;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Flatten `RunAgentInput.context[]` into a plain key/value record and ensure
|
|
168
|
+
* `forwardedProps` is a record. Exported so hook implementations can call it
|
|
169
|
+
* when they have an `inputData` but not a fully-populated hook context.
|
|
170
|
+
*/
|
|
171
|
+
declare function buildContextExtras(inputData: RunAgentInput): ToolCallContextExtras;
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/agent.d.ts
|
|
174
|
+
/**
|
|
175
|
+
* Structural interface for a Strands multi-agent orchestrator (Graph/Swarm).
|
|
176
|
+
* TypeScript-only: the Python SDK currently has no orchestrator equivalent.
|
|
177
|
+
*/
|
|
178
|
+
interface StrandsOrchestrator {
|
|
179
|
+
readonly id?: string;
|
|
180
|
+
stream(input: string): AsyncGenerator<unknown, unknown, unknown>;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Convert ``RunAgentInput.messages`` to AG-UI message objects.
|
|
184
|
+
*
|
|
185
|
+
* Used to seed the running ``MessagesSnapshotEvent`` payload so each snapshot
|
|
186
|
+
* carries the full thread history.
|
|
187
|
+
*/
|
|
188
|
+
declare function buildSnapshotMessages(input_messages: Message[]): Message[];
|
|
189
|
+
/** Options accepted by `StrandsAgent`. */
|
|
190
|
+
interface StrandsAgentOptions {
|
|
191
|
+
/**
|
|
192
|
+
* Either an `Agent` (the template — adapter clones it per thread and syncs
|
|
193
|
+
* proxy tools) OR a multi-agent orchestrator (`Graph`, `Swarm`).
|
|
194
|
+
* Orchestrators are stateless per invocation so the same instance serves
|
|
195
|
+
* every thread.
|
|
196
|
+
*/
|
|
197
|
+
agent: Agent | StrandsOrchestrator;
|
|
198
|
+
name: string;
|
|
199
|
+
description?: string;
|
|
200
|
+
config?: StrandsAgentConfig;
|
|
201
|
+
/**
|
|
202
|
+
* Plugins forwarded to every per-thread Strands agent created by this
|
|
203
|
+
* adapter (observability, loop caps, policy checks, ...). Mirrors the
|
|
204
|
+
* Python adapter's `hooks=` kwarg. Ignored when `agent` is a multi-agent
|
|
205
|
+
* orchestrator.
|
|
206
|
+
*/
|
|
207
|
+
plugins?: Plugin[];
|
|
208
|
+
}
|
|
209
|
+
/** AWS Strands Agent wrapper for AG-UI integration. */
|
|
210
|
+
declare class StrandsAgent {
|
|
211
|
+
readonly name: string;
|
|
212
|
+
readonly description: string;
|
|
213
|
+
readonly config: StrandsAgentConfig;
|
|
214
|
+
private readonly _templateFields;
|
|
215
|
+
/**
|
|
216
|
+
* Hook providers forwarded to each per-thread StrandsAgentCore.
|
|
217
|
+
*
|
|
218
|
+
* Taken directly from the caller rather than read off the template because
|
|
219
|
+
* Strands' `Agent.hooks` is a `HookRegistry` containing only registered
|
|
220
|
+
* callbacks — the original list of provider objects is not retained, and
|
|
221
|
+
* the registry also contains callbacks bound to internal Strands objects
|
|
222
|
+
* that must not be cross-wired into per-thread agents.
|
|
223
|
+
*/
|
|
224
|
+
private readonly _plugins;
|
|
225
|
+
private readonly _agentsByThread;
|
|
226
|
+
private readonly _proxyToolNamesByThread;
|
|
227
|
+
/**
|
|
228
|
+
* Guards first-time thread initialization. The sessionManagerProvider call
|
|
229
|
+
* introduces an async yield point between the "is this thread new?" check
|
|
230
|
+
* and the map assignment, so concurrent requests for the same new threadId
|
|
231
|
+
* could otherwise both create an agent and one would clobber the other.
|
|
232
|
+
*/
|
|
233
|
+
private readonly _threadInitLock;
|
|
234
|
+
/**
|
|
235
|
+
* Threads with an in-flight run. Strands `Agent.stream()` throws if a
|
|
236
|
+
* second invocation is started on a busy agent; we detect the collision
|
|
237
|
+
* up front and emit a protocol-shaped RUN_ERROR/THREAD_BUSY instead.
|
|
238
|
+
* TypeScript-only: the Python adapter has no equivalent guard.
|
|
239
|
+
*/
|
|
240
|
+
private readonly _activeRunsByThread;
|
|
241
|
+
/** Outstanding Strands interrupt IDs per thread, used to validate
|
|
242
|
+
* incoming `RunAgentInput.resume[]` (interrupts.mdx rule 4). */
|
|
243
|
+
private readonly _pendingInterruptsByThread;
|
|
244
|
+
/**
|
|
245
|
+
* When non-null, the adapter bypasses per-thread cloning and invokes
|
|
246
|
+
* the orchestrator directly. See `StrandsAgentOptions.agent`.
|
|
247
|
+
*/
|
|
248
|
+
private readonly _orchestrator;
|
|
249
|
+
/**
|
|
250
|
+
* Injectable logger. Defaults to console `warn`/`error` with `debug`
|
|
251
|
+
* suppressed, matching Python's stdlib `logging.getLogger(__name__)`.
|
|
252
|
+
*/
|
|
253
|
+
private readonly _log;
|
|
254
|
+
constructor(options: StrandsAgentOptions);
|
|
255
|
+
/** Run the Strands agent and yield AG-UI events. */
|
|
256
|
+
run(inputData: RunAgentInput): AsyncGenerator<BaseEvent, void, void>;
|
|
257
|
+
protected _runRaw(inputData: RunAgentInput): AsyncGenerator<BaseEvent, void, void>;
|
|
258
|
+
private _runSingleAgent;
|
|
259
|
+
/**
|
|
260
|
+
* Legacy burst path for tool calls — invoked when the Strands SDK delivers
|
|
261
|
+
* a complete `ToolUseBlock` or when a `ToolBehavior.argsStreamer` takes
|
|
262
|
+
* over args emission at contentBlockStop.
|
|
263
|
+
*
|
|
264
|
+
* The streaming path inside `_runSingleAgent` handles the common case
|
|
265
|
+
* directly; this helper handles continuation turns and custom streamers.
|
|
266
|
+
*
|
|
267
|
+
* Getters/setters surface the caller's local variables because JS closures
|
|
268
|
+
* capture by reference only for `const` / `let` in scope — an object of
|
|
269
|
+
* mutable fields would work but would require threading `state` through
|
|
270
|
+
* `_runSingleAgent`'s long body.
|
|
271
|
+
*/
|
|
272
|
+
private _emitToolCall;
|
|
273
|
+
/**
|
|
274
|
+
* Orchestrator-mode run loop. TypeScript-only: drives a `Graph` or `Swarm`
|
|
275
|
+
* `.stream()` call and translates multi-agent events. Per-thread caching,
|
|
276
|
+
* session managers, and proxy-tool sync don't apply.
|
|
277
|
+
*/
|
|
278
|
+
private _runOrchestrator;
|
|
279
|
+
private _buildThreadAgentConfig;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Build the message-history seed handed to `AgentConfig.messages` on
|
|
283
|
+
* cold-cache agent creation. TypeScript-only: the Python SDK mutates
|
|
284
|
+
* `Agent.messages` in place after construction via
|
|
285
|
+
* `_buildStrandsHistory`, whereas the TS SDK consumes a seed at
|
|
286
|
+
* construction time.
|
|
287
|
+
*
|
|
288
|
+
* - Normal run (tail is a `user` turn): seed everything except the final
|
|
289
|
+
* user turn; the final turn is passed to `agent.stream(...)` as the
|
|
290
|
+
* fresh prompt.
|
|
291
|
+
* - Continuation run (tail is a `tool` message) or orphan tail: seed the
|
|
292
|
+
* entire history so the agent sees its own tool call + result before the
|
|
293
|
+
* synthetic continuation prompt fires.
|
|
294
|
+
*
|
|
295
|
+
* Returns `undefined` when the resulting seed would be empty or would
|
|
296
|
+
* start with an `assistant` turn (Bedrock rejects assistant-first history).
|
|
297
|
+
*/
|
|
298
|
+
declare function buildStrandsSeed(messages: Message[], log?: Logger): Promise<AgentConfig["messages"]>;
|
|
299
|
+
/**
|
|
300
|
+
* Convert AG-UI messages into the `MessageData` shape `AgentConfig.messages`
|
|
301
|
+
* accepts on cold-cache agent construction. Similar in spirit to
|
|
302
|
+
* `_buildStrandsHistory` but drops orphan tool turns (Bedrock rejects them).
|
|
303
|
+
*/
|
|
304
|
+
declare function convertMessagesForStrandsSeed(messages: Message[], log?: Logger): Promise<Array<{
|
|
305
|
+
role: "user" | "assistant";
|
|
306
|
+
content: unknown[];
|
|
307
|
+
}>>;
|
|
308
|
+
//#endregion
|
|
309
|
+
export { ToolCallContext as _, convertMessagesForStrandsSeed as a, buildContextExtras as b, MaybePromise as c, StateContextBuilder as d, StateFromArgs as f, ToolBehavior as g, StrandsAgentConfig as h, buildStrandsSeed as i, PredictStateMapping as l, StatePayload as m, StrandsAgentOptions as n, ArgsStreamer as o, StateFromResult as p, buildSnapshotMessages as r, CustomResultHandler as s, StrandsAgent as t, SessionManagerProvider as u, ToolCallContextExtras as v, Logger as x, ToolResultContext as y };
|
|
310
|
+
//# sourceMappingURL=agent-B2EYZvns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-B2EYZvns.d.ts","names":[],"sources":["../src/logger.ts","../src/config.ts","../src/agent.ts"],"mappings":"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"}
|