Skip to content

ToruAI/toris-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Toris Agent

License: MIT Python 3.11+

Claude Code as a personal agent. Runs on your Claude Pro/Max/Teams subscription. No API key needed.

In April 2026, Anthropic cut off subscription access for third-party wrappers like OpenClaw, forcing them onto pay-per-token API keys. Toris still runs on subscription because it drives the Claude Agent SDK directly — the same SDK that powers the claude CLI in your terminal. Paste your claude setup-token OAuth into /setup and start talking.

Voice in, voice out. Full agent tools: Bash, Read, Grep, WebSearch, Edit, Write. Sandboxed writes. Persistent sessions you can resume, switch, search, and compact. Tool approval, watch mode, pluggable MCP memory. Multi-persona.

Features

Feature Description
Voice in/out ElevenLabs or OpenAI — choose per-user via /settings
Agentic execution Claude Agent SDK with Bash, Read, Grep, WebSearch, Edit, Write
Sandboxed writes All writes and command execution confined to a sandbox directory
Session management /new, /continue, /sessions, /switch, /search, /compact
Approval modes "Go All" (auto) or "Approve" (confirm each tool call)
Watch mode Stream tool calls live to chat — Off / Live / Debug
Automations List & toggle scheduled tasks via /automations
Conversational setup /setup walks you through credentials + voice config in chat
Token verification Every credential is tested before it's saved
Multi-persona Run multiple AI personas from one codebase
Topic filtering Multiple personas in one Telegram group (forum topics)
Rate limiting 2s cooldown + 10/min per user
Admin-gated setup ALLOWED_USER_IDS + ADMIN_USER_IDS for multi-user chats

Architecture

Telegram (voice / text / photo)
        │
        ▼
┌──────────────────┐
│  python-telegram │
│       -bot       │
└────────┬─────────┘
         │
    ┌────┴────┐
    │   STT   │  ← ElevenLabs Scribe OR OpenAI Whisper (voice only)
    └────┬────┘
         ▼
┌──────────────────┐
│ Claude Agent SDK │  ← Bash, Read, Grep, WebSearch, Edit, Write
│  + tool approval │
│  + session mgmt  │
└────────┬─────────┘
         │
    ┌────┴────┐
    │   TTS   │  ← ElevenLabs OR OpenAI (if audio enabled)
    └────┬────┘
         ▼
     Telegram

Prerequisites

  • Telegram Bot — Create one via @BotFather
  • Voice provider (optional) — ElevenLabs or OpenAI API key. Can be configured later via /setup or skipped for text-only mode.
  • Claude access — API key or subscription OAuth token. Can be configured via /setup in Telegram.

For Docker deployment: Docker and Docker Compose. For non-Docker deployment: Python 3.11+ and Node.js 20+ (for the Claude Code CLI).

Claude Authentication

Choose ONE of these methods:

Method Best For How
API Key Docker, CI/CD, teams Paste sk-ant-api-... from console.anthropic.com via /setup, or set ANTHROPIC_API_KEY in env
Subscription OAuth Personal use, Pro/Max/Teams plans Run claude setup-token on any machine with a browser, paste the result via /setup, or set CLAUDE_CODE_OAUTH_TOKEN in env
Mounted credentials Docker with existing claude /login Mount ~/.claude/.credentials.json into the container (see docker-compose.yml)

Deployment Options

Option 1: Docker (Recommended for Production)

# Clone the repository
git clone --recurse-submodules https://github.com/toruai/toris-agent.git
cd toris-agent

# Configure
cp docker/toris.env.example docker/toris.env
# Edit docker/toris.env — you only need TELEGRAM_BOT_TOKEN to start.
# Everything else (Claude auth, voice provider) can be set via /setup in Telegram.

# Start
docker-compose up -d

# View logs
docker-compose logs -f toris

# Stop
docker-compose down

Benefits:

  • Isolated sandbox for file operations
  • Automatic restarts on failure
  • Persistent state across restarts (volumes)
  • No Python / Node installation on the host

Option 2: Non-Docker (systemd or foreground)

# Clone and setup
git clone --recurse-submodules https://github.com/toruai/toris-agent.git
cd toris-agent

python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Install Claude Code CLI
npm install -g @anthropic-ai/claude-code

# Configure — only TELEGRAM_BOT_TOKEN is needed to start
cp .env.example .env
# Edit .env with your bot token

# Run
python bot.py

See Systemd Deployment for a production unit file.


First-time setup via Telegram

After starting the bot for the first time, open your Telegram chat and run /setup. The bot walks you through a conversational onboarding:

  1. Name — how the bot should address you
  2. Claude auth — choose API Key or OAuth (Claude Pro/Max/Teams subscription)
    • API Key: paste your sk-ant-api-... from console.anthropic.com
    • OAuth: run claude setup-token on any machine with a browser, paste the result
  3. Voice provider — ElevenLabs, OpenAI, or skip (text-only)
  4. Verification — the bot tests every credential against the live API before saving

Your tokens are deleted from the Telegram chat immediately after being verified and stored. You can re-run /setup at any time, or use targeted commands: /claude_token, /elevenlabs_key, /openai_key.

If a message delete fails (missing Telegram permissions), the bot refuses to save the token and asks you to delete it manually — no token ever stays visible in chat.


Configuration

Required environment variables

Variable Description
TELEGRAM_BOT_TOKEN Bot token from @BotFather
TELEGRAM_DEFAULT_CHAT_ID Your Telegram chat ID (security: only this chat can use the bot; set to 0 during first setup, then lock it down)

Auth — configure one or more (or do it via /setup in Telegram)

Variable Purpose
ANTHROPIC_API_KEY Claude API access via API key
CLAUDE_CODE_OAUTH_TOKEN Claude via subscription OAuth (Pro/Max/Teams)
ELEVENLABS_API_KEY ElevenLabs voice provider
OPENAI_API_KEY OpenAI voice provider

Optional environment variables

Variable Default Description
TELEGRAM_ALLOWED_USER_IDS (empty) Comma-separated user IDs; empty = all users in chat allowed
TELEGRAM_ADMIN_USER_IDS (empty) Comma-separated admin IDs; empty = all authorized users are admins
TELEGRAM_TOPIC_ID (empty) Restrict bot to a specific Telegram forum topic
PERSONA_NAME Assistant Display name in logs / greetings
SYSTEM_PROMPT_FILE (default minimal) Path to a persona prompt file (e.g. prompts/toris.md)
TTS_PROVIDER auto-detect elevenlabs or openai
STT_PROVIDER auto-detect elevenlabs or openai
STT_LANGUAGE auto e.g. en, pl
ELEVENLABS_VOICE_ID JBFqnCBsd6RMkjVDRZzb (George) See ElevenLabs voice library
OPENAI_VOICE_ID coral OpenAI voices: alloy, ash, ballad, cedar, coral, echo, fable, juniper, marin, onyx, nova, sage, shimmer, verse
OPENAI_TTS_MODEL gpt-4o-mini-tts Or tts-1, tts-1-hd
OPENAI_STT_MODEL whisper-1 Or gpt-4o-mini-transcribe, gpt-4o-transcribe
MAX_VOICE_RESPONSE_CHARS 500 Truncate TTS input (controls cost)
CLAUDE_TIMEOUT 300 Max seconds to wait for a Claude response
CLAUDE_WORKING_DIR $HOME Directory Claude can read from
CLAUDE_SANDBOX_DIR $HOME/claude-sandbox Directory Claude can write to and execute in
LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR, CRITICAL

User Settings

Use /settings in Telegram to configure per-user preferences:

  • Mode — Go All (auto-approve tools) or Approve (confirm each tool call)
  • Watch — Off / Live (tool calls as they happen) / Debug (full SDK events)
  • Audio — voice responses on/off
  • Speed — voice playback speed (0.8x – 1.3x)
  • Automation cards — compact or full display style

Multi-Persona Setup

Run multiple AI personalities from the same codebase. Each gets its own:

  • Telegram bot
  • Voice and personality
  • Sandbox directory
  • Topic filter (for group chats)

Docker multi-persona

Duplicate the service in docker-compose.yml with different env files:

services:
  toris:
    env_file: docker/toris.env
    volumes:
      - toris-state:/home/claude/state
      - toris-sandbox:/home/claude/sandbox

  assistant2:
    env_file: docker/assistant2.env
    volumes:
      - assistant2-state:/home/claude/state
      - assistant2-sandbox:/home/claude/sandbox

Persona prompt

See prompts/toris.md for the default persona. Key elements:

# TORIS — Your Second Brain

You are TORIS, a voice-powered thinking partner built on Claude.

## Your Capabilities
- READ files from {read_dir}
- WRITE and EXECUTE in {sandbox_dir}
- Web search, research, note-taking

## CRITICAL — Voice Output Rules
- NO markdown formatting
- Speak in natural flowing sentences

Docker Deployment Guide

Building and running

# Build the image
docker-compose build

# Start
docker-compose up -d

# View logs
docker-compose logs -f toris

# Restart
docker-compose restart toris

# Stop
docker-compose down

# Stop and remove volumes (WARNING: deletes session history)
docker-compose down -v

Configuration

cp docker/toris.env.example docker/toris.env
# Edit docker/toris.env — you only need TELEGRAM_BOT_TOKEN to start.

See the Configuration section above for the full env var reference.

Credentials for subscription users

If you want to use an existing claude /login session from your host machine:

# In docker-compose.yml, uncomment:
- ~/.claude/.credentials.json:/home/claude/.claude/.credentials.json:ro

Data persistence

Volume Contents Location
toris-state Session history & user settings /home/claude/state
toris-sandbox File operations sandbox /home/claude/sandbox
toris-claude-config Claude credentials & settings /home/claude/.claude

Backup state:

docker cp claude-voice-toris:/home/claude/state ./backup-state

Health checks

docker-compose ps
docker-compose logs -f toris

Systemd Deployment

For non-Docker production deployments on Linux.

Setup

# Create deployment directory
sudo mkdir -p /opt/toris-agent
cd /opt/toris-agent

# Clone and install
sudo git clone --recurse-submodules https://github.com/toruai/toris-agent.git .
sudo python3 -m venv venv
sudo venv/bin/pip install -r requirements.txt

# Install Claude Code globally
sudo npm install -g @anthropic-ai/claude-code

# Create config
sudo mkdir -p /etc/toris-agent
sudo cp .env.example /etc/toris-agent/toris-agent.env
sudo $EDITOR /etc/toris-agent/toris-agent.env

Service file

Create /etc/systemd/system/toris-agent.service:

[Unit]
Description=Toris Agent — Claude voice bot for Telegram
After=network.target

[Service]
Type=simple
User=claude
Group=claude
WorkingDirectory=/opt/toris-agent
EnvironmentFile=/etc/toris-agent/toris-agent.env
ExecStart=/opt/toris-agent/venv/bin/python bot.py
Restart=always
RestartSec=10

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/toris-agent/sandbox /var/lib/toris-agent/state

[Install]
WantedBy=multi-user.target

Create user and directories

sudo useradd -r -s /bin/false claude
sudo mkdir -p /var/lib/toris-agent/{state,sandbox}
sudo chown -R claude:claude /var/lib/toris-agent
echo "CLAUDE_SANDBOX_DIR=/var/lib/toris-agent/sandbox" | sudo tee -a /etc/toris-agent/toris-agent.env
echo "STATE_DIR=/var/lib/toris-agent/state" | sudo tee -a /etc/toris-agent/toris-agent.env

Manage the service

sudo systemctl daemon-reload
sudo systemctl enable toris-agent
sudo systemctl start toris-agent

sudo systemctl status toris-agent
sudo journalctl -u toris-agent -f

Bot Commands

Command Description
/start Welcome / help
/setup Conversational credential setup
/health System & provider health check
/new [name] Start a new session
/continue Resume the last session
/sessions List recent sessions
/switch <id> Switch to a session by ID
/search <term> Search sessions by keyword
/cancel Cancel the current request
/compact Summarize & compress the current session
/status Current session info
/settings Voice, mode, speed, watch mode
/automations List & toggle scheduled automations

Security Considerations

  • Chat ID restriction — only the configured chat ID can interact with the bot
  • Per-user allowlistTELEGRAM_ALLOWED_USER_IDS restricts which users are authorized inside that chat
  • Admin gatingTELEGRAM_ADMIN_USER_IDS restricts /setup and credential commands
  • Anonymous denied — when an allowlist is configured, anonymous / channel posts are rejected
  • Sandbox isolation — Claude can only write / execute in the sandbox directory
  • Rate limiting — 2s cooldown + 10/min per user
  • Token hygiene — onboarding tokens are deleted from chat before saving; if delete fails, the bot refuses to save
  • No secrets in prompts — keep API keys in env / /setup, never in persona prompt files

Architecture

bot.py                 # Handler registration + startup
handlers/
  session.py           # /start /new /continue /sessions /switch /status /cancel /compact /search
  admin.py             # /setup /claude_token /elevenlabs_key /openai_key + settings callbacks
  messages.py          # voice / text / photo / onboarding / automations callbacks
auth.py                # Authorization, rate limiting, topic filtering
state_manager.py       # Thread-safe sessions + settings with atomic persistence
claude_service.py      # Claude Agent SDK wrapper + working indicator
voice_service.py       # TTS/STT with provider failover + health checks
automations.py         # RemoteTrigger integration
shared_state.py        # Cross-module pending approvals + cancel events
config.py              # Env var single source of truth
prompts/               # Persona prompt files
tests/                 # 170+ unit tests (uses asyncio.run, not pytest-asyncio)

Development

source venv/bin/activate
pip install -r requirements.txt

# Run tests
pytest tests/ -v

# With coverage
pytest tests/ --cov=. --cov-report=term-missing

See CONTRIBUTING.md for contribution guidelines and the test convention.

How It Works

Voice message arrives. STT transcribes it (ElevenLabs Scribe or OpenAI Whisper). The transcript goes to the Claude Agent SDK, which decides what tools to call and runs them. With watch mode on, tool calls stream into the chat live. With approve mode on, Claude waits for a ✓ before anything with side effects runs. The response comes back as text; TTS speaks it.

Usually a few seconds end to end. The SDK runs a full agent loop, not a chat-completion wrapper.

License

MIT. Built by ToruAI.

About

Voice-first, agentic Telegram interface to Claude. Not a chatbot wrapper — Claude reads files, searches the web, writes and runs code in a sandbox. ElevenLabs or OpenAI for voice.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors