Omnigent lets an orchestrator agent supervise vendor-diverse sub-agents in one shared session. The elegant part is what it didn’t build: there is no special delegation RPC, no separate review channel, no bespoke tool-result bus. There is one primitive — the child conversation — and everything is expressed through it.
A sub-agent is a child conversation, pinned to its parent by parent_conversation_id and a (parent, title) unique index. To delegate, the orchestrator calls sys_session_send / sys_session_create, ends its turn, and is later woken by inbox_awaken when a child completes. It never busy-polls. Strikingly, even web_fetch is implemented this way — as a child conversation you post to and await — not as a blocking tool call.
Because the unit of work is a conversation rather than a function call, three properties fall out for free:
- Shareable — a collaborator can open any child session and watch it live.
- Resumable — a child survives restarts; its transcript is the state.
- Forkable — you can branch a child and even switch the worker’s vendor on the fork.
Why this is non-obvious
Most frameworks model sub-agents as in-process function calls and bolt on persistence, sharing, and resumption later — each as its own subsystem. Omnigent gets all three by making the cheapest unit (a conversation + an inbox) the only unit. Uniformity at the primitive level means features compose instead of multiplying.
The pitfall
An inbox/await model needs a real wake-up path (here, a server-backed inbox and an arrival-ordered turn gate). Done naively it becomes polling, or worse, a lost-wakeup race when two children finish at once. The discipline is: the parent yields its turn and trusts the inbox — it does not loop.
Sources
-
omnigent/runner/tool_dispatch.py:1955✓ verified -
omnigent/runner/tool_dispatch.py:200✓ verified