yeoman is a lightweight, multi-channel AI assistant runtime with deterministic policy control, long-term memory, voice I/O, and tool sandboxing.
Originally inspired by HKUDS/nanobot. MIT license preserved.
| Policy engine | Deterministic per-channel, per-chat access control with hot-reload — no ad-hoc ACLs |
| Multi-channel | Telegram, WhatsApp (Baileys bridge), Discord, Feishu — unified pipeline |
| Memory | SQLite-backed semantic + FTS recall with session context and background notes |
| Voice | STT via Groq Whisper, TTS via ElevenLabs / OpenRouter — bidirectional voice in WhatsApp |
| Tools & skills | Sandboxed execution (bubblewrap), extensible skill system (OpenClaw-compatible) |
| 11 LLM providers | OpenRouter, Anthropic, OpenAI, DeepSeek, Gemini, Groq, DashScope, Moonshot, Zhipu, AiHubMix, local vLLM — via LiteLLM |
Channel → Bus (inbound) → 13-stage Middleware Pipeline → OrchestratorIntent[]
01 Normalize → 02 Dedup → 03 Archive → 04 Context → 05 Admin
→ 06 Policy → 07 Idea Capture → 08 Access Control → 09 New Chat
→ 10 No-Reply → 11 Security → 12 LLM Response → 13 Outbound
Intent dispatch → Bus (outbound/reaction) → Channel → User
Hexagonal / ports-and-adapters. core/ports.py defines interfaces (PolicyPort, ResponderPort, ReplyArchivePort, SecurityPort, TelemetryPort); adapters implement them. The pipeline emits typed OrchestratorIntent objects; channels react asynchronously. Media (ASR/TTS/vision) is cross-cutting — channels enrich inbound, the responder synthesizes outbound.
# Developer mode: source checkout + pinned repo venv
git clone https://github.com/dimitree2k/yeoman.git
cd yeoman
uv sync
./bin/yeoman --version
# User mode: installed CLI outside a source checkout
uv tool install yeoman
yeoman --version
# Or:
pip install yeoman
yeoman --versionRule of thumb:
- If you are inside the yeoman git checkout, use
./bin/yeoman - If you installed yeoman as a tool or package, use
yeoman - Avoid
python3 -m yeoman.cli.commandsunlessyeoman envshows thatpython3is the same interpreter backing the active launcher
Check the active runtime any time:
yeoman env
# or, in the repo checkout:
./bin/yeoman env1. Initialize
yeoman onboardIf you are working from the source checkout, run the same commands with ./bin/yeoman instead.
2. Add API keys — pick any method:
| Method | Location | Notes |
|---|---|---|
.env file |
~/.yeoman/.env |
Recommended. yeoman config migrate-to-env can generate it |
| Environment variables | Shell / systemd | OPENROUTER_API_KEY, ANTHROPIC_API_KEY, etc. |
| Config file | ~/.yeoman/config.json |
Works but .env is preferred for secrets |
# Example: set model in config, key in .env
echo 'OPENROUTER_API_KEY=sk-or-v1-xxx' >> ~/.yeoman/.env{
"agents": {
"defaults": { "model": "anthropic/claude-opus-4-5" }
}
}3. Chat
yeoman agent -m "Hello!"Tip
For local models, point providers.vllm.apiBase at any OpenAI-compatible server (vLLM, Ollama, etc).
All channels are configured in ~/.yeoman/config.json and access-controlled via ~/.yeoman/policy.json.
| Channel | Complexity | Notes |
|---|---|---|
| Telegram | Easy | Bot token from @BotFather |
| Discord | Easy | Bot token + MESSAGE CONTENT intent |
| Medium | QR link via yeoman channels login (Node.js ≥18) |
|
| Feishu | Medium | WebSocket — no public IP needed |
Start all enabled channels:
yeoman gatewayChannel setup details
{ "channels": { "telegram": { "enabled": true, "token": "YOUR_BOT_TOKEN" } } }{ "channels": { "discord": { "enabled": true, "token": "YOUR_BOT_TOKEN" } } }Invite with scopes: bot · Permissions: Send Messages, Read Message History.
yeoman channels login # scan QR
yeoman gateway # start{ "channels": { "whatsapp": { "enabled": true } } }Supports voice (STT + TTS), bridge lifecycle management (yeoman channels bridge start|stop|restart|status), and media persistence.
pip install yeoman[feishu]{
"channels": {
"feishu": { "enabled": true, "appId": "cli_xxx", "appSecret": "xxx" }
}
}~/.yeoman/policy.json controls four dimensions per channel and chat:
| Dimension | Modes |
|---|---|
| Who can talk | everyone · allowlist · owner_only |
| When to reply | all · off · mention_only · allowed_senders · owner_only |
| Allowed tools | all · allowlist (with deny overrides) |
| Persona | Per-chat persona file selection |
Merge precedence: defaults → channels.<ch>.default → channels.<ch>.chats.<id>
Policy is hot-reloaded — no restart needed. Debug with:
yeoman policy explain --channel telegram --chat -1001234567890 --sender "12345|User"Owner response controls (WhatsApp owner only):
/stop # pause current chat until /start
/stop all # pause every chat until /start all
/start # resume current chat
/start all # resume all chats
/pause 30min # pause current chat for a duration
/pause all 1h # pause all chats for a duration
Supported pause units: s, min, h, d (for example 45s, 15min, 2h, 1d).
| Provider | Type | |
|---|---|---|
| OpenRouter | LLM gateway | openrouter.ai |
| AiHubMix | LLM gateway | aihubmix.com |
| Anthropic | LLM (Claude) | console.anthropic.com |
| OpenAI | LLM (GPT) | platform.openai.com |
| DeepSeek | LLM | platform.deepseek.com |
| Gemini | LLM | aistudio.google.com |
| Groq | LLM + STT (Whisper) | console.groq.com |
| DashScope | LLM (Qwen) | dashscope.console.aliyun.com |
| Moonshot | LLM (Kimi) | platform.moonshot.cn |
| Zhipu AI | LLM (GLM) | open.bigmodel.cn |
| vLLM | Local LLM | Any OpenAI-compatible server |
Adding a new provider requires only 2 changes: a ProviderSpec in providers/registry.py and a config field in config/schema.py.
| Feature | Description |
|---|---|
| Policy engine | Deterministic access control — no ad-hoc ACLs |
| Workspace restriction | tools.restrictToWorkspace: true sandboxes all file/exec tools |
| Exec isolation | Linux bubblewrap sandboxing with per-session containers |
| Scoped file grants | Explicit path grants with blocked paths/patterns override |
| I/O validation | Three-stage security middleware: input → tool → output checks with sensitive data redaction |
The overseer is an autonomous orchestration layer that runs alongside the gateway. It executes runbooks — declarative maintenance scripts that monitor health, clean up resources, prune memory, audit policy, and sample response quality.
yeoman overseer start # start the service
yeoman overseer status # check PID, heartbeat, budget
yeoman overseer runbooks # list loaded runbooks
yeoman logs # tail all logs (gateway + bridge + overseer)Runbooks are Markdown files with YAML frontmatter. Two modes:
- Deterministic — check a condition, send an alert. No LLM, no cost.
- LLM-escalated — spin up a Claude agent with scoped tools and a token budget, sandboxed via bubblewrap.
Safety is layered: circuit breakers, rate limits (30 actions/hr, 20 LLM calls/day), budget caps (500K tokens/day), cooldowns, lock management, and network-isolated sandboxing.
12 starter runbooks ship out of the box (health checks, log rotation, memory pruning, policy audit, and more). See packages/overseer/README.md for full documentation.
For persistent operation:
yeoman overseer install-units
systemctl --user daemon-reload
systemctl --user enable --now yeoman-overseerIf yeoman includes the bundled agent-doctor skill, you can run a local health check for memory,
cron, config, workspace files, gateway/bridge, security posture, and system prerequisites.
Ask the agent:
diagnose yeoman
run a health check
check what is broken
Or run it directly:
yeoman doctorIf runtime behavior seems inconsistent, inspect the active launcher and Python first:
yeoman envUse it:
- right after onboarding
- after editing
config.json,.env, orpolicy.json - after runtime/dependency upgrades
- when memory, gateway, WhatsApp, or cron behavior seems off
Exit codes:
0no problems found1warnings or critical issues found
The doctor does not auto-fix anything; it reports findings and proposed fixes first.
| Command | Description |
|---|---|
yeoman onboard |
Initialize config & workspace |
yeoman agent -m "..." |
Single-shot chat |
yeoman agent |
Interactive chat |
yeoman gateway |
Start all enabled channels |
yeoman status |
Runtime status |
yeoman env |
Show active launcher and Python environment |
yeoman doctor |
Run health checks and report issues |
yeoman logs |
View gateway/bridge/overseer logs |
| Channels | |
yeoman channels login |
Link WhatsApp (scan QR) |
yeoman channels status |
Show channel status |
yeoman channels bridge start|stop|restart|status |
Manage WhatsApp bridge |
| Policy | |
yeoman policy path |
Show policy file location |
yeoman policy explain |
Debug policy decisions for a chat/sender |
yeoman policy cmd "/policy ..." |
Run policy commands from CLI |
yeoman policy annotate-whatsapp-comments |
Auto-fill WhatsApp group names in policy |
| Memory | |
yeoman memory status |
Memory backend info and counters |
yeoman memory search --query "..." |
Search long-term memory |
yeoman memory add --text "..." |
Insert manual memory entry |
yeoman memory prune |
Retention cleanup |
yeoman memory reindex |
Rebuild FTS index |
yeoman memory notes status|set |
Per-chat background notes config |
| Config | |
yeoman config migrate-to-env |
Move secrets from config.json to .env |
| Overseer | |
yeoman overseer start [--foreground] |
Start the overseer service |
yeoman overseer stop |
Stop the overseer service |
yeoman overseer status |
PID, heartbeat, budget snapshot |
yeoman overseer runbooks |
List loaded runbooks |
yeoman overseer install-units |
Install systemd user units |
| Cron | |
yeoman cron list|add|remove|enable|run |
Manage scheduled tasks |
yeoman cron add-voice |
Schedule voice broadcast jobs |
docker build -t yeoman .
docker run -v ~/.yeoman:/root/.yeoman -p 18790:18790 yeoman gatewaypackages/
├── gateway/ Main gateway service
│ └── yeoman_gateway/
│ ├── agent/ Core agent loop, prompt builder, skills, tools
│ ├── core/ Orchestrator pipeline, ports, intents, models
│ ├── adapters/ Port implementations (policy, LLM, archive, telemetry)
│ ├── channels/ Telegram, WhatsApp, Discord, Feishu
│ ├── providers/ LLM registry, LiteLLM wrapper, transcription
│ ├── policy/ Engine, schema, identity normalization, personas
│ ├── memory/ SQLite store, embeddings, extractor, sessions
│ ├── media/ ASR, TTS, vision, routing
│ ├── security/ Rule engine, bubblewrap isolation
│ ├── skills/ Bundled skills (github, weather, cron, tmux...)
│ └── cli/ typer commands
├── overseer/ Autonomous orchestration layer
│ └── yeoman_overseer/
│ ├── agent/ LLM agent loop, budget tracker, tool dispatch
│ ├── runbook/ Schema, parser, starter runbooks
│ ├── trigger/ Evaluator, health checks (poll/cron/event)
│ ├── safety/ Circuit breaker, rate limiter
│ ├── audit/ JSONL logger, internal git
│ ├── comms/ Cascading alerts (Telegram, SMTP)
│ └── systemd/ Service unit files
├── shared/ Shared config schema, utilities
└── bridge/ WhatsApp bridge (TypeScript / Baileys)
See CHANGELOG.md for full release history.
MIT License · Originally inspired by HKUDS/nanobot
