You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Push should support several named agents inside one assistant and allow one configured agent to delegate a bounded task to another. For example, neo may run through Codex and delegate an independent review to reviewer running through Claude Code.
Push remains a dispatcher and coordinator. It starts the selected runtime, records parent-child execution state, and returns the child result to the caller. The runtime continues to own its model, tools, skills, MCP servers, permissions, authentication, and external integrations.
This builds on the backend seam from #15 and is separate from choosing the next runtime adapter in #30.
Proposed design
Named agents
Replace backend names as the durable routing identity with named agent definitions:
The optional runtime_profile is opaque to Push. The runtime owns everything inside that profile, including model and tool configuration.
Existing agent = "claude", "codex", or "pi" configs remain valid through synthetic named-agent definitions. Routes and jobs resolve agent names. Job frontmatter gains agent; legacy backend remains accepted during migration, and specifying both is an error.
Delegation contract
The first dispatch surface is CLI-based so any coding runtime with shell access can use it:
push agent list [--json]
push agent run <agent> [--json]
push agent runs [--root <invocation-id>] [--json]
push agent run reads one prompt from standard input. Push appends the allowed target names, descriptions, and command usage to the caller's instructions. The caller decides whether and where to delegate. Push does no task classification, prompt rewriting, answer merging, retry, or fallback.
Every child starts a fresh backend session and returns one final reply synchronously. A coordinator may start several CLI calls concurrently.
Policy and limits
Each agent has an explicit delegation allowlist.
The configured graph must be acyclic and may not contain self edges.
Default maximum depth is three child edges, configurable from one to eight.
Default delegated worker limit is four, configurable from one to 32.
Capacity is cross-process and uses advisory slot locks.
Calls fail immediately with capacity_exhausted instead of waiting. This avoids nested parent-child deadlocks.
Prompt size is capped at 64 KiB.
Persisted prompt and result fields are capped at 64 KiB.
Live final replies are capped at 1 MiB and fail rather than returning a partial result.
Push applies no unattended permission override. The target runtime profile must already be suitable for non-interactive execution.
The allowlist is an operational guard, not a sandbox. The runtime sandbox and OS permissions remain the security boundary.
Root chat, job, evaluator, and direct CLI runs create root invocation identities. Delegated runs store the immediate parent and root. Only the root coordinator's final result is delivered to the messaging channel. Child results are persisted before being returned to the parent and remain inspectable through push agent runs.
Stable child states are succeeded, rejected, capacity_exhausted, failed, timed_out, and cancelled. Failed or interrupted work is never rerun automatically.
Session identity
Backend session state must include the named agent and runtime identity. Changing an agent's runtime or native profile rotates its session. Description, timeout, and delegation allowlist changes do not.
Delegated child sessions are always fresh and are never stored for reuse.
Cancellation and recovery
Parent cancellation or service shutdown terminates active descendants within two seconds and marks them cancelled. On restart, Push marks invocations left in running as cancelled with interrupted_by_restart; it never reruns them.
A parent and all nested CLI calls use one catalog hash. If config changes while a root is active, a new child is rejected with configuration_changed. A service restart starts roots against the new catalog.
Acceptance criteria
A default Codex agent can delegate one task to a Claude agent and incorporate the child result into one channel reply.
Two allowed children can run concurrently and share the correct root and parent ids.
A fifth child under the default four-worker limit fails immediately and starts no runtime.
Unknown, disallowed, cyclic, self, and over-depth calls start no runtime and return distinct structured errors.
A child receives common assistant instructions, its configured native profile, and no parent backend session or hidden transcript.
Child success is persisted before its JSON result is visible to the parent.
Changing an agent from Codex to Claude starts a fresh Claude session on the next root turn.
Parent timeout and shutdown terminate active descendants within two seconds.
Restart recovery cancels interrupted invocations without rerunning them.
Existing single-backend configs, routes, jobs, and session state work without manual migration.
push doctor validates names, references, graph cycles, runtime binaries, profiles, and timeout limits.
What and why
Push should support several named agents inside one assistant and allow one configured agent to delegate a bounded task to another. For example,
neomay run through Codex and delegate an independent review toreviewerrunning through Claude Code.Push remains a dispatcher and coordinator. It starts the selected runtime, records parent-child execution state, and returns the child result to the caller. The runtime continues to own its model, tools, skills, MCP servers, permissions, authentication, and external integrations.
This builds on the backend seam from #15 and is separate from choosing the next runtime adapter in #30.
Proposed design
Named agents
Replace backend names as the durable routing identity with named agent definitions:
The optional
runtime_profileis opaque to Push. The runtime owns everything inside that profile, including model and tool configuration.Existing
agent = "claude","codex", or"pi"configs remain valid through synthetic named-agent definitions. Routes and jobs resolve agent names. Job frontmatter gainsagent; legacybackendremains accepted during migration, and specifying both is an error.Delegation contract
The first dispatch surface is CLI-based so any coding runtime with shell access can use it:
push agent runreads one prompt from standard input. Push appends the allowed target names, descriptions, and command usage to the caller's instructions. The caller decides whether and where to delegate. Push does no task classification, prompt rewriting, answer merging, retry, or fallback.Every child starts a fresh backend session and returns one final reply synchronously. A coordinator may start several CLI calls concurrently.
Policy and limits
capacity_exhaustedinstead of waiting. This avoids nested parent-child deadlocks.The allowlist is an operational guard, not a sandbox. The runtime sandbox and OS permissions remain the security boundary.
Invocation ledger
Add a durable
agent_invocationsledger with:Root chat, job, evaluator, and direct CLI runs create root invocation identities. Delegated runs store the immediate parent and root. Only the root coordinator's final result is delivered to the messaging channel. Child results are persisted before being returned to the parent and remain inspectable through
push agent runs.Stable child states are
succeeded,rejected,capacity_exhausted,failed,timed_out, andcancelled. Failed or interrupted work is never rerun automatically.Session identity
Backend session state must include the named agent and runtime identity. Changing an agent's runtime or native profile rotates its session. Description, timeout, and delegation allowlist changes do not.
Delegated child sessions are always fresh and are never stored for reuse.
Cancellation and recovery
Parent cancellation or service shutdown terminates active descendants within two seconds and marks them
cancelled. On restart, Push marks invocations left inrunningascancelledwithinterrupted_by_restart; it never reruns them.A parent and all nested CLI calls use one catalog hash. If config changes while a root is active, a new child is rejected with
configuration_changed. A service restart starts roots against the new catalog.Acceptance criteria
push doctorvalidates names, references, graph cycles, runtime binaries, profiles, and timeout limits.Out of scope
Design artifact
The full reviewed design is prepared at
docs/multi-agent/design.md. It should land with the implementation after human review.