Chairman Agent
Requirements: Python 3.9+ (stdlib only, no pip install), one Anthropic API key — everything else (Supabase, SendBlue, Telegram, macOS LaunchAgents) is optional — full walkthrough in SETUP.md.
An autonomous "chief of staff" agent: a conversational + heartbeat-driven Claude loop with server-side tool use (bash, file editing, web search), a cost guard that hard-stops spend at a monthly cap, a 32-persona agent roster it can delegate to, and a local dashboard to watch it work.
This is not a chatbot wrapper. It has three ways in — one-shot CLI chat, a
scheduled heartbeat via macOS LaunchAgent, and two optional messaging bridges
(iMessage via SendBlue, Telegram) — and one execution loop underneath all of
them (agent.py:agent_loop). Whatever channel a message comes in on, it hits
the same system prompt, the same tools, and the same cost guard.
Why it matters
Most "AI assistant" setups are a single prompt-response call. This one is a standing process: it runs on a timer whether or not you're looking at it, tracks its own spend and refuses to keep calling the API once a cap trips, and keeps a persona roster it can route sub-tasks to instead of trying to be one undifferentiated generalist. If you want an agent that has actual authority to act (run bash, edit files, search the web) on a schedule instead of only when you type to it, this is the shape of that.
What's in here
agent.py— the core loop.--chat,--chat-stdin, and--heartbeatmodes; server-side tool use (bash, text editor, web search) against the Anthropic Messages API; retries until the model stops calling tools.prompt.py— the agent's persona and standing operating rules (voice, execution standard, memory policy, mandated output structure). This is the actual "who is this agent" file — read it before you run anything, and rewrite it to be yours before you point it at your own business.config/agents.py— a 32-persona roster (Executive / Oversight / Operations / Intelligence / Revenue / Community / Product tiers) the Chairman can delegate named tasks to. Each entry is a system prompt + provider + model.cost_guard.py— monthly spend cap with an auto-cutoff threshold; wraps the API call so a runaway tool loop can't blow past budget mid-run.credit_guard.py,musa_cadence.py— smaller guard/cadence utilities used by the heartbeat and Telegram bridge.agent_bus.py— writes task/decision ledger rows to a Supabase project (optional — the agent runs fine with this unset, it just won't log).webhook.py+sendblue.py— inbound/outbound iMessage bridge via SendBlue. No Mac Full Disk Access or AppleScript required. SeeSENDBLUE-SETUP.mdfor the full wiring walkthrough.telegram_bridge.py— a stdlib long-poll Telegram bridge with one-tap commands (/pulse,/costs,/agent <ID> <task>, etc.) routed through the sameagent_loop.dashboard/— a local ops dashboard (server.py+index.html+ops.html) for watching heartbeat status, chat history, token/cost usage, and connection health. Run it separately from the agent itself.com.chairman.heartbeat.plist,com.chairman.webhook.plist— macOS LaunchAgent definitions for the scheduled heartbeat and the always-on webhook server.CUTOVER.md— a worked example of migrating a Telegram bot + agent roster from one system into this one. Useful as a reference for how the pieces fit together, not something you need to run.
Not included: the data/, inbox/, done/, and dashboard/conversations/
directories, and dashboard/usage.jsonl — these are runtime state (task
queue, processed tasks, real chat history, real usage logs) from the original
deployment. They're gitignored here on purpose; your own instance will grow
its own versions of these directories the first time you run it.
Quickstart
1. Install dependencies
The agent itself is stdlib-only (urllib, no pip install needed for
agent.py, webhook.py, sendblue.py, telegram_bridge.py,
dashboard/server.py). You need Python 3.9+ and a shell. That's it.
2. Set your environment
Copy env.example to .env and fill in real values (it's named without the
leading dot in this repo so it survives KeyzHub's secret-filename scanner —
rename it however you like once it's on your machine):
cp env.example .env
At minimum you need ANTHROPIC_API_KEY. Everything else (Supabase, SendBlue,
Telegram) is optional and gates its own feature — leave a block unset and
that bridge simply won't come up.
agent.py looks for its .env at <repo-root>/content-os/config/.env by
default (ENV_FILE near the top of the file — it's a relative path one
level up from this directory, named after the original project's layout).
Either recreate that path, or change ENV_FILE in agent.py to point at
wherever you put your .env.
3. Make the persona yours
Open prompt.py and config/agents.py. Both are written for 19Keys /
Sovereign Mind Media by name. Replace the identity, voice rules, and roster
with your own before running this against your own business — the agent
will follow whatever persona and standing mandate you give it, verbatim.
prompt.py also references a memory file path
(sovereign-wiki/memory/CHAIRMAN-MEMORY.md in the original deployment) that
isn't part of this repo. Point it at wherever you want the agent's memory to
live, or remove the reference if you're not wiring up persistent memory.
4. Run it once, by hand
python3 agent.py --chat "what should I focus on this week"
or pipe a message in:
echo "summarize today's priorities" | python3 agent.py --chat-stdin
Run a single heartbeat cycle manually (this is what the LaunchAgent will run on a schedule):
python3 agent.py --heartbeat
Drop a task file for the next heartbeat to pick up:
mkdir -p inbox
cat > inbox/$(date +%Y%m%d-%H%M)-task.md <<'EOF'
## Task
Whatever you want the agent to do next cycle.
EOF
5. Load the LaunchAgent (macOS scheduled heartbeat)
Edit the two .plist files first — they hardcode absolute paths
(/Users/19keys/sovereign-empire-sweep/chairman-agent/...) that need to
point at wherever you cloned this repo, and the heartbeat's
StartCalendarInterval (currently: Mondays at 9:00am) is a placeholder
schedule, not a recommendation.
cp com.chairman.heartbeat.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.chairman.heartbeat.plist
Unload:
launchctl unload ~/Library/LaunchAgents/com.chairman.heartbeat.plist
The webhook plist (com.chairman.webhook.plist) is only needed if you're
wiring up the SendBlue iMessage bridge — see SENDBLUE-SETUP.md.
6. Run the dashboard (optional)
cd dashboard
python3 server.py
Defaults to http://localhost:8919. It reads the same logs/, data/, and
dashboard/conversations/ directories the agent writes to at runtime — those
will be empty until you've actually run the agent a few times.
Make it your own
- Persona:
prompt.pyis the whole personality. Nothing here is magic — it's plain-language standing instructions the model follows. Rewrite it in your own voice. - Roster:
config/agents.pydefines every persona the Chairman can delegate to. Trim it to the roles you actually have, or expand it. - Cost cap:
cost_guard.pyholds the monthly spend cap and cutoff threshold — set your own number before you turn on the heartbeat. - Channels: iMessage (
SENDBLUE-SETUP.md) and Telegram (telegram_bridge.py) are both optional and independent — wire up whichever channels you actually want to talk to the agent through. - Live grounding:
agent.py:live_crm_context()pulls business numbers from a Supabase project into the system prompt ifSUPABASE_URL/SUPABASE_ANON_KEYare set. If you don't have a Supabase project, leave those unset — the agent runs without live grounding.
A note on scope
This was built as one operator's personal chief-of-staff agent, wired to their specific business. The architecture (heartbeat + tool-using loop + cost guard + multi-channel bridge + persona roster) is the reusable part. The specific persona, roster, and business-numbers wiring are not — treat them as a fully worked example to fork and replace, not as configuration to leave as-is.