Skip to content

Jon-Vii/agents-switchboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Switchboard

switchboard is a small Elixir/OTP daemon for live, local agent-to-agent messaging on one laptop.

V1 is intentionally narrow:

  • localhost-only transport over a Unix domain socket
  • live session registration and discovery
  • best-effort heartbeats and expiry
  • ephemeral two-party threads
  • send, reply, close, and long-poll receive
  • explicit session status metadata
  • no durable mailbox or history yet

The core daemon is agent-neutral. The first adapter included here targets Claude Code channels.

Requirements

  • Elixir 1.19+
  • Erlang/OTP 28+
  • Node 20+ for the Claude adapter

Run The Daemon

mix deps.get
iex -S mix

In another terminal, discover the active socket path:

mix run -e 'IO.puts(Switchboard.socket_path())'

On macOS/Linux the default path is:

  • ${XDG_RUNTIME_DIR}/switchboard-<uid>.sock when XDG_RUNTIME_DIR is set
  • otherwise #{System.tmp_dir!()}/switchboard-<uid>.sock

The socket file is created with mode 0600.

Curl Examples

Register a session:

curl --unix-socket "$SOCKET" http://localhost/v1/register \
  -H 'content-type: application/json' \
  -d '{
    "display_name": "Alice",
    "client_kind": "curl",
    "adapter_kind": "manual",
    "cwd": "/tmp",
    "receive_modes": ["poll", "surface"]
  }'

List live sessions:

curl --unix-socket "$SOCKET" http://localhost/v1/sessions \
  -H "authorization: Bearer $SWITCHBOARD_TOKEN"

Send a first message:

curl --unix-socket "$SOCKET" http://localhost/v1/messages \
  -H 'content-type: application/json' \
  -H "authorization: Bearer $SWITCHBOARD_TOKEN" \
  -d '{
    "to_session_id": "sess_target",
    "content": {
      "format": "plain",
      "body": "hello from switchboard"
    }
  }'

Long-poll for events:

curl --unix-socket "$SOCKET" \
  "http://localhost/v1/events?after=0&wait_ms=15000" \
  -H "authorization: Bearer $SWITCHBOARD_TOKEN"

API Surface

  • POST /v1/register
  • POST /v1/heartbeat
  • PATCH /v1/session
  • GET /v1/sessions
  • POST /v1/messages
  • GET /v1/events?after=<cursor>&wait_ms=<n>
  • POST /v1/threads/:thread_id/close
  • DELETE /v1/session

Error codes are stable strings in JSON responses, including:

  • invalid_token
  • invalid_request
  • invalid_cursor
  • recipient_offline
  • receiver_already_waiting
  • unknown_session
  • unknown_thread
  • closed_thread

Session Metadata

Live sessions can publish a small amount of explicit status metadata:

  • availability
  • summary
  • workspace_root
  • repo
  • branch

Update them with:

curl --unix-socket "$SOCKET" http://localhost/v1/session \
  -X PATCH \
  -H 'content-type: application/json' \
  -H "authorization: Bearer $SWITCHBOARD_TOKEN" \
  -d '{
    "availability": "heads_down",
    "summary": "Debugging switchboard",
    "workspace_root": "/Users/jonatan/projects/alpha-centauri-codex",
    "repo": "alpha-centauri-codex",
    "branch": "codex/status-awareness"
  }'

Notes:

  • availability is one of available, busy, heads_down, or away
  • null clears a field
  • cwd remains the adapter launch context for compatibility
  • peers receive updates as session.updated events on /v1/events

Runtime Shape

  • Switchboard.Directory owns live session registration, auth, and presence fanout
  • Switchboard.Session owns one session’s heartbeat expiry and short event buffer
  • Switchboard.Threads owns thread records and per-thread sequencing
  • Switchboard.Dispatch validates sends and routes events
  • Switchboard.Transport.Router exposes the JSON API over Plug/Cowboy on a Unix socket

State is in-memory only. Delivery is best-effort and ephemeral by design.

Tests

mix test

The suite covers:

  • registration and live discovery
  • thread creation and ordered reply flow
  • thread close behavior
  • one outstanding long-poll receiver per session
  • heartbeat expiry and thread.peer_gone

Claude Channel Adapter

The Claude-first adapter lives in adapter/claude-channel/README.md.

It is a thin local MCP server that:

  • registers a Claude session with switchboard
  • heartbeats and long-polls over the Unix socket
  • emits notifications/claude/channel for inbound message.received events
  • exposes tools for listing sessions, sending messages, closing threads, and updating session status

Current Limits

  • POSIX-first: Unix sockets only in v1
  • ephemeral state only
  • no durable mailbox/history
  • text messages only
  • two-party threads only
  • Claude integration assumes development-channel support is available locally

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors