pinet/  multi-agent coordination for pi
DOC PINET/CORESTATUS · LIVING DOCUMENTLICENSE · MIT

Pinet Core

The runtime under the adapters: how the broker owns the mesh, how messages become durable inbox entries, and how the system repairs itself when an agent goes quiet.

§ 01topology

Runtime modes

Every pi session that loads the bridge runs in one of four modes. Pinet stays off unless you set runtimeMode, autoConnect, or autoFollow. Nothing connects to your workspace by accident.

ModeRoleUse when
singleOne instance handles everything: ingress, work, replies.You run one agent and want Slack access without a mesh.
brokerCoordinates: watches Slack, assigns work, tracks ownership, syncs state.You run several agents and want one control plane.
followerConnects to the broker, receives assigned work, stays in sync.Worker sessions joining an existing broker.
offExtension loaded, nothing running.Default.

Inside pi, /pinet start makes the current session the broker,/pinet follow joins it, and /pinet status tells you which of these is true right now. Only one session holds the Socket Mode connection: Slack allows a limited number per app, and a single WebSocket owner avoids duplicate delivery.

§ 02primitive

The message primitive

message.send is the one primitive. A Slack reply, an agent-to-agent note, and a broker nudge are the same operation with different addresses; adapters translate at the edges. The broker itself needs no adapter: it is a pi session, and you can type to it in its own terminal. This is what keeps new transports cheap: Discord, Linear, or GitHub would plug into the same flow rather than growing their own routing.

inbox semantics

Each agent has a durable inbox. Messages are:

  • routed by thread ownership (an owned thread keeps flowing to its owner)
  • queued while the agent is mid-turn, drained on the next turn
  • marked read once processed
  • preserved across restarts

Thread ownership is the continuity mechanism. Once an agent claims a Slack thread, replies in that thread route to it until the claim is released, by the agent finishing or by RALPH noticing the owner is gone.

§ 03identity

Agent identity

Agents carry a logical identity that survives reconnects. Heartbeats and leases handle liveness: a worker that stops responding loses its lease, and its claims become assignable again. Dead agents get reaped, not ignored.

Identities are named. When "Rocket Dolphin" or "Silent Crocodile" posts in a thread, you know which agent holds which task. With dozens of tasks moving at once, names are what make the mesh legible to the humans steering it. Rename a session any time with/pinet rename.

§ 04self-repair

The RALPH loop

RALPH is the broker's autonomous maintenance cycle. On every pass (default: five minutes) it:

  • checks worker presence,
  • releases stale thread claims held by unavailable workers,
  • observes pending backlog while broker maintenance handles assignment, and
  • triggers scheduled wake-ups.

The loop is tunable: faster cycles for quicker recovery, snoozing after empty cycles for quiet nights.

{
  "slack-bridge": {
    "ralphLoopIntervalMs": 120000,
    "ralphSnoozeAfterEmptyCycles": 3,
    "ralphSnoozeDurationMs": 1800000
  }
}
operational noteIf work gets stuck: /pinet status for current state,/pinet logs for repeated failures, then let RALPH run; most stalls clear on its next pass without intervention.
§ 05interface

The dispatcher

Agents drive coordination through a compact pinet dispatcher rather than a sprawl of tools: one entry point, discoverable actions, a small schema per action.

{
  "action": "send",
  "args": {
    "to": "@worker",
    "message": "Please review PR #123"
  }
}
send
Message an agent or a broker-only channel.
read
Read this agent's inbox.
schedule
Schedule a future wake-up.
free
Mark this agent idle and available for work.
help
Discover actions and their schemas; nothing bloats the hot path.

Hot-path Slack replies go through a dedicated slack_send tool; uploads, canvases, pins, bookmarks, and other cold Slack actions sit behind a matchingslack dispatcher. The split is deliberate: frequent operations get compact dedicated tools, everything else is discovered on demand.

§ 06package

@pinet/pinet-core

The pinet-core package holds the runtime helpers that work independently of Slack: the pieces the bridge uses internally, extracted behind package exports so future adapters can move one boundary at a time.

  • output option normalisation (defaults to cli; accepts json or full),
  • durable read-result formatting,
  • scheduled wake-up time parsing, and
  • thread ID helpers.

No Slack types, no adapter imports. If you are building a different transport for Pinet, this is the layer you build against.

pinet-core source the slack adapter