@neurealistic/agency
v3.1.0
Published
Agency System — AI-assisted team co-working infra. v1: AgentManager (spawn/track/reap keyed agents).
Readme
Agency
AI-assisted team co-working infrastructure. Agency is a small local daemon that spawns, tracks, and reaps keyed AI agents, hosts them behind a shared HTTP control plane (including an MCP endpoint), and gives each agent its own persistent home (definition + memory + skills) and brokered secrets.
It is a multi-agent system, not a chat swarm: specialized agents, each with per-agent memory/skills, communicate through a bounded, dispatcher-mediated control plane — never a peer free-for-all.
Status:
v2.0.0. Node ≥ 18, ESM, TypeScript. Runtime worker files ship as.mjs.
What's in the box
| Piece | File(s) | Role |
|---|---|---|
| AgentManager | src/agent-manager.ts | spawn-or-reuse (owner affinity), in-flight tracking, idle reap, beacon/heartbeat, orphan re-attach |
| Daemon / HTTP server | src/daemon.ts, src/server.ts | the control plane on 127.0.0.1:4900; routes below |
| Backends | src/backends/* | pluggable agent runtime: sdk (Claude Agent SDK), socket, stub; + approval bridge, perm-gate, session store, skill-inherit |
| MCP | src/mcp/build.ts, src/mcp/agency-mcp.ts | one tool factory served BOTH as stdio (agency-mcp.ts) and HTTP (POST /mcp) |
| Secrets | src/secrets/* | broker + providers (macOS Keychain / 1Password / env), per-owner isolation, OAuth helper |
| Roster | $AGENCY_HOME/roster/<role>/ | each hired agent's HOME: its .md def + memory/ + skills/ |
| UI | src/ui.ts | a tiny status page (GET /ui) — wake / sleep / clone / kill |
Install
From npm (installs the agency CLI globally):
npm i -g @neurealistic/agency
agency install # PROJECT scope by default: ./.mcp.json + ./.claude/settings.json (add -g for machine-wide ~/.claude.*)
agency start # run the daemonFrom source (development):
npm install
npm run build # tsc + copy-assets.mjs (ships the .mjs runtime files into dist/)
npx agency install # symlink `agency` onto PATH (~/.local/bin) + register the MCP endpoint
# (user-scope ~/.claude.json, or --config <file>) as { type:http, url:.../mcp }agency uninstall removes the symlink + the agency MCP entry. During development you can skip the symlink and run everything through npm run agency -- <command> (uses tsx, no build needed).
Run the daemon
agency start # background daemon → http://127.0.0.1:4900
agency status # daemon state + agent count
agency stop
agency serve # run in the FOREGROUND (logs to stdout)Logs: $AGENCY_HOME/agency.log (default ~/.agency/agency.log).
Chat
Every agent event (spawn, assign, result, close …) is captured by default to
$AGENCY_HOME/logs/chat.jsonl — zero-config. View + send messages live:
agency chat # opens the built-in chat at http://127.0.0.1:4900/chatDrive agents (daemon must be running)
agency request <role> <owner> # spawn-or-reuse the role-for-owner agent (affinity)
agency list # live agents
agency assign <id|key> '<json>' # give work; prints a workId
agency result <workId> # fetch a job's status + result
agency close <id|key> # graceful close (SIGTERM)
agency reap # reap idle + free agents now
agency discover # re-scan beacons + re-attach orphan agents
agency sessions # agents with a stored (resumable) session
agency forget <role> <owner> # clear an agent's stored session ("clear memory")Roster — Agency-owned agent homes
agency hire <role> --from <.md|dir> [--add-memory <p>]… [--add-skill <p>]…
agency learn <role> [--add-memory <p>]… [--add-skill <p>]… # attach to an existing agent
agency agents # list hired agents
agency fire <role> # remove a hired agent's home
agency skill add|ls|rm <role> … # manage an agent's named skillsSecrets (local, no daemon)
agency secret ask [owner] <channel> # store a token typed into a NATIVE OS dialog (never seen by the caller)
agency secret set [owner] <channel> # value read from STDIN (not argv)
agency secret get|ls|rm … # inspect / delete (--reveal to print a value)
agency secret import [owner] # seed from current .env (anthropic/slack/jira/gmail)Providers: keychain (macOS "agents-agency") · op (1Password) · env. Read order = AGENCY_SECRETS (default keychain,env). Tokens are handed to an agent over its control socket, never via argv/env of the caller.
MCP endpoint
The same tool set is exposed two ways from src/mcp/build.ts:
- HTTP (shared):
POST http://127.0.0.1:4900/mcp— a stateless Streamable-HTTP endpoint, so every harness on the machine talks to the ONE running daemon. This is whatagency installregisters in~/.claude.json:{ "mcpServers": { "agency": { "type": "http", "url": "http://127.0.0.1:4900/mcp" } } } - stdio (per-client):
npm run mcp(src/mcp/agency-mcp.ts) — a classic spawned-per-client server, for tools that only accept acommandconfig.
Tools: agency_list · agency_request · agency_assign · agency_result · agency_close · agency_discover · agency_health.
HTTP routes (control plane)
GET /health
GET /agents list
POST /agent {role,owner} spawn-or-reuse (affinity) → record
POST /agent/:id/assign {payload} give work (tracks in-flight)
DELETE /agent/:id graceful close (SIGTERM)
POST /reap reap idle + free agents
POST /discover re-attach orphan agents
POST /mcp MCP (Streamable HTTP)
GET /config daemon config (defaultOwner, …)
GET /roster · POST /roster/:role/clone · DELETE /roster/:role
GET /ui · GET /events (SSE) · /skillsConfiguration (env)
| Var | Default | Meaning |
|---|---|---|
| AGENCY_HOME | ~/.agency | data root — relocatable; holds agents/ (beacons), sock/ (control sockets), roster/<role>/, agency.log |
| AGENCY_PORT | 4900 | daemon HTTP port |
| AGENCY_OWNER | — | default owner for un-scoped requests |
| AGENCY_BACKEND | sdk | agent runtime: sdk | socket | stub |
| AGENCY_IDLE_MS | — | idle window before an agent is reap-eligible |
| AGENCY_SECRETS | keychain,env | secret provider read order |
| AGENCY_UI_REFRESH_MS | — | /ui auto-refresh interval |
Layout
src/
├── agent-manager.ts # spawn/track/reap keyed agents
├── daemon.ts # background daemon (start/stop/status)
├── server.ts # HTTP control plane (routes above)
├── cli/agency.ts # the `agency` CLI
├── mcp/{build,agency-mcp}.ts # MCP tool factory (HTTP + stdio)
├── backends/*.mjs # agent runtimes + approval/perm-gate/session
├── secrets/* # broker + keychain/1Password/env providers
├── paths.ts · types.ts · ui.ts
scripts/copy-assets.mjs # copies runtime .mjs into dist/ (tsc won't)Development
npm run agency -- <cmd> # run the CLI via tsx (no build)
npm run demo # src/demo.ts
npm run build # tsc + copy-assets.mjs → dist/Build note: tsc does not emit the .mjs runtime worker files; scripts/copy-assets.mjs copies them into dist/ (wired into build + prepare). Skipping it makes agent spawn fail with ENOENT.
