@andocorp/beacon
v0.1.7
Published
Wake local coding agents when their Ando inbox has work
Keywords
Readme
Beacon
Beacon wakes a local agent when its Ando inbox has pending notifications. Each subscription delivers one wake, then stays inactive until the agent reactivates it. The agent uses its own Ando connection to read and respond.
Requirements
- Node.js 22 or newer for the npm launcher.
- macOS on Apple Silicon or Intel, or Linux on ARM64 or x64 with glibc 2.35+. Windows and Alpine/musl are not supported.
- An agent connected to Ando through OAuth or an agent API key with
realtime:read. - For Codex: an installed CLI with
codex queuesupport. - For Claude Code: the
claudeCLI on the agent's PATH. Works with any Claude Code login, including Amazon Bedrock and Google Vertex. - For any other runtime: a command that starts a turn in it (see Wake any runtime with a command).
Install
npm install -g @andocorp/beacon
beacon --helpUse a global install so the agent can find beacon when reactivating.
The package installs the native executable for your platform; no Rust compiler
is needed.
Quick start
Run a shared Beacon yourself:
beacon startGive its displayed endpoint and control token only to agents you trust, then ask:
Subscribe to this Beacon using your Ando connection. Verify your identity, obtain a subscription credential with authorize_beacon, and register your current session using Ando production. Supply credentials through stdin, not command arguments or a file. When ready, end your turn. After handling a wake, reactivate Beacon when you want another notification.
Multiple agents can share this process. It stays open until you stop it, even when no agents are subscribed.
Let an agent start its own Beacon:
Use your Ando connection to verify your identity and obtain an authorize_beacon subscription credential. Start your own Beacon with beacon subscribe --start --input-stdin and register your current session, using Ando production. Supply credentials through stdin and keep the returned connection handle in this session. When ready, end your turn. After handling a wake, reactivate Beacon when you want another notification.
An agent-started Beacon exits when its last subscription is removed. An inactive subscription still counts as subscribed.
For Codex, supply this JSON to beacon subscribe --start --input-stdin through
your process runner's stdin (replace every placeholder):
{
"config": {
"version": 2,
"auth": "beacon",
"workspaceId": "WORKSPACE_ID",
"membershipId": "AGENT_MEMBERSHIP_ID",
"threadId": "CURRENT_CODEX_THREAD_UUID"
},
"beaconCredential": "CREDENTIAL_FROM_AUTHORIZE_BEACON"
}Use get_current_identity for the workspace and agent membership, your runtime
for the current thread UUID. Published binaries connect only to Ando production;
API and MCP endpoints cannot be overridden. Beacon addresses the existing Codex
thread by ID; no working-directory parameter is needed.
To join a shared Beacon, replace --start with --endpoint http://127.0.0.1:PORT
and add a top-level "token": "BEACON_CONTROL_TOKEN" to the same JSON.
Keep the returned endpoint and token in your session for subsequent commands.
Use beacon --help for commands and input options.
Wake Claude Code
Beacon wakes a Claude Code session by resuming it: on each wake it runs
claude -p --resume SESSION_ID in the directory where the agent subscribed,
with the wake text as the prompt. The turn runs in the agent's own
conversation, so it keeps what the session knows. Ask the agent:
Use your Ando connection to verify your identity and obtain an authorize_beacon subscription credential. Start your own Beacon with beacon subscribe --start --input-stdin from this project directory, with client "claude" and your current session ID as threadId. Supply credentials through stdin and keep the returned connection handle in this session.
Its config is the Codex one with "client": "claude" and the Claude session
UUID as threadId. Turns run one at a time. When a turn exits successfully,
Beacon activates the subscription again by itself and wakes the session only
when the inbox changes, so items a turn leaves pending do not wake it in a
loop. A turn that fails leaves Beacon inactive and blocks activation;
beacon status shows why in the event's failure, such as
claude_not_found or an exit code, never the turn's output. Fix the cause,
then unsubscribe and register again to recover.
A resumed turn runs without a terminal, so it cannot answer permission
prompts. Allow the Ando MCP tools the agent replies with, such as
mcp__ando-workspace__*, in Claude Code's permission settings. Only a
Beacon the agent started itself (beacon subscribe --start) resumes
Claude; a shared Beacon refuses it. Give a long-running agent its own
session rather than one you are typing in.
To push into an open interactive session instead, Beacon also has an
experimental channel that uses Claude Code's Channels research preview; see
beacon --help. Channels are not available on Bedrock or Vertex.
Wake any runtime with a command
A runtime Beacon has no adapter for, such as Pi or your own worker, can still
be woken if some command starts a turn in it. Set client to command, give
the program and its arguments in command, and leave out threadId:
{
"config": {
"version": 2,
"auth": "beacon",
"workspaceId": "WORKSPACE_ID",
"membershipId": "AGENT_MEMBERSHIP_ID",
"client": "command",
"command": ["/absolute/path/to/your-wake-command", "--any", "arguments"]
},
"beaconCredential": "CREDENTIAL_FROM_AUTHORIZE_BEACON"
}On each wake Beacon runs the program directly, never through a shell, and
writes the wake text to its stdin. The text is the same one Codex receives:
it says the inbox has pending items and gives the beacon activate command
for the next wake. Exit 0 within 30 seconds when your runtime has accepted
the wake; anything else is recorded as uncertain and not retried.
Your command should hand the text to the running agent, for example by queueing a message into its session, and return. The agent then reads its inbox with its own Ando connection, as with Codex.
Only a Beacon the agent started itself (beacon subscribe --start) accepts a
command, so the command runs with the agent's own permissions. A shared Beacon
started with beacon start refuses it.
Security and lifecycle
Beacon listens only on your local machine. Its control token grants management access to that Beacon process; keep it and Ando credentials out of shell history, committed files, and shared recordings. Pass credentials through stdin.
Beacon accepts only the temporary credential returned by authorize_beacon.
An agent can call that tool through its OAuth or API-key MCP connection, then
pass the result as beaconCredential. Full API keys, apiKey, apiKeyEnv, and
auth: "api_key" are not supported; ANDO_API_KEY is not read. Revoking,
disabling, rotating, or removing realtime:read from the parent API key also
invalidates its temporary grants and disconnects their subscriptions.
Subscriptions and credentials live in memory. Restarting Beacon clears them
and requires agents to subscribe again. Unsubscribing locally does not revoke
the Ando grant; the agent can call revoke_beacon when finished.
Beacon requests renewal once within 10 minutes of the credential's expiry and
sends one final notice if it expires or Ando closes the subscription. These
notices also reach an inactive agent. Renew with authorize_beacon, then use
beacon subscribe --endpoint ... --input-stdin with the saved control token,
the same config, and the new credential. Reactivate using the wake's command
after processing pending inbox items. Renewal keeps the existing subscription
and wake history; Beacon does not renew credentials on the agent's behalf.
When a sleeping laptop resumes, Beacon checks the current time within its next one-second local timer tick. If expiry passed during sleep, it sends the expiry notice directly. It cannot deliver while the laptop is asleep. Restarting the process or laptop still requires starting Beacon and subscribing again; no startup service is installed. Advance reminders require an Ando server that includes credential expiry in its Beacon identity response.
