@aws/agentcore 1.0.0-preview.23 → 1.0.0-preview.25
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/dist/assets/README.md +5 -0
- package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +146 -28
- package/dist/assets/__tests__/input-validation.test.ts +44 -0
- package/dist/assets/agents/AGENTS.md +2 -0
- package/dist/assets/evaluators/autoevals-lambda/execution-role-policy.json +15 -0
- package/dist/assets/evaluators/autoevals-lambda/lambda_function.py +37 -0
- package/dist/assets/evaluators/autoevals-lambda/pyproject.toml +22 -0
- package/dist/assets/evaluators/deepeval-lambda/execution-role-policy.json +15 -0
- package/dist/assets/evaluators/deepeval-lambda/lambda_function.py +29 -0
- package/dist/assets/evaluators/deepeval-lambda/pyproject.toml +19 -0
- package/dist/assets/mcp/python/pyproject.toml +1 -1
- package/dist/assets/python/a2a/googleadk/base/main.py +8 -2
- package/dist/assets/python/a2a/googleadk/base/pyproject.toml +4 -4
- package/dist/assets/python/a2a/langchain_langgraph/base/main.py +11 -5
- package/dist/assets/python/a2a/langchain_langgraph/base/pyproject.toml +2 -2
- package/dist/assets/python/a2a/strands/base/pyproject.toml +1 -1
- package/dist/assets/python/http/autogen/base/README.md +5 -0
- package/dist/assets/python/http/autogen/base/main.py +2 -0
- package/dist/assets/python/http/googleadk/base/README.md +5 -0
- package/dist/assets/python/http/googleadk/base/main.py +2 -0
- package/dist/assets/python/http/langchain_langgraph/base/README.md +5 -0
- package/dist/assets/python/http/langchain_langgraph/base/main.py +4 -0
- package/dist/assets/python/http/langchain_langgraph/base/pyproject.toml +2 -2
- package/dist/assets/python/http/openaiagents/base/README.md +5 -0
- package/dist/assets/python/http/openaiagents/base/main.py +2 -0
- package/dist/assets/python/http/strands/base/README.md +6 -0
- package/dist/assets/python/http/strands/base/main.py +40 -4
- package/dist/assets/python/http/strands/base/pyproject.toml +1 -1
- package/dist/assets/python/mcp/standalone/base/pyproject.toml +1 -1
- package/dist/assets/typescript/http/strands/base/README.md +5 -0
- package/dist/assets/typescript/http/strands/base/main.ts +8 -3
- package/dist/assets/typescript/http/vercelai/base/README.md +5 -0
- package/dist/assets/typescript/http/vercelai/base/main.ts +8 -2
- package/dist/cli/index.mjs +507 -502
- package/npm-shrinkwrap.json +234 -376
- package/package.json +4 -1
- package/scripts/extract-cli-model.mjs +47 -6
- package/scripts/extract-cli-model.test.mjs +43 -0
- package/scripts/render_adoc.py +81 -5
- package/scripts/safe-junit-reporter.ts +7 -0
- package/scripts/sanitize-test-artifacts.ts +65 -0
- package/scripts/test_render_adoc.py +38 -0
|
@@ -5,7 +5,7 @@ from google.adk.agents import Agent
|
|
|
5
5
|
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
|
|
6
6
|
from google.adk.runners import Runner
|
|
7
7
|
from google.adk.sessions import InMemorySessionService
|
|
8
|
-
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
|
|
8
|
+
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill
|
|
9
9
|
from bedrock_agentcore.runtime import serve_a2a
|
|
10
10
|
from model.load import load_model
|
|
11
11
|
|
|
@@ -99,7 +99,6 @@ runner = Runner(
|
|
|
99
99
|
card = AgentCard(
|
|
100
100
|
name=agent.name,
|
|
101
101
|
description=agent.description,
|
|
102
|
-
url="http://localhost:9000/",
|
|
103
102
|
version="0.1.0",
|
|
104
103
|
capabilities=AgentCapabilities(streaming=True),
|
|
105
104
|
skills=[
|
|
@@ -112,6 +111,13 @@ card = AgentCard(
|
|
|
112
111
|
],
|
|
113
112
|
default_input_modes=["text"],
|
|
114
113
|
default_output_modes=["text"],
|
|
114
|
+
supported_interfaces=[
|
|
115
|
+
AgentInterface(
|
|
116
|
+
protocol_binding="JSONRPC",
|
|
117
|
+
protocol_version="1.0",
|
|
118
|
+
url="http://localhost:9000/",
|
|
119
|
+
)
|
|
120
|
+
],
|
|
115
121
|
)
|
|
116
122
|
|
|
117
123
|
if __name__ == "__main__":
|
|
@@ -9,11 +9,11 @@ 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.
|
|
12
|
+
"a2a-sdk[http-server] >= 1.0.1, < 2.0.0",
|
|
13
13
|
"aws-opentelemetry-distro",
|
|
14
|
-
"bedrock-agentcore[a2a] >= 1.0
|
|
15
|
-
"google-adk >=
|
|
16
|
-
"google-genai >=
|
|
14
|
+
"bedrock-agentcore[a2a-v1] >= 1.19.0",
|
|
15
|
+
"google-adk[a2a] >= 2.5.0, < 3.0.0",
|
|
16
|
+
"google-genai >= 2.9.0, < 3.0.0",
|
|
17
17
|
# 1.13.0 was yanked for broken imports.
|
|
18
18
|
"opentelemetry-resourcedetector-gcp >= 1.9.0a0, < 2.0.0, != 1.13.0",
|
|
19
19
|
]
|
|
@@ -4,11 +4,11 @@ import os
|
|
|
4
4
|
from langchain_core.tools import tool
|
|
5
5
|
from langgraph.prebuilt import create_react_agent
|
|
6
6
|
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
|
|
7
|
+
from a2a.helpers import new_task_from_user_message
|
|
7
8
|
from a2a.server.agent_execution import AgentExecutor, RequestContext
|
|
8
9
|
from a2a.server.events import EventQueue
|
|
9
10
|
from a2a.server.tasks import TaskUpdater
|
|
10
|
-
from a2a.types import AgentCapabilities, AgentCard, AgentSkill, Part
|
|
11
|
-
from a2a.utils import new_task
|
|
11
|
+
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, Part
|
|
12
12
|
from bedrock_agentcore.runtime import serve_a2a
|
|
13
13
|
from model.load import load_model
|
|
14
14
|
|
|
@@ -100,7 +100,7 @@ class LangGraphA2AExecutor(AgentExecutor):
|
|
|
100
100
|
self.graph = graph
|
|
101
101
|
|
|
102
102
|
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
103
|
-
task = context.current_task or
|
|
103
|
+
task = context.current_task or new_task_from_user_message(context.message)
|
|
104
104
|
if not context.current_task:
|
|
105
105
|
await event_queue.enqueue_event(task)
|
|
106
106
|
updater = TaskUpdater(event_queue, task.id, task.context_id)
|
|
@@ -109,7 +109,7 @@ class LangGraphA2AExecutor(AgentExecutor):
|
|
|
109
109
|
result = await self.graph.ainvoke({"messages": [("user", user_text)]})
|
|
110
110
|
response = result["messages"][-1].content
|
|
111
111
|
|
|
112
|
-
await updater.add_artifact([Part(
|
|
112
|
+
await updater.add_artifact([Part(text=response)])
|
|
113
113
|
await updater.complete()
|
|
114
114
|
|
|
115
115
|
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
@@ -119,7 +119,6 @@ class LangGraphA2AExecutor(AgentExecutor):
|
|
|
119
119
|
card = AgentCard(
|
|
120
120
|
name="{{ name }}",
|
|
121
121
|
description="A LangGraph agent on Bedrock AgentCore",
|
|
122
|
-
url="http://localhost:9000/",
|
|
123
122
|
version="0.1.0",
|
|
124
123
|
capabilities=AgentCapabilities(streaming=True),
|
|
125
124
|
skills=[
|
|
@@ -132,6 +131,13 @@ card = AgentCard(
|
|
|
132
131
|
],
|
|
133
132
|
default_input_modes=["text"],
|
|
134
133
|
default_output_modes=["text"],
|
|
134
|
+
supported_interfaces=[
|
|
135
|
+
AgentInterface(
|
|
136
|
+
protocol_binding="JSONRPC",
|
|
137
|
+
protocol_version="1.0",
|
|
138
|
+
url="http://localhost:9000/",
|
|
139
|
+
)
|
|
140
|
+
],
|
|
135
141
|
)
|
|
136
142
|
|
|
137
143
|
if __name__ == "__main__":
|
|
@@ -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.
|
|
12
|
+
"a2a-sdk[http-server] >= 1.0.1, < 2.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",
|
|
@@ -17,7 +17,7 @@ dependencies = [
|
|
|
17
17
|
{{/if}}{{#if (eq modelProvider "OpenAI")}}"langchain-openai >= 0.2.0",
|
|
18
18
|
{{/if}}"aws-opentelemetry-distro",
|
|
19
19
|
"opentelemetry-instrumentation-langchain >= 0.59.0",
|
|
20
|
-
"bedrock-agentcore[a2a] >= 1.
|
|
20
|
+
"bedrock-agentcore[a2a-v1] >= 1.19.0",
|
|
21
21
|
"botocore[crt] >= 1.35.0",
|
|
22
22
|
"langgraph >= 0.2.0",
|
|
23
23
|
]
|
|
@@ -10,7 +10,7 @@ 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.
|
|
13
|
+
{{/if}}"a2a-sdk[all] >= 0.3.0, < 0.4.0",
|
|
14
14
|
"aws-opentelemetry-distro",
|
|
15
15
|
"bedrock-agentcore[a2a] >= 1.9.1",
|
|
16
16
|
"botocore[crt] >= 1.35.0",
|
|
@@ -13,6 +13,11 @@ file defines a Starlette ASGI app with the AutoGen framework running within.
|
|
|
13
13
|
|
|
14
14
|
`model/load.py` instantiates your chosen model provider.
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
Validate invocation input before forwarding it to the agent framework. Keep plain prompts typed as strings and pass
|
|
19
|
+
only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -127,6 +127,8 @@ async def invoke(payload, context):
|
|
|
127
127
|
|
|
128
128
|
# Process the user prompt
|
|
129
129
|
prompt = payload.get("prompt", "What can you help me with?")
|
|
130
|
+
if not isinstance(prompt, str):
|
|
131
|
+
raise ValueError("prompt must be a string")
|
|
130
132
|
session_id = getattr(context, "session_id", "default-session")
|
|
131
133
|
|
|
132
134
|
# Reuse the per-session agent (preserves conversation history)
|
|
@@ -13,6 +13,11 @@ file defines a Starlette ASGI app with the Google ADK framework running within.
|
|
|
13
13
|
|
|
14
14
|
`model/load.py` instantiates your chosen model provider (Gemini).
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
Validate invocation input before forwarding it to the agent framework. Keep plain prompts typed as strings and pass
|
|
19
|
+
only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -191,6 +191,8 @@ async def invoke(payload, context):
|
|
|
191
191
|
|
|
192
192
|
# Process the user prompt
|
|
193
193
|
prompt = payload.get("prompt", "What can you help me with?")
|
|
194
|
+
if not isinstance(prompt, str):
|
|
195
|
+
raise ValueError("prompt must be a string")
|
|
194
196
|
session_id = getattr(context, "session_id", "default_session")
|
|
195
197
|
user_id = payload.get("user_id", "default_user")
|
|
196
198
|
|
|
@@ -13,6 +13,11 @@ file defines a Starlette ASGI app with the LangChain/LangGraph framework running
|
|
|
13
13
|
|
|
14
14
|
`model/load.py` instantiates your chosen model provider.
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
Validate invocation input before forwarding it to the agent framework. Keep plain prompts typed as strings and pass
|
|
19
|
+
only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -183,6 +183,8 @@ async def invoke(payload, context):
|
|
|
183
183
|
|
|
184
184
|
# Process the user prompt
|
|
185
185
|
prompt = payload.get("prompt", "What can you help me with?")
|
|
186
|
+
if not isinstance(prompt, str):
|
|
187
|
+
raise ValueError("prompt must be a string")
|
|
186
188
|
session_id = getattr(context, "session_id", "default-session")
|
|
187
189
|
touch_thread(session_id)
|
|
188
190
|
log.info(f"Agent input: {prompt}")
|
|
@@ -202,6 +204,8 @@ async def invoke(payload, context):
|
|
|
202
204
|
|
|
203
205
|
# Process the user prompt
|
|
204
206
|
prompt = payload.get("prompt", "What can you help me with?")
|
|
207
|
+
if not isinstance(prompt, str):
|
|
208
|
+
raise ValueError("prompt must be a string")
|
|
205
209
|
session_id = getattr(context, "session_id", "default-session")
|
|
206
210
|
touch_thread(session_id)
|
|
207
211
|
log.info(f"Agent input: {prompt}")
|
|
@@ -12,8 +12,8 @@ dependencies = [
|
|
|
12
12
|
"aws-opentelemetry-distro",
|
|
13
13
|
"opentelemetry-instrumentation-langchain >= 0.59.0",
|
|
14
14
|
"langgraph >= 1.0.2",
|
|
15
|
-
"mcp
|
|
16
|
-
"langchain-mcp-adapters >= 0.
|
|
15
|
+
"mcp ~= 1.24.0",
|
|
16
|
+
"langchain-mcp-adapters >= 0.3.1",
|
|
17
17
|
"langchain >= 1.0.3",
|
|
18
18
|
"bedrock-agentcore >= 1.8.0",
|
|
19
19
|
"botocore[crt] >= 1.35.0",
|
|
@@ -13,6 +13,11 @@ file defines a Starlette ASGI app with the OpenAI Agents SDK framework running w
|
|
|
13
13
|
|
|
14
14
|
`model/load.py` instantiates your chosen model provider (OpenAI).
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
Validate invocation input before forwarding it to the agent framework. Keep plain prompts typed as strings and pass
|
|
19
|
+
only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -184,6 +184,8 @@ async def invoke(payload, context):
|
|
|
184
184
|
|
|
185
185
|
# Process the user prompt
|
|
186
186
|
prompt = payload.get("prompt", "What can you help me with?")
|
|
187
|
+
if not isinstance(prompt, str):
|
|
188
|
+
raise ValueError("prompt must be a string")
|
|
187
189
|
session_id = getattr(context, "session_id", "default-session")
|
|
188
190
|
session = get_session(session_id)
|
|
189
191
|
|
|
@@ -13,6 +13,12 @@ file defines a Starlette ASGI app with the chosen Agent framework SDK running wi
|
|
|
13
13
|
|
|
14
14
|
`model/load.py` instantiates your chosen model provider.
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
Validate invocation input before forwarding it to Strands. Keep plain prompts typed as strings. If the app accepts a
|
|
19
|
+
caller-supplied message history, retain `strip_trailing_tool_use()`, which normalizes the history tail before
|
|
20
|
+
invoking the agent.
|
|
21
|
+
|
|
16
22
|
## Environment Variables
|
|
17
23
|
|
|
18
24
|
| Variable | Required | Description |
|
|
@@ -481,17 +481,53 @@ get_or_create_agent = agent_factory()
|
|
|
481
481
|
{{/if}}
|
|
482
482
|
|
|
483
483
|
|
|
484
|
+
def strip_trailing_tool_use(messages: Any) -> list[dict]:
|
|
485
|
+
"""Strip toolUse blocks from the tail until the last message has none."""
|
|
486
|
+
if not isinstance(messages, list):
|
|
487
|
+
raise ValueError("messages must be a list")
|
|
488
|
+
|
|
489
|
+
messages = list(messages)
|
|
490
|
+
while messages:
|
|
491
|
+
last = messages[-1]
|
|
492
|
+
if not isinstance(last, dict):
|
|
493
|
+
raise ValueError("each message must be an object")
|
|
494
|
+
original_content = last.get("content", [])
|
|
495
|
+
if not isinstance(original_content, list) or not all(isinstance(block, dict) for block in original_content):
|
|
496
|
+
raise ValueError("each message content value must be a list of content blocks")
|
|
497
|
+
|
|
498
|
+
content = [block for block in original_content if "toolUse" not in block]
|
|
499
|
+
if len(content) == len(original_content):
|
|
500
|
+
break
|
|
501
|
+
if content:
|
|
502
|
+
messages[-1] = {**last, "content": content}
|
|
503
|
+
break
|
|
504
|
+
messages.pop()
|
|
505
|
+
|
|
506
|
+
return messages
|
|
507
|
+
|
|
508
|
+
|
|
484
509
|
def _extract_prompt(payload: dict):
|
|
485
|
-
"""Accept harness
|
|
510
|
+
"""Accept validated harness messages, tool results, or a plain prompt string."""
|
|
511
|
+
if not isinstance(payload, dict):
|
|
512
|
+
raise ValueError("payload must be a JSON object")
|
|
486
513
|
if "messages" in payload:
|
|
487
|
-
return payload["messages"]
|
|
514
|
+
return strip_trailing_tool_use(payload["messages"])
|
|
488
515
|
if "tool_results" in payload:
|
|
516
|
+
tool_results = payload["tool_results"]
|
|
517
|
+
if not isinstance(tool_results, list) or not all(
|
|
518
|
+
isinstance(tool_result, dict) and isinstance(tool_result.get("toolUseId"), str)
|
|
519
|
+
for tool_result in tool_results
|
|
520
|
+
):
|
|
521
|
+
raise ValueError("tool_results must contain objects with a toolUseId string")
|
|
489
522
|
return [{"role": "user", "content": [{"toolResult": {
|
|
490
523
|
"toolUseId": tr["toolUseId"],
|
|
491
524
|
"status": tr.get("status", "success"),
|
|
492
525
|
"content": tr.get("content", []),
|
|
493
|
-
}} for tr in
|
|
494
|
-
|
|
526
|
+
}} for tr in tool_results]}]
|
|
527
|
+
prompt = payload.get("prompt", "")
|
|
528
|
+
if not isinstance(prompt, str):
|
|
529
|
+
raise ValueError("prompt must be a string")
|
|
530
|
+
return prompt
|
|
495
531
|
|
|
496
532
|
|
|
497
533
|
def _has_inline_function_call(messages) -> bool:
|
|
@@ -14,7 +14,7 @@ dependencies = [
|
|
|
14
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
|
-
{{/if}}"mcp
|
|
17
|
+
{{/if}}"mcp ~= 1.24.0",
|
|
18
18
|
{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
|
|
19
19
|
{{/if}}{{#if (eq modelProvider "LiteLLM")}}"litellm >= 1.0.0",
|
|
20
20
|
{{/if}}{{#if bedrockMantle}}"openai >= 1.0.0",
|
|
@@ -13,6 +13,11 @@ defines an HTTP server that streams tokens from your chosen Agent framework SDK.
|
|
|
13
13
|
|
|
14
14
|
`model/load.ts` instantiates your chosen model provider.
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
The generated Zod request schema keeps plain prompts typed as strings before forwarding them to Strands. Retain this
|
|
19
|
+
validation when extending the request shape, and pass only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -34,6 +34,10 @@ const SYSTEM_PROMPT = `
|
|
|
34
34
|
You are a helpful assistant. Use tools when appropriate.
|
|
35
35
|
`;
|
|
36
36
|
|
|
37
|
+
const requestSchema = z.object({
|
|
38
|
+
prompt: z.string().default(''),
|
|
39
|
+
});
|
|
40
|
+
|
|
37
41
|
{{#if hasMemory}}
|
|
38
42
|
const agentCache = new Map<string, Agent>();
|
|
39
43
|
|
|
@@ -87,7 +91,8 @@ async function getOrCreateAgent(sessionId: string): Promise<Agent> {
|
|
|
87
91
|
|
|
88
92
|
const app = new BedrockAgentCoreApp({
|
|
89
93
|
invocationHandler: {
|
|
90
|
-
|
|
94
|
+
requestSchema,
|
|
95
|
+
async *process(payload, context) {
|
|
91
96
|
{{#if hasMemory}}
|
|
92
97
|
const sessionId = context?.sessionId ?? 'default-session';
|
|
93
98
|
const actorId = getActorId(payload, context);
|
|
@@ -99,7 +104,7 @@ const app = new BedrockAgentCoreApp({
|
|
|
99
104
|
|
|
100
105
|
{{#if hasMemory}}
|
|
101
106
|
try {
|
|
102
|
-
for await (const event of agent.stream(payload.prompt
|
|
107
|
+
for await (const event of agent.stream(payload.prompt)) {
|
|
103
108
|
if (
|
|
104
109
|
event.type === 'modelStreamUpdateEvent' &&
|
|
105
110
|
event.event?.type === 'modelContentBlockDeltaEvent' &&
|
|
@@ -123,7 +128,7 @@ const app = new BedrockAgentCoreApp({
|
|
|
123
128
|
// e.g. Anthropic). Restoring on error keeps the session reusable.
|
|
124
129
|
const snapshot = agent.takeSnapshot({ include: ['messages'] });
|
|
125
130
|
try {
|
|
126
|
-
for await (const event of agent.stream(payload.prompt
|
|
131
|
+
for await (const event of agent.stream(payload.prompt)) {
|
|
127
132
|
if (
|
|
128
133
|
event.type === 'modelStreamUpdateEvent' &&
|
|
129
134
|
event.event?.type === 'modelContentBlockDeltaEvent' &&
|
|
@@ -13,6 +13,11 @@ defines an HTTP app that streams tokens using the Vercel AI SDK's `streamText` A
|
|
|
13
13
|
|
|
14
14
|
`model/load.ts` instantiates your chosen model provider.
|
|
15
15
|
|
|
16
|
+
## Input Validation
|
|
17
|
+
|
|
18
|
+
The generated Zod request schema keeps plain prompts typed as strings before forwarding them to the agent framework.
|
|
19
|
+
Retain this validation when extending the request shape, and pass only prompt text to the agent.
|
|
20
|
+
|
|
16
21
|
## Environment Variables
|
|
17
22
|
|
|
18
23
|
| Variable | Required | Description |
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
|
|
2
2
|
import { streamText, type ModelMessage } from 'ai';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
import { loadModel } from './model/load.js';
|
|
4
5
|
|
|
5
6
|
const SYSTEM_PROMPT = `You are a helpful assistant.`;
|
|
6
7
|
|
|
8
|
+
const requestSchema = z.object({
|
|
9
|
+
prompt: z.string().default(''),
|
|
10
|
+
});
|
|
11
|
+
|
|
7
12
|
const HISTORY_LIMIT = 128;
|
|
8
13
|
|
|
9
14
|
// Keeps one message history per sessionId so each session remembers its own
|
|
@@ -32,10 +37,11 @@ function getHistory(sessionId: string): ModelMessage[] {
|
|
|
32
37
|
|
|
33
38
|
const app = new BedrockAgentCoreApp({
|
|
34
39
|
invocationHandler: {
|
|
35
|
-
|
|
40
|
+
requestSchema,
|
|
41
|
+
async *process(payload, context) {
|
|
36
42
|
const sessionId = context?.sessionId ?? 'default-session';
|
|
37
43
|
const history = getHistory(sessionId);
|
|
38
|
-
const userMessage: ModelMessage = { role: 'user', content: payload.prompt
|
|
44
|
+
const userMessage: ModelMessage = { role: 'user', content: payload.prompt };
|
|
39
45
|
|
|
40
46
|
const model = await loadModel();
|
|
41
47
|
const result = streamText({
|