Skip to main content

Execution Model

2.4 Execution Model​

Phase-Ordered Message Delivery​

The fundamental correctness property of the SDK is:

Messages sent during Phase N are delivered to agent inboxes BEFORE Phase N+1 begins.

When you write self.run(Sequence(action_A, action_B)), the runtime guarantees that all messages sent by agents during action_A are delivered to recipient inboxes before action_B starts executing. This eliminates race conditions and ensures deterministic execution regardless of which backend is used or how many threads/processes are involved.

This means the order of actions in run() IS the message delivery order. If Bank agents broadcast their status in Phase 1, and Bank agents check solvency in Phase 2, then every bank sees every other bank's status message when it checks solvency. This is the no-write-sharing invariant: agents never read each other's state directly, only through messages, and messages have a well-defined delivery time.

Eight Execution Backends​

All backends implement the ExecutionBackend abstract base class with three methods: execute_action(), deliver_messages(), and get_agents_for(). The model code does not know or care which backend is running it --- the same model.py produces identical results on any backend (guaranteed by the SHA-256 seed hierarchy and phase-ordered delivery).

Backend__init__ ParamsParallelismBest For
LocalBackend(none)SequentialDebugging, small models, determinism verification
ThreadPoolBackendmax_workers: int = 4ThreadsI/O-bound agents, moderate parallelism
ProcessPoolBackendmax_workers: Optional[int] = NoneProcessesCPU-bound models (GIL bypass)
MCPBackendmcp_config: MCPConfigDistributed HTTPMulti-machine deployment
EmulatorBackend(inherits MCP)In-processTesting distributed logic locally
AsyncBackendsemaphore_limit: int = 128asyncioLLM-heavy models (bifurcated execution)
PregelBackendmax_supersteps: int = 100BSP superstepsGraph algorithms (PageRank, label propagation)
DaskBackendscheduler_address, n_workers, partition_strategyDistributed clusterLarge-scale production

Backends are switched via settings.json without any code changes:

{"orchestration": {"mode": "local"}}
{"orchestration": {"mode": "threaded", "max_workers": 8}}
{"orchestration": {"mode": "async", "async_semaphore_limit": 128}}
{"orchestration": {"mode": "dask", "scheduler_address": "tcp://scheduler:8786"}}

The PregelBackend deserves special mention: it implements the Bulk Synchronous Parallel (BSP) model where agents can vote_to_halt() when they have nothing more to do. Execution continues in supersteps until all agents have halted or a convergence condition is met. This is the natural execution model for iterative graph algorithms.