What is Legio?
Legio is a One Man Company framework — a coordinated team of autonomous AI agents built on the Claude Agent SDK (Python), organized like a Roman legion under Caesar's command.
A solo operator gets the output of an entire team — research, writing, coding, analysis — orchestrated through natural language via Telegram, with persistent context that survives restarts.
The Chain of Command
| Role | Latin Term | What It Does |
|---|---|---|
| You | Caesar | The human operator. Commands the system via Telegram. |
| Orchestrator | Legatus | Routes messages, manages centuriones, responds when no specialist is needed. Holds its own Claude SDK session. |
| Specialist | Centurio (pl. centuriones) | A task-specific agent. Each has a prompt file, MCP tools, and private notes. Created on demand. |
When Caesar sends a message, the Legatus decides whether to respond directly or delegate to one or more centuriones based on @mentions. Centuriones work in parallel when multiple are addressed.
System Topology
How It Works
- Caesar sends a message in Telegram (free-form text or
/command) - Bot authenticates —
_caesar_filterverifies Telegram user ID + private chat - OTP interception — if a destructive action is pending, the message is checked as a TOTP code first
- Legatus parses
@mentionsand routes accordingly - If
@mentions→ dispatch to centuriones in parallel viaasyncio.gather() - If no
@mentions→ Legatus responds as the default voice using its own SDK session - All messages (inbound + responses) are persisted to the Praetorium (SQLite)
- Responses are rendered from markdown to Telegram HTML via mistune v3
- Long responses are split at paragraph boundaries (4000-char limit per Telegram message)
Core Principles
Prompt Over Code
If behavior can be achieved through prompting, don't hard-code it. Code handles infrastructure, data models, and orchestration plumbing. Everything else — routing logic, response style, domain rules — belongs in prompts and edicta (standing orders).
Roman Vocabulary
Domain concepts use Latin terms. This creates an unambiguous vocabulary that can't be confused with generic programming terms:
| Concept | Latin | Plural | Meaning |
|---|---|---|---|
| Message | Nuntius | Nuntii | Immutable frozen dataclass with UUID, sender, audience, timestamp |
| Message bus | Praetorium | — | SQLite-backed shared history with WAL mode and visibility rules |
| Memory | Memoria | — | Persistent filesystem storage (edicta, acta, commentarii) |
| Workspace | Castra | — | Runtime directory tree (prompts, data, configs) |
| Standing order | Edictum | Edicta | Global directive that all agents read before tasks |
| Shared knowledge | Actum | Acta | Published outputs available to all agents |
| Private notes | Commentarium | Commentarii | Per-centurio append-only journal |
| Authorization | Auctoritas | — | Pending TOTP request for destructive actions |
100% Test Coverage
Enforced via pytest --cov-fail-under=100. Every line of production code is tested. Security tests (@pytest.mark.security) run on every commit. Async tests use asyncio_mode = "strict".
Tech Stack
| Technology | Role |
|---|---|
| Python 3.11+ | Strict typing, X | None syntax, async/await throughout |
| Claude Agent SDK | Agent orchestration via ClaudeSDKClient, MCP tool hosting via create_sdk_mcp_server |
| python-telegram-bot | Caesar's interface — handlers, filters, ApplicationBuilder |
| aiosqlite | Praetorium message persistence with WAL mode and FOREIGN KEY constraints |
| mistune v3 | Markdown → Telegram HTML rendering with HTMLRenderer(escape=True) |
| pyotp | TOTP-based authorization for destructive actions (timing-safe via hmac.compare_digest) |
| ruff | 30 rule families for linting — no print, no os.path, no bare except, security/bandit checks |
Startup Flow
Project Stats
| Metric | Value |
|---|---|
| Pure production LOC | ~2,500 |
| Test LOC | ~4,000 |
| Test : Production ratio | 1.56 : 1 |
| Test coverage | 100% |
| Source modules | 16 files across 3 packages |
| Ruff rule families | 30 |
| Max file size | 350 pure code lines |