From a0a45f64a391f8c0f60aa6e0d63ef3f2711068fd Mon Sep 17 00:00:00 2001 From: agent-of-mkmeral Date: Mon, 23 Mar 2026 18:12:11 +0000 Subject: [PATCH] docs(bidi): migrate stop_conversation to strands_tools.stop and request_state Update all bidi streaming docs to reflect the new stop mechanism: - Replace stop_conversation imports with strands_tools.stop - Document request_state['stop_event_loop'] flag for custom stop tools - Add deprecation notices for legacy stop_conversation tool - Update 7 files: agent, events, quickstart, io, and 3 model pages Related: strands-agents/sdk-python#1954 --- .../bidirectional-streaming/agent.mdx | 2 +- .../bidirectional-streaming/events.mdx | 2 +- .../concepts/bidirectional-streaming/io.mdx | 20 +++++++------- .../models/gemini_live.mdx | 6 ++--- .../models/nova_sonic.mdx | 6 ++--- .../models/openai_realtime.mdx | 6 ++--- .../bidirectional-streaming/quickstart.mdx | 27 ++++++++++++++----- 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/agent.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/agent.mdx index 9b07dd69b..deaa26b7c 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/agent.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/agent.mdx @@ -167,7 +167,7 @@ Tools execute concurrently without blocking the conversation. When a tool is inv 3. Tool use and result messages are added atomically to conversation history 4. Results are automatically sent back to the model -The special `stop_conversation` tool triggers agent shutdown instead of sending results back to the model. +The agent loop checks for `request_state["stop_event_loop"]` to trigger graceful shutdown instead of sending tool results back to the model. Any tool can set this flag to stop the conversation. The built-in `strands_tools.stop` tool uses this mechanism. The legacy `stop_conversation` tool is deprecated but still supported as a fallback. ### Connection Lifecycle diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/events.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/events.mdx index bfabcaefc..4efd7c77d 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/events.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/events.mdx @@ -164,7 +164,7 @@ Emitted when the streaming connection is closed. - `"timeout"`: Connection timed out - `"error"`: Error occurred - `"complete"`: Conversation completed normally - - `"user_request"`: User requested closure (via `stop_conversation` tool) + - `"user_request"`: User requested closure (via `strands_tools.stop` or any tool that sets `request_state["stop_event_loop"]`) ### Response Lifecycle Events diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/io.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/io.mdx index 745531314..9bba4ce46 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/io.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/io.mdx @@ -31,7 +31,7 @@ Implementation of these protocols will look as follows: ```python from strands.experimental.bidi import BidiAgent -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop from strands.experimental.bidi.types.events import BidiOutputEvent from strands.experimental.bidi.types.io import BidiInput, BidiOutput @@ -70,12 +70,12 @@ To connect your I/O channels into the agent loop, you can pass them as arguments import asyncio from strands.experimental.bidi import BidiAgent -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop async def main(): - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(tools=[stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(tools=[stop]) await agent.run(inputs=[MyBidiInput()], outputs=[MyBidiOutput()]) @@ -100,12 +100,12 @@ import asyncio from strands.experimental.bidi import BidiAgent from strands.experimental.bidi.io import BidiAudioIO -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop async def main(): - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(tools=[stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(tools=[stop]) audio_io = BidiAudioIO(input_device_index=1) await agent.run( @@ -154,12 +154,12 @@ import asyncio from strands.experimental.bidi import BidiAgent from strands.experimental.bidi.io import BidiTextIO -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop async def main(): - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(tools=[stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(tools=[stop]) text_io = BidiTextIO(input_prompt="> You: ") await agent.run( diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/gemini_live.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/gemini_live.mdx index 92a6ce89e..87f5f5763 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/gemini_live.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/gemini_live.mdx @@ -39,7 +39,7 @@ import asyncio from strands.experimental.bidi import BidiAgent from strands.experimental.bidi.io import BidiAudioIO, BidiTextIO from strands.experimental.bidi.models import BidiGeminiLiveModel -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop from strands_tools import calculator @@ -54,8 +54,8 @@ async def main() -> None: }, client_config={"api_key": ""}, ) - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(model=model, tools=[calculator, stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(model=model, tools=[calculator, stop]) audio_io = BidiAudioIO() text_io = BidiTextIO() diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/nova_sonic.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/nova_sonic.mdx index 96599803c..95336c184 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/nova_sonic.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/nova_sonic.mdx @@ -43,7 +43,7 @@ import asyncio from strands.experimental.bidi import BidiAgent from strands.experimental.bidi.io import BidiAudioIO, BidiTextIO from strands.experimental.bidi.models import BidiNovaSonicModel -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop from strands_tools import calculator @@ -58,8 +58,8 @@ async def main() -> None: }, client_config={"region": "us-east-1"}, # only available in us-east-1, eu-north-1, and ap-northeast-1 ) - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(model=model, tools=[calculator, stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(model=model, tools=[calculator, stop]) audio_io = BidiAudioIO() text_io = BidiTextIO() diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/openai_realtime.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/openai_realtime.mdx index 3250c0ee9..2282ce3c1 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/models/openai_realtime.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/models/openai_realtime.mdx @@ -38,7 +38,7 @@ import asyncio from strands.experimental.bidi import BidiAgent from strands.experimental.bidi.io import BidiAudioIO, BidiTextIO from strands.experimental.bidi.models import BidiOpenAIRealtimeModel -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop from strands_tools import calculator @@ -53,8 +53,8 @@ async def main() -> None: }, client_config={"api_key": ""}, ) - # stop_conversation tool allows user to verbally stop agent execution. - agent = BidiAgent(model=model, tools=[calculator, stop_conversation]) + # stop tool allows user to verbally stop agent execution. + agent = BidiAgent(model=model, tools=[calculator, stop]) audio_io = BidiAudioIO() text_io = BidiTextIO() diff --git a/src/content/docs/user-guide/concepts/bidirectional-streaming/quickstart.mdx b/src/content/docs/user-guide/concepts/bidirectional-streaming/quickstart.mdx index ec5db5480..8dc0c265c 100644 --- a/src/content/docs/user-guide/concepts/bidirectional-streaming/quickstart.mdx +++ b/src/content/docs/user-guide/concepts/bidirectional-streaming/quickstart.mdx @@ -414,19 +414,19 @@ See [Controlling Conversation Lifecycle](#controlling-conversation-lifecycle) fo ## Graceful Shutdown -Use the experimental `stop_conversation` tool to allow users to end conversations naturally: +Use the `stop` tool from `strands_tools` to allow users to end conversations naturally. The `stop` tool sets `request_state["stop_event_loop"]`, which the agent loop checks to trigger a graceful shutdown: ```python import asyncio from strands.experimental.bidi import BidiAgent, BidiAudioIO from strands.experimental.bidi.models import BidiNovaSonicModel -from strands.experimental.bidi.tools import stop_conversation +from strands_tools import stop model = BidiNovaSonicModel() agent = BidiAgent( model=model, - tools=[stop_conversation], - system_prompt="You are a helpful assistant. When the user says 'stop conversation', use the stop_conversation tool." + tools=[stop], + system_prompt="You are a helpful assistant. When the user says 'stop', use the stop tool." ) audio_io = BidiAudioIO() @@ -436,12 +436,27 @@ async def main(): inputs=[audio_io.input()], outputs=[audio_io.output()] ) - # Conversation ends when user says "stop conversation" + # Conversation ends when user says "stop" asyncio.run(main()) ``` -The agent will gracefully close the connection when the user explicitly requests it. +You can also create custom stop tools using the `request_state["stop_event_loop"]` flag: + +```python +from strands import tool + +@tool +def end_session(request_state: dict) -> str: + request_state["stop_event_loop"] = True + return "Goodbye!" +``` + +The agent will gracefully close the connection when any tool sets `request_state["stop_event_loop"] = True`. + +:::note[Deprecated: stop_conversation] +The legacy `stop_conversation` tool from `strands.experimental.bidi.tools` is deprecated and will be removed in a future version. Migrate to `strands_tools.stop` or use `request_state["stop_event_loop"]` in custom tools. +::: ## Debug Logs