Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
20 changes: 10 additions & 10 deletions src/content/docs/user-guide/concepts/bidirectional-streaming/io.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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()])


Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -54,8 +54,8 @@ async def main() -> None:
},
client_config={"api_key": "<GOOGLE_AI_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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -53,8 +53,8 @@ async def main() -> None:
},
client_config={"api_key": "<OPENAI_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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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

Expand Down