Skip to main content
Spawn & Announce lets a parent agent delegate work to sub-agents without blocking — fire tasks in parallel and collect results via callbacks or the event bus.
The user delegates parallel work; the parent spawns sub-agents and keeps running without blocking.

Quick Start

1

Simple Spawn with Callback

Fire-and-forget pattern with immediate feedback.
2

Parallel Fan-out Pattern

Spawn multiple sub-agents, do other work, then collect results.

How It Works

The spawn-announce pattern uses an event-driven architecture to coordinate between parent and sub-agents.

Choosing Your Pattern

Different use cases require different coordination patterns.

Common Patterns

Fire-and-Forget with Callback

Best for immediate processing of sub-agent results.

Parallel Fan-out with Join

Scale work across multiple sub-agents, then combine results.

Event-Driven Coordination

React to sub-agent events without callbacks.

Configuration

spawn_sub_agent Parameters

announce_completion Parameters

wait_for_completions Parameters


Async Usage

For async code, use the async variants with proper event-driven waiting.
aspawn_sub_agent + await_for_completions are reliable — a sub-agent running on a background thread wakes the awaiter as soon as it finishes, and mixing sync and async spawn calls on the same AgentTeam is safe because both paths share one threading.RLock.
Fixed in PraisonAI PR #4887. Prior to this release the async spawn/completion path had three defects reachable from ordinary usage: (1) await_for_completions() could hang until timeout — or forever with timeout=None — because check_completions() called asyncio.get_running_loop() from a background spawn thread, which raised RuntimeError that was silently swallowed, so the awaiter never woke even after the sub-agent finished; (2) the sync path used threading.RLock while the async path used asyncio.Lock, which excludes nothing against a real OS thread, so mixing sync and async spawn on one AgentTeam was a genuine data race; (3) fire-and-forget asyncio.create_task(...) results were not stored, so the event loop’s weak reference let a sub-agent run be garbage-collected mid-run. After this release, await_for_completions captures the running loop in its own coroutine frame and closes over it in check_completions, both paths share one threading.RLock, and background spawn tasks are held in a strong-reference set (self._bg_spawn_tasks) so they cannot be collected. No API surface changed.
await_for_completions subscribes to the event bus before running the initial state check, so a sub-agent that finishes between the check and the subscribe no longer causes a lost signal.

Best Practices

Prevent indefinite waiting by setting reasonable timeout values.
Inside async def functions, use aspawn_sub_agent and await_for_completions.
Completion callbacks should be lightweight to avoid blocking the event loop.
Attach metadata to track spawned sub-agents back to your domain context.
Since PR #4887, spawn_sub_agent (sync) and aspawn_sub_agent / aannounce_completion / await_for_completions (async) share one threading.RLock, so calling both on the same AgentTeam no longer races on shared completion state.

Subagent Delegation

Core multi-agent coordination

Event Bus

Event-driven architecture