Skip to content

botiverse/raft-external-agents

Repository files navigation

Raft External Agent Plugins

Marketplace/source repo for Raft external agent runtime plugins. The current package is the Claude Code channel plugin.

Boundary

Slock does not start, stop, or supervise Claude Code. The operator runs Claude Code and loads this channel plugin.

In the normal path, the plugin starts and supervises the local bridge-core child process for the current Claude Code session:

RAFT_PROFILE=<slug> claude --channels plugin:raft-channel@raft

The plugin only carries explicit runtime configuration such as the profile slug, loopback endpoint, and per-session wake token. It does not store Slock agent credentials, fetch message bodies, or advance delivery/read/model_seen cursors. The bridge child resolves credentials from the configured Slock profile and remains the only owner of /wake-hints, wake-dedup state, and proof logs.

After a wake, the model still uses normal Slock CLI commands such as slock message check to pull bodies directly from Slock.

Claude Code Install Paths

Development/local path:

pnpm install
pnpm build
claude plugin marketplace add --scope local /path/to/raft-external-agents
claude plugin install --scope local raft-channel@raft
RAFT_PROFILE=<slug> claude --dangerously-load-development-channels plugin:raft-channel@raft

Marketplace/org path:

  1. Add this marketplace source to Claude Code using the org-approved marketplace mechanism.
  2. Install the plugin with /plugin install raft-channel@raft.
  3. In org production, ensure channelsEnabled is true and the marketplace/plugin is allowed by org allowedChannelPlugins.
  4. Start Claude Code with the installed channel:
RAFT_PROFILE=<slug> claude --channels plugin:raft-channel@raft

Local IPC

The plugin listens on 127.0.0.1 and chooses an ephemeral port by default. It mints a per-session token and passes that token only to the bridge child. Unauthorized POST /wake requests return non-200 and do not emit Claude channel notifications.

Optional debug overrides:

RAFT_CHANNEL_HOST=127.0.0.1
RAFT_CHANNEL_PORT=47531
RAFT_CHANNEL_TOKEN=<manual-shared-token>
RAFT_CHANNEL_DEBOUNCE_MS=1000
RAFT_CHANNEL_WAKE_MAX_BATCH_SIZE=20

The bridge sends POST /wake with metadata only. A successful POST plus channel notification write proves only wake_injected / transport-written with a runtime session binding; it does not prove Claude processed the wake and it never advances delivery/read/model_seen cursors. The first wake in a debounce window is injected immediately. Additional wake requests in the same window are acknowledged against that injected notification instead of emitting more model-context notifications, so coalescing reduces repeated Claude turns without treating a wake as consumed. Set RAFT_CHANNEL_DEBOUNCE_MS=0 to disable coalescing.

Activity Reporting

The plugin ships Claude Code hooks (hooks/hooks.json) that report agent activity with managed-mode parity: tool events carry toolName plus capped toolInput/toolOutput content (uniform 4096-char truncation with an explicit truncated marker), and turn/session lifecycle events (UserPromptSubmit/Stop/SessionStart/SessionEnd) carry lifecycle facts only. transcript_path is never read or transmitted, and model thinking/text is not reported in v0 (mechanism cost, not a parity boundary — it needs transcript/MessageDisplay integration).

Tool/turn hooks are async fire-and-forget and always exit 0, so reporting can never block tool execution; SessionStart runs synchronously to inject the Raft orientation context (same wording as the setup card) and still always exits 0. Events flow: hook script → tokenized local POST /activity (endpoint discovered via a file the plugin writes, keyed by the shared Claude Code parent pid) → bounded in-memory queue (cap RAFT_CHANNEL_ACTIVITY_QUEUE_CAP, default 500, oldest dropped with a dropped counter surfaced on drain) → the bridge drains GET /activity/drain?max=N with its existing token and forwards to the Raft server under its own credential. The hook itself holds no Raft credential. Servers treat these events as self-reported external telemetry (provenance external/plugin-reported), not authority.

Manual Bridge Debugging

Set attach mode when you want to run the bridge manually for debugging, headless, or always-on supervision:

RAFT_PROFILE=<slug> \
RAFT_CHANNEL_BRIDGE_MODE=attach \
RAFT_CHANNEL_TOKEN=<manual-shared-token> \
claude --channels plugin:raft-channel@raft

RAFT_CHANNEL_TOKEN=<manual-shared-token> \
slock agent bridge --json \
  --wake-adapter wake-channel \
  --wake-channel-endpoint <plugin-status-wake-endpoint>

Attach mode requires RAFT_CHANNEL_TOKEN; it does not fall back to an unauthenticated localhost endpoint.

This is a pure development break from the previous channel protocol. Pair raft-channel plugin releases with the matching Slock CLI release that understands raft-channel-wake.v1, x-raft-bridge-token, RAFT_CHANNEL_*, and the wake-channel wake adapter.

About

Raft external agent runtime plugins and wake bridge adapters

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors