diff --git a/README.md b/README.md index c47fa63a..e3d909a9 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ from strands import Agent # or bring your agent. @app.entrypoint async def handler(request): prompt = request.get("prompt") + if not isinstance(prompt, str): + raise ValueError("prompt must be a string") agent = Agent() @@ -55,6 +57,9 @@ async def handler(request): app.run() ``` +Validate agent input before forwarding it to an agent framework. Keep prompts typed as strings and pass only prompt +text to the agent. + **What you get with Bedrock AgentCore:** - ✅ **Keep your agent logic** - Works with Strands, LangGraph, CrewAI, Autogen, or custom frameworks - ✅ **Zero infrastructure management** - No servers, containers, or scaling concerns diff --git a/src/bedrock_agentcore/runtime/ag_ui.py b/src/bedrock_agentcore/runtime/ag_ui.py index fac40467..70ea5ab4 100644 --- a/src/bedrock_agentcore/runtime/ag_ui.py +++ b/src/bedrock_agentcore/runtime/ag_ui.py @@ -96,6 +96,9 @@ def entrypoint(self, agent_or_func: Any) -> Any: - An object with a ``.run()`` method (framework agents) - A callable / async generator function (custom agents, decorator form) + Adapters should validate message content after protocol parsing before forwarding it to another agent + framework. + The registered handler is served on both ``POST /invocations`` (SSE) and ``/ws`` (WebSocket). diff --git a/src/bedrock_agentcore/runtime/app.py b/src/bedrock_agentcore/runtime/app.py index f2e596be..870a1a6b 100644 --- a/src/bedrock_agentcore/runtime/app.py +++ b/src/bedrock_agentcore/runtime/app.py @@ -215,6 +215,9 @@ def __init__( def entrypoint(self, func: Callable) -> Callable: """Decorator to register a function as the main entrypoint. + Invocation payloads are passed to the registered function unchanged. Applications should validate input + before forwarding it to an agent framework. + Args: func: The function to register as entrypoint diff --git a/tests_integ/agents/streaming_agent.py b/tests_integ/agents/streaming_agent.py index 33c35005..a4c052c5 100644 --- a/tests_integ/agents/streaming_agent.py +++ b/tests_integ/agents/streaming_agent.py @@ -12,6 +12,8 @@ async def agent_invocation(payload): user_message = payload.get( "prompt", "No prompt found in input, please guide customer to create a json payload with prompt key" ) + if not isinstance(user_message, str): + raise ValueError("prompt must be a string") stream = agent.stream_async(user_message) async for event in stream: app.logger.info("Streaming event: %s", event) diff --git a/tests_integ/async/interactive_async_strands.py b/tests_integ/async/interactive_async_strands.py index 43025ae1..62f658dc 100644 --- a/tests_integ/async/interactive_async_strands.py +++ b/tests_integ/async/interactive_async_strands.py @@ -517,6 +517,8 @@ def agent_invocation(payload): "Hello! I can start long-running data processing tasks. Try: " "'Start processing a large dataset for ML training' or 'What are my options?'", ) + if not isinstance(user_message, str): + raise ValueError("prompt must be a string") result = agent(user_message) diff --git a/tests_integ/runtime/test_simple_agent.py b/tests_integ/runtime/test_simple_agent.py index 65d24f56..53a383f1 100644 --- a/tests_integ/runtime/test_simple_agent.py +++ b/tests_integ/runtime/test_simple_agent.py @@ -20,7 +20,10 @@ def setup(self): @app.entrypoint async def agent_invocation(payload): - return agent(payload.get("message")) + message = payload.get("message") + if not isinstance(message, str): + raise ValueError("message must be a string") + return agent(message) app.run() """).strip()