Skip to content

Repository files navigation

pi-agent-colab

npm tests license pi-package

Live session-to-session collaboration for pi and kimchi.

Run two (or more) coding-agent terminals side by side. Each session discovers the others, binds an A2A-compatible inbox, and can hand bounded work to a peer — "kinda like a subagent", except the worker is a full interactive session with its own user, its own context, and its own TUI.

flowchart LR
    subgraph TUI-A["kimchi/pi TUI — session A (lead)"]
        A1[agent + tools<br/>list_peers · link_peer<br/>ask_peer · message_peer] --> A2[agent-colab extension]
        A2 --> A3[A2A inbox server<br/>127.0.0.1:port<br/>bearer token]
        A2 -- "/colab picker<br/>/agent-name" --> U1[user]
    end

    subgraph TUI-B["kimchi/pi TUI — session B (worker)"]
        B1[agent + tools] --> B2[agent-colab extension]
        B2 --> B3[A2A inbox server<br/>127.0.0.1:port<br/>bearer token]
    end

    R[("peer registry<br/><agentDir>/peers/*.json<br/>pid-liveness, names.json")]

    A2 <-- HTTP JSON-RPC<br/>message/send · tasks/get<br/>A2A v1.0 subset --> B3
    B2 <-. HTTP JSON-RPC .-> A3
    A2 --- R
    B2 --- R

    style A3 fill:#1b3a5c,color:#fff
    style B3 fill:#1b3a5c,color:#fff
    style R fill:#4a2d12,color:#fff
Loading

Why

Orchestrating parallel coding work today means copy-pasting between terminals, or spawning throwaway subagent processes that can't see what your other sessions already know. agent-colab makes your existing sessions addressable:

  • Discover every live local session — new, restarted, or reloaded peers appear on their own; nothing to re-register.
  • Delegate a bounded task to a named worker and wait for its reply (ask_peer), or fire-and-forget a heads-up (message_peer).
  • Stay cache-friendly: peers exchange conclusions + file pointers, never transcripts or JSON dumps. Inbound messages append at the conversation tail — every session remains one unbroken, prefix-cache-friendly token stream. (Session merging was deliberately rejected: a merged file is a token stream no inference server ever cached.)

Install

# As a pi package (recommended)
pi install npm:pi-agent-colab          # or: pi install git:github.com/getkimchi/pi-agent-colab

# From a checkout
./install.sh                           # symlinks into pi's discovered extensions dir

New sessions load it automatically. Already-running sessions: type /reload — pi re-runs extension discovery in place, no restart needed.

Quick start

# Terminal A                          # Terminal B
$ kimchi                              $ kimchi
> /agent-name alpha                   > /colab          ← pick alpha
> ...                                 > "Ask alpha what's in its cwd"
                                        → agent calls ask_peer,
                                          alpha's reply lands here
Command What it does
/colab Pick a live session → link it as a worker, optionally tell your agent
/agent-name <name> Name this session (persisted; peers address you by it)
/reload Attach/update the extension in a running session

Tools your agent gets

Tool Behavior
list_peers Live local sessions (self hidden, linked marked)
link_peer / unlink_peer Designate / drop a worker
ask_peer Blocking task → wakes an idle peer, returns its reply as the tool result
message_peer Fire-and-forget → never wakes the peer; optional notifyWhenIdle one-shot notice

Delivery semantics

Acknowledgment is transport-level, never model-level — the JSON-RPC task state is the receipt, handled by the extension. The receiving agent never burns a turn to say "got it".

sequenceDiagram
    participant UA as User (A)
    participant AA as Agent A
    participant IA as A's inbox (A2A)
    participant IB as B's inbox (A2A)
    participant AB as Agent B

    UA->>AA: "Ask beta to check the flaky test"
    AA->>IA: ask_peer → POST message/send
    IA->>IB: JSON-RPC (bearer token)
    IB->>IB: consent check (accept/hold/refuse)
    IB->>AB: inject "[peer message from alpha]"<br/>idle → followUp + triggerTurn<br/>busy → steer (between tool calls)
    Note over AB: works, settles
    IB-->>IA: task completed (reply text captured<br/>from B's session transcript)
    IA-->>AA: tool result: B's reply
    AA->>UA: "beta says: it's the retry loop in x.ts"
Loading

Fire-and-forget (message_peer) skips the wake entirely: the task completes at injection (that's the HTTP-200-style ack), the message queues as nextTurn, and an opt-in notifyWhenIdle notice is sent by the extension — immediately if the peer is already idle, otherwise after its next settle.

Configuration

Variable Default Meaning
AGENT_COLAB on off disables the extension
AGENT_COLAB_INBOUND accept hold = approval dialog per message · refuse = reject at the door
AGENT_COLAB_STATE_DIR <agentDir>/peers peer registry location

Security

  • Inboxes bind 127.0.0.1 only, with a mandatory per-session bearer token.
  • Peer messages cannot approve permissions, change configuration, or execute commands; the receiver's own permission gates still apply.
  • Every inbound message is labeled with its sender in the transcript.
  • Abuse resistance: 200 KB message cap, burst cap, duplicate suppression, in-flight cap, self-send refusal — agent-to-agent loops die on their own.

Architecture notes

  • Pure extension — imports only pi's public API (ExtensionAPI, getAgentDir), typebox, and pi-tui. No harness internals; works in vanilla pi and kimchi.
  • Registry<agentDir>/peers/<sessionId>.json records with pid-liveness pruning on read; names.json persists /agent-name across restarts. The agent dir is inferred from the live session-file path, so all sessions converge on one registry even across harness redirections.
  • A2A subsetGET /.well-known/agent-card.json, message/send, tasks/get, tasks/cancel (JSON-RPC 2.0 over loopback HTTP, per the A2A v1.0 spec). The client.ts/a2a-server.ts seam is designed for a later swap to the official a2a-js SDK and SSE streaming.
  • Session files are append-only entry chains (parentId-linked); reply capture reads the newest assistant entry after an injection marker.

Development

npm install
npm test        # 37 tests: registry, A2A protocol, tools, full extension lifecycle
npm run check   # tsc --noEmit

Roadmap

  • Headless sessions (-p/rpc) bind inboxes — long-running workers stay reachable
  • A2A message/stream (SSE) for streaming delegation updates
  • Shared-server KV reuse: messages already carry log refs; a KV-transfer layer carries what was read while A2A carries what changed

License

MIT

About

Live session-to-session collaboration for pi & kimchi coding agents discover local sessions, delegate tasks to a peer session as a worker, A2A loopback transport. Installable as a pi package.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages