From f22350ce2fbd035d9b1800ff53530ae1cb1d8810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Fri, 15 May 2026 08:46:46 -0700 Subject: [PATCH] Use symmetric spawn-then-run() pattern in multi-task examples Switch every example to ``await runner.spawn(task)`` followed by ``await runner.run()`` (no task argument), and ``await runner.cancel()`` on client-disconnected instead of ``await task.cancel()``. This makes the main pipeline task look the same as the worker / proxy tasks spawned alongside it, and lets ``runner.cancel()`` drive a uniform shutdown across every root task on the bus. --- .../multi-task/code-assistant/code-assistant.py | 9 +++++---- .../local-handoff/local-handoff-two-agents-tts.py | 11 ++++++----- .../local-handoff/local-handoff-two-agents.py | 13 ++++++------- .../multi-task/parallel-debate/parallel-debate.py | 11 ++++++----- .../multi-task/remote-proxy-assistant/assistant.py | 4 +++- examples/multi-task/remote-proxy-assistant/main.py | 8 +++++--- 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/examples/multi-task/code-assistant/code-assistant.py b/examples/multi-task/code-assistant/code-assistant.py index 2b701db13..aaed286bc 100644 --- a/examples/multi-task/code-assistant/code-assistant.py +++ b/examples/multi-task/code-assistant/code-assistant.py @@ -145,8 +145,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, ) - await runner.spawn(CodeWorker("code_worker", project_path=PROJECT_PATH)) - @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): logger.info("Client connected") @@ -161,9 +159,12 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info("Client disconnected") - await task.cancel() + await runner.cancel() - await runner.run(task) + await runner.spawn(CodeWorker("code_worker", project_path=PROJECT_PATH)) + await runner.spawn(task) + + await runner.run() async def bot(runner_args: RunnerArguments): diff --git a/examples/multi-task/local-handoff/local-handoff-two-agents-tts.py b/examples/multi-task/local-handoff/local-handoff-two-agents-tts.py index aeee2358b..c4e75ed28 100644 --- a/examples/multi-task/local-handoff/local-handoff-two-agents-tts.py +++ b/examples/multi-task/local-handoff/local-handoff-two-agents-tts.py @@ -227,9 +227,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, ) - await runner.spawn(_build_greeter()) - await runner.spawn(_build_support()) - @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): logger.info("Client connected") @@ -251,9 +248,13 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info("Client disconnected") - await task.cancel() + await runner.cancel() - await runner.run(task) + await runner.spawn(_build_greeter()) + await runner.spawn(_build_support()) + await runner.spawn(task) + + await runner.run() async def bot(runner_args: RunnerArguments): diff --git a/examples/multi-task/local-handoff/local-handoff-two-agents.py b/examples/multi-task/local-handoff/local-handoff-two-agents.py index 21f388d41..cf7d8aed5 100644 --- a/examples/multi-task/local-handoff/local-handoff-two-agents.py +++ b/examples/multi-task/local-handoff/local-handoff-two-agents.py @@ -200,11 +200,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, ) - # Spawn the child LLM tasks. ``bridged=()`` on each child auto-wraps - # its pipeline with bus edges, so no extra wiring is needed here. - await runner.spawn(_build_greeter()) - await runner.spawn(_build_support()) - @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): logger.info("Client connected") @@ -226,9 +221,13 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info("Client disconnected") - await task.cancel() + await runner.cancel() - await runner.run(task) + await runner.spawn(_build_greeter()) + await runner.spawn(_build_support()) + await runner.spawn(task) + + await runner.run() async def bot(runner_args: RunnerArguments): diff --git a/examples/multi-task/parallel-debate/parallel-debate.py b/examples/multi-task/parallel-debate/parallel-debate.py index c86dd02c9..7b51fecfe 100644 --- a/examples/multi-task/parallel-debate/parallel-debate.py +++ b/examples/multi-task/parallel-debate/parallel-debate.py @@ -198,9 +198,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, ) - for role in ROLE_PROMPTS: - await runner.spawn(DebateWorker(role)) - @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): logger.info("Client connected") @@ -218,9 +215,13 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info("Client disconnected") - await task.cancel() + await runner.cancel() - await runner.run(task) + for role in ROLE_PROMPTS: + await runner.spawn(DebateWorker(role)) + await runner.spawn(task) + + await runner.run() async def bot(runner_args: RunnerArguments): diff --git a/examples/multi-task/remote-proxy-assistant/assistant.py b/examples/multi-task/remote-proxy-assistant/assistant.py index b7e728e39..6f69e52c6 100644 --- a/examples/multi-task/remote-proxy-assistant/assistant.py +++ b/examples/multi-task/remote-proxy-assistant/assistant.py @@ -104,8 +104,10 @@ async def websocket_endpoint(websocket: WebSocket): assistant = AcmeAssistant() await runner.spawn(proxy) + await runner.spawn(assistant) + logger.info("Assistant server ready, waiting for activation") - await runner.run(assistant) + await runner.run() logger.info("Assistant server session ended") diff --git a/examples/multi-task/remote-proxy-assistant/main.py b/examples/multi-task/remote-proxy-assistant/main.py index 57afef6b5..299a85b19 100644 --- a/examples/multi-task/remote-proxy-assistant/main.py +++ b/examples/multi-task/remote-proxy-assistant/main.py @@ -116,7 +116,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): remote_task_name="assistant", forward_messages=(BusFrameMessage,), ) - await runner.spawn(proxy) async def on_assistant_ready(_data: TaskReadyData) -> None: logger.info("Remote assistant ready, activating") @@ -145,9 +144,12 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info("Client disconnected") - await task.cancel() + await runner.cancel() - await runner.run(task) + await runner.spawn(proxy) + await runner.spawn(task) + + await runner.run() async def bot(runner_args: RunnerArguments):