Skip to content

[Relay] Add a durable read-only broker through the CLI #378

Description

@ranveersequeira

Parent

#377

What to build

Deliver the first complete Agentify-owned relay path: a developer can start a bounded read-only provider task, receive a stable Agentify task ID, observe durable events from another CLI process, and cancel the task.

This slice should use current one-shot delegate adapters as the execution fallback. It establishes broker ownership and task semantics without claiming multi-turn provider sessions, nested delegation, or write support.

User story

As a developer, I can start a Claude or Codex task in one terminal and inspect or cancel it from another terminal without relying on the provider's opaque session state.

Proposed CLI

agentify agent spawn --provider codex --mode read "Review the retry design"
agentify agent observe agt_01K... --follow
agentify agent cancel agt_01K... --reason "No longer needed"
agentify agent list --state running

A synchronous convenience command may compose spawn + observe:

agentify agent ask --provider claude "Explain the failing test"

Required behavior

  • Generate stable opaque task IDs owned by Agentify.
  • Persist task metadata, immutable execution policy, messages, sequenced events, terminal result, usage, and errors in worktree-local SQLite state.
  • Run a per-repository local supervisor reachable by owner-only Unix socket or Windows named pipe.
  • Autostart the supervisor on the first command and handle compatible reconnects.
  • Reuse existing route/profile/fallback/timeout/usage normalization instead of duplicating provider selection.
  • Execute only mode: read; reject write and nested-delegation requests.
  • Emit normalized, bounded, redacted public events.
  • Make event delivery at-least-once with monotonic per-task sequence numbers and cursor-based deduplication.
  • Support cooperative cancellation followed by owned process-tree termination after a grace period.
  • Mark terminal status honestly as succeeded, failed, cancelled, or lost.
  • Keep current agentify delegate behavior unchanged.

Minimal internal contract

spawn(request): Promise<SpawnReceipt>
observe(taskId, { after, waitMs, maxEvents }): Promise<Observation>
cancel(taskId, reason?): Promise<CancelReceipt>
list(filter?): Promise<TaskSummary[]>

A task request must capture:

  • objective and explicit provider/route request;
  • resolved provider, model, fallback, and capability level;
  • repository identity and workspace root;
  • immutable read-only grant;
  • timeout, turn/budget request, and enforcement provenance;
  • parent task as null in this slice;
  • idempotency key when supplied.

Suggested implementation seams

  • Extract reusable route/policy resolution from src/core/models.js.
  • Extend src/core/provider-registry.js with declared one-shot capability manifests.
  • Add the broker under src/core/agent-broker/.
  • Put broker database/socket/runtime artifacts under worktree-local paths from src/core/project-store.js.
  • Add CLI dispatch in src/main.js and completions in src/core/completion.js.
  • Reuse ACP process-tree cleanup helpers where possible without converting the transparent ACP proxy into the broker.

Acceptance criteria

  • agentify agent spawn returns before a long-running worker completes and prints a stable task ID.
  • A second CLI process can observe the same task using a cursor and does not receive duplicate logical events.
  • --follow exits on a terminal state and returns a meaningful exit code.
  • Cancellation first requests graceful stop, then terminates the owned process tree within a bounded grace period.
  • Tasks survive client exit; broker restart produces an honest recovered or lost state.
  • Only read-only execution is accepted; writes and nested children fail closed.
  • Public events exclude secrets, raw environment values, hidden reasoning, and unbounded tool arguments.
  • Current routing, fallback, timeout, usage, rolling-budget, and JSON output behavior is reused and regression-tested.
  • Existing delegate, acp, serve, context, and workflow tests remain green.
  • Unit/integration tests use fake providers and cover spawn, observe, reconnect, cancellation, idempotency, corrupt state, and process crash.
  • --json schemas are versioned and documented.

Out of scope

  • MCP collaboration tools.
  • Provider-native multi-turn follow-up.
  • Nested delegation.
  • Write access or worktree creation.
  • Remote/network broker transport.
  • Automatic retry of non-idempotent provider work.

Blocked by

None - can start immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    agentify-readyReady for Agentify automationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions