Files
VolcanicSecretary/README.md
EugeneTes d8561748a7 Add README, Docker packaging, and workspace templates
Docker build verified locally (docker build -t volcanic-secretary .
succeeded on this machine). Step 6's manual end-to-end checklist
against a real Telegram bot was not run in this environment (no bot
token or owner id available); the checklist is kept in the README's
Tests section for the owner to run before relying on this in
production.

Claude-Session: https://claude.ai/code/session_01JtuZTCMW9TyogEmBgGf8JT
2026-09-06 17:43:58 +02:00

5.3 KiB

Volcanic Secretary

A personal assistant you talk to over Telegram. The agent engine is Pi embedded through its SDK. It lives in one workspace directory, runs tools without asking, remembers things in MEMORY.md, and can schedule reminders, prompts, and watcher scripts.

Setup (Windows or any host with Node 24)

  1. Create a bot with @BotFather and copy the token.
  2. Find your numeric Telegram user id (send /start to @userinfobot).
  3. Log in to a model provider once with pi so ~/.pi/agent/auth.json exists, or plan to set PI_MODEL plus a provider API key.
  4. Copy .env.example to .env and fill in TELEGRAM_BOT_TOKEN and TELEGRAM_OWNER_ID. Add OPENAI_API_KEY if you want voice notes transcribed.
  5. npm install, then npm run dev (development) or npm run build && npm start.

The bot messages you 🟒 Online. when it is ready. Only your user id is accepted; everyone else is ignored.

Talking to it

Send text, photos, voice notes, or files. Photos go to the model as images. Voice notes are transcribed with OpenAI and echoed back as 🎀 .... Files are saved to workspace/inbox/ and the agent is told the path.

While the agent works you see one βš™οΈ Working… message that updates with tool activity, then the answer. Send another message while it works and it is queued for the current run (you get a πŸ‘€ reaction).

Commands: /status, /new, /stop, /jobs, /cancel <id>, /compact.

Scheduling

Ask in plain language:

  • "Remind me at 9 tomorrow to call the dentist" (one-off, sent directly)
  • "Every weekday at 8, summarize what's in my inbox folder" (recurring prompt through the agent)
  • "Write a script that checks the price on this page every 10 minutes and tell me only if it drops below 50" (watcher script)

Watcher scripts follow one rule: print nothing and exit 0 to stay silent, print a message to trigger delivery, exit non-zero on a real error. Failures are reported once and stay quiet while the same failure repeats.

Jobs live in workspace/.secretary/jobs.json.

Workspace

workspace/
  AGENTS.md    persona and standing instructions (edit freely)
  MEMORY.md    facts the assistant keeps; it edits this itself
  scripts/     scripts for scheduled jobs
  inbox/       files you sent
  .secretary/  runtime state

The agent's edits to MEMORY.md are local runtime data. Leave them uncommitted, or run git update-index --assume-unchanged workspace/MEMORY.md.

Environment variables

Variable Required Default Purpose
TELEGRAM_BOT_TOKEN yes Bot token
TELEGRAM_OWNER_ID yes Your numeric user id
WORKSPACE_DIR no ./workspace Workspace directory
OPENAI_API_KEY no Enables voice transcription
STT_MODEL no gpt-4o-transcribe OpenAI transcription model
PI_MODEL no Pi default provider/model or provider/model:thinking
PI_CODING_AGENT_DIR no ~/.pi/agent Pi config directory (auth, settings, packages)
SECRETARY_TIMEZONE no system IANA timezone for cron and time display
SECRETARY_SHELL no Git Bash / bash Shell used for scheduled scripts
LOG_LEVEL no info debug, info, warn, error

Keeping it running on Windows

Use Task Scheduler (run node dist/main.js at logon, restart on failure) or npm i -g pm2 then pm2 start dist/main.js --name secretary.

Docker / Coolify

docker compose up -d --build runs it with two named volumes: /workspace and /pi-agent. Provide the environment through Coolify. For model auth either copy a Pi agent directory containing auth.json into the /pi-agent volume, or set ANTHROPIC_API_KEY and PI_MODEL=anthropic/claude-opus-4-8 (or another model you have access to). The image includes bash, git, ripgrep, and Python 3 so watcher scripts work the same as on Windows.

Tests

npm test runs the unit tests. SECRETARY_SMOKE=1 npx vitest run src/agent/pi-backend.smoke.test.ts runs one real model call through Pi.

Manual end-to-end checklist

Run npm run dev with a real bot and walk through every line:

  1. hi β†’ progress message appears then disappears, reply arrives as formatted text.
  2. Long answer (explain git rebase in detail with code examples) β†’ multiple messages, code blocks render, no HTML shows raw.
  3. Photo with caption what is this β†’ reply describes the image.
  4. Voice note β†’ 🎀 <transcript> then a reply. Without OPENAI_API_KEY β†’ the not-configured note.
  5. Document (a small .csv) with caption summarize this β†’ file appears in workspace/inbox/ with date prefix, reply uses it.
  6. Send a message while a long run is in progress β†’ πŸ‘€ reaction, and the agent picks it up in the same run.
  7. /stop during a run β†’ Stopped. and no final answer message.
  8. remind me in 2 minutes to stretch β†’ confirmation with the fire time; two minutes later <job name>: <message> arrives directly.
  9. every minute run scripts/ping.py and tell me if it prints something where ping.py prints on even minutes β†’ messages arrive only on even minutes; /jobs lists it; /cancel <id> removes it.
  10. Ask it to remember a fact (remember that my dog is called Rex), then /new, then what is my dog called β†’ answer comes from MEMORY.md.
  11. Stop the daemon, start it again β†’ conversation continues (what did we just talk about).
  12. /compact β†’ reply with token counts.