Control

Telegram & remote control

Connect a Telegram bot and FRIDAY becomes fully remote-controllable. Not just chat — the entire control surface: the deterministic router, slash commands, the interactive shell, document Q&A, voice notes, and human-in-the-loop approvals.

Setup

Tokens live in OS environment variables, never in config.yaml.

  1. Create a bot with @BotFather and copy the token.
  2. Message your new bot once, then read your chat id (any “get my id” bot works, or check getUpdates).
  3. Set the two environment variables and restart FRIDAY.
.env
FRIDAY_TELEGRAM_TOKEN=123456:ABC-your-bot-token
FRIDAY_TELEGRAM_CHAT_ID=987654321

# Optional outbound-only notifications channel
FRIDAY_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...

On boot you'll get a “FRIDAY is online and ready.” message, and the bot starts long-polling for your messages. Only your configured chat id is accepted — messages from any other chat are ignored.

What you can do remotely

Inbound messages run through app.process_input(text, source="telegram") — the exact same pipeline as the terminal, so the full prefix grammar from Commands & shell works from your phone:

plain text
Full turn pipeline — router, capabilities, memory — replies in chat
/ slash commands
All 13, with native Telegram autocomplete via setMyCommands
! shell commands
Run real commands on your machine, remotely
> follow-ups
Answer sudo / y-n prompts from the chat
document upload
PDF · DOCX · PPTX · XLSX · MD · TXT · HTML · CSV → RAG
voice notes
Transcribed by the local Whisper STT, then processed

Shell, from your phone

Because the ! shell is just another input prefix, you can drive a full interactive session over Telegram — including password prompts, which FRIDAY relays and accepts via > (input is not echoed back into the chat):

telegram
you  →  !sudo systemctl restart nginx
bot  ←  [sudo] password for you:
        Awaiting password — reply with > <password>
you  →  > ••••••••
bot  ←  ✓ nginx restarted · [exit 0]
Lock the gate before you leave
Remote shell is powerful. The shell respects FRIDAY's screen-lock PIN gate — lock it and ! is refused remotely until you /unlock <pin>. Treat your bot token like a key to your machine.

Documents & voice notes

Drop a supported file into the chat and FRIDAY downloads it, loads it into session RAG, and confirms — then any caption (or your next message) is answered against that document. Send a voice note and it's transcribed through the same local STT used for the wake-word path, then handled as a normal turn. No cloud transcription.

Approval gates

Sensitive workflows (security tooling, destructive actions) can request a yes/no round-trip. FRIDAY sends the question and blocks until you reply approve / deny / cancel (or natural equivalents like “yes”, “stop”). The reply is intercepted before routing, so a bare “yes” resolves the gate instead of becoming a new query.

Refuse-by-default
If the channel is offline when an approval is requested, the answer is deny — security workflows never run unattended. A 3-minute timeout also resolves to no-action.

Live chat UX

  • Typing indicator — the “FRIDAY is typing…” status stays alive while it works.
  • In-place answer — a 💭 placeholder bubble is edited into the final response, so you see it morph rather than getting a second message.
  • Auto-chunking — replies over Telegram's 4096-char limit are split on sentence boundaries.
  • Markdown → Telegram HTML — **bold**, *italic*, and `code` render natively.

Proactive notifications

Telegram and Discord aren't only inbound. FRIDAY pushes events to you when you're away — wired through the EventBus in modules/comms/plugin.py:

⏰ reminders
reminder_fired → a chat ping when a reminder is due
🌅 goal check-ins
morning check-in and evening review prompts
⚠️ goal at risk
a nudge when a tracked goal needs attention
🔔 triggers
automation triggers that opt in with notify_remote

Discord is outbound-only (a webhook URL — no bot account needed); Telegram is the full two-way channel.