Swarm#
A multi-channel Letta bot that connects to IRC and can also ingest read-only Bluesky feeds, dispatching messages to Letta agents.
The runnable entrypoint is TypeScript: npm start.
Features#
- @mention dispatch — tag an agent like
@researcher tell me about Python - Letta Cloud integration — talks to your Letta agents via the official REST API
- No auto-threading — every command must include an explicit
@agentmention - Reconnect logic — automatically reconnects to IRC with exponential backoff
- Chunked replies — long agent responses are split safely across multiple IRC lines
- Read-only Bluesky feed ingest — polls a specific feed URI and mirrors new posts into
#lathawithout posting back to Bluesky or sending them through Letta - @updates command — fetches the latest five posts from the configured Bluesky feed into IRC on demand
Setup#
-
Install dependencies:
npm install -
Create a
.envfile in the repo root:LETTA_API_KEY=your-api-key-here LETTA_AGENT_RESEARCHER_ID=agent-... LETTA_AGENT_OBSIDIAN_ID=agent-... FREEQ_CREDS_PATH=/home/nandi/code/rookery/scripts/rookery-creds.jsonnpm startreads this file automatically. You can still export env vars in the shell if you prefer. -
Point
FREEQ_CREDS_PATHat a Rookery creds JSON — the bot uses the same PDS session flow asscripts/freeq-connect.tsin the rookery repo. The file needsdid,handle,access_token,private_key_pem,public_jwk, andpds_origin. -
Review
swarm.yaml— defaults are already set for#swarmand#lathaonwss://irc.freeq.at/irc. Updatechannels.irc.joinChannels, the optionalchannels.blueskyfeed settings, and theagents:map as needed.
Running#
npm start
The bot will load the local creds, create a short-lived PDS session, join the configured IRC rooms (default #swarm and #latha), and mirror any enabled Bluesky feed(s) into #latha.
Usage in #swarm#
<alice> @researcher what is the capital of France
<swarmbot> alice: The capital of France is Paris.
<bob> @obsidian fix my bug
<swarmbot> bob: Unknown agent '@obsidian'. Available: researcher, obsidian
Configuration (swarm.yaml)#
Key fields:
server.mode/server.apiKey— Letta API authagent.name/agent.id— default Letta agentchannels.irc.server— IRC WebSocket URLchannels.irc.nick/channels.irc.joinChannels— IRC identity and ordered rooms to join (Freeq defaults to#swarmand#latha)channels.irc.allowedUsers— exact allowlist for inbound messageschannels.irc.messageReadDelayMs— ignore initial Freeq scrollback after joiningchannels.bluesky.feedUri/channels.bluesky.mirrorChannel/channels.bluesky.limit/channels.bluesky.pollIntervalMs— Bluesky feed generator URI, mirror target, fetch limit, and polling cadence (the current config uses the For You feed atat://did:plc:3guzzweuqraryl3rdkimjamk/app.bsky.feed.generator/for-youwithlimit: 1)channels.bluesky.apiBaseUrl— optional Bluesky AppView/XRPC base URL for anonymous requests; defaults tohttps://public.api.bsky.appchannels.bluesky.auth.identifier/channels.bluesky.auth.appPassword/channels.bluesky.auth.pdsUrl— optional Bluesky session for personalized feeds like For You;pdsUrldefaults tohttps://bsky.socialchannels.blueskyis read-only — posts are ingested and mirrored into IRC, but the adapter will not publish back to Blueskyagents.*— map of@name→ Lettaagent_id
Adding More Agents#
Edit swarm.yaml:
agents:
researcher: "agent-ac7541ac-0292-463e-9b72-2182ad91ddf2"
obsidian: "agent-62060ac1-999d-47cc-8d0e-eafa3f360a6b"
Then restart the bot. Users can immediately use @obsidian ....
Troubleshooting#
| Symptom | Likely Cause | Fix |
|---|---|---|
401 Unauthorized |
Missing LETTA_API_KEY |
Export the env var |
Freeq creds error |
FREEQ_CREDS_PATH is missing or wrong |
Point it at a rookery creds JSON |
Unknown agent |
Name not in agents map |
Add it to swarm.yaml |
| Timeout errors | Letta API is slow | Increase letta.timeout |
| Won't reconnect | Network blip | Wait — backoff handles it |
Related Projects#
- panproto — Schematic version control for data schemas.
Relevant for evolving
swarm.yamlstructure, agent response formats, or conversation memory schemas as the bot grows.