Skip to content

Support named agents and bounded agent delegation #160

Description

@owainlewis

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, 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:

agent = "neo"
delegation_max_depth = 3
delegation_max_workers = 4
delegation_max_timeout = "30m"

[agents.neo]
runtime = "codex"
runtime_profile = "neo"
description = "Straightforward coding and implementation"
delegates = ["reviewer", "researcher"]
timeout = "20m"

[agents.reviewer]
runtime = "claude"
runtime_profile = "reviewer"
description = "Independent code review"
delegates = []
timeout = "10m"

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.

Invocation ledger

Add a durable agent_invocations ledger with:

id, root_id, parent_id, source_kind, source_id,
agent_name, runtime, runtime_profile, config_hash, depth,
state, prompt_hash, prompt, result, error,
created_at, started_at, finished_at

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.
  • Tests cover config migration, fake runner contracts, cross-process capacity, persistence ordering, cancellation, crash recovery, and end-to-end channel isolation.
  • Push does not add Gmail, OAuth, external-service tools, a generic tool registry, an MCP host, or its own reasoning loop.

Out of scope

  • Gmail, calendar, browser, or other service integrations in Push
  • Shared model, MCP, tool, skill, credential, or permission configuration
  • Push automatically choosing a child agent
  • Persistent child conversations
  • Cross-machine execution
  • Voting, debate, automatic answer merging, or automatic fallback
  • A general workflow language

Design artifact

The full reviewed design is prepared at docs/multi-agent/design.md. It should land with the implementation after human review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions