GitHunt
VB

vbrazo/voiceable

Multi-agent SDLC pipeline: voice/text → plan, design, implement, test, integrate — with approval gates and optional OpenClaw/Nanobot backends

Voiceable

Multi-agent SDLC orchestration with voice, GitHub, and human-in-the-loop approvals.

Send a voice note (or text) to your Telegram, WhatsApp, or Slack bot describing a feature. Voiceable breaks it down into 5 SDLC stages, writes code, opens a PR, runs tests, and merges — pausing for your approval at every step.


What It Does

  1. You send a message (text or voice): "Build a REST API for task management"
  2. Planner agent decomposes it into user stories, risks, and scope
  3. You approve (or request revisions) via inline buttons
  4. Designer produces architecture, components, and API contracts
  5. You approve
  6. Implementer writes the code and a GitHub PR draft
  7. GitHub branch is created, files pushed, PR opened
  8. You approve
  9. Tester writes pytest tests and estimates CI coverage
  10. Test results posted as a PR comment
  11. You approve
  12. Integrator reviews the full pipeline
  13. You tap Merge PR & Close Issue — done

Each approval message shows the agent's reasoning (Verbose Reasoning Transparency). If you tap "Request Revision", the bot asks what to change and re-runs the stage with your feedback.


Architecture

Current (in-process agents, VOICEABLE_AGENT_BACKEND=in_process)

Human (voice/text)
   │  Telegram / WhatsApp / Slack
   ▼
FastAPI Webhooks  (/webhooks/{platform})
   │
   ├─ VoiceService       → Whisper STT → text
   │                     ← OpenAI TTS ← voice note reply
   │
   ├─ ApprovalService    → handles button taps & revision replies
   │
   └─ PipelineService    → PipelineMachine (plans actions)
         │                     │
         │              Execute Actions:
         │                ├─ RunAgent(stage)
         │                ├─ SendApproval → channel.send_approval()
         │                ├─ CreateGitHubIssue
         │                ├─ PushFilesAndOpenPR
         │                └─ MergePRAndCloseIssue
         │
         └── SDLC Agents (spawned on demand, direct Anthropic API)
               ├─ PlannerAgent      (claude-opus-4-6)
               ├─ DesignerAgent     (claude-opus-4-6)
               ├─ ImplementerAgent  (claude-sonnet-4-6)
               ├─ TesterAgent       (claude-sonnet-4-6)
               └─ IntegratorAgent   (claude-haiku-4-5)

Optional Backend: OpenClaw (VOICEABLE_AGENT_BACKEND=openclaw)

Human (voice/text)
   │  Telegram / WhatsApp / Slack
   ▼
OpenClaw Gateway  (channels, bindings, routing)
   │
   └─ OpenClaw Agent ──► POST /api/pipelines        (start run)
                    ──► POST /api/pipelines/{id}/approve  (approval)
                    ──► POST /api/pipelines/{id}/revision (revision)
                    ◄── PipelineRunResponse          (data + message_text)
                    │
                    └─ OpenClaw sends messages/approval UI to user

Voiceable (backend API — FSM, run state, GitHub)
   └─ PipelineService → PipelineMachine
         │                ├─ OpenClawAdapter  ──► OpenClaw Gateway ──► LLM
         │                ├─ CreateGitHubIssue
         │                ├─ PushFilesAndOpenPR
         │                └─ MergePRAndCloseIssue
         └─ SQLite (PipelineRun state)

Channel webhook handling, approval button flows, and voice I/O move into OpenClaw
(Phases 2–4 of the migration). Set VOICEABLE_AGENT_BACKEND=openclaw to route
agent execution through OpenClaw while keeping channels in-process during the transition.

Optional Backend: Nanobot (VOICEABLE_AGENT_BACKEND=nanobot)

Human (voice/text)
   │  Telegram / WhatsApp / Slack
   ▼
FastAPI Webhooks  (/webhooks/{platform})
   │
   └─ PipelineService → PipelineMachine
         │                ├─ NanobotAdapter  ──► nanobot-ai LiteLLMProvider
         │                │                     ├─ OpenRouter
         │                │                     ├─ Anthropic
         │                │                     ├─ OpenAI
         │                │                     └─ ... (DeepSeek, Gemini, etc.)
         │                ├─ CreateGitHubIssue
         │                ├─ PushFilesAndOpenPR
         │                └─ MergePRAndCloseIssue
         └─ SQLite (PipelineRun state)

Pipeline FSM

                  CREATED
                    │
                  PLANNING
                    │
          AWAITING_PLAN_APPROVAL
                    │ approved
    DESIGNING → AWAITING_DESIGN_APPROVAL
                    │ approved
IMPLEMENTING → AWAITING_IMPL_APPROVAL
                    │ approved
      TESTING → AWAITING_TEST_APPROVAL
                    │ approved
    INTEGRATING → AWAITING_INTEGRATION_APPROVAL
                    │ approved
                COMPLETED

Any AWAITING_* → REJECTED (reject button)
Any AWAITING_* → re-runs same stage (revision button + feedback text)

Key Design Patterns (from agentic-patterns.com)

Pattern Where Applied
Plan-Then-Execute PipelineMachine returns Action list; PipelineService executes
Discrete Phase Separation Typed Pydantic contracts between every stage
Human-in-the-Loop Approval Framework Approval buttons before each stage transition
Planner-Worker Separation Machine plans, agents execute
Sub-Agent Spawning PipelineService._get_agent() instantiates agents on demand
Verbose Reasoning Transparency reasoning_trace field shown in every approval message
Specification-Driven Development DesignerOutput is the contract ImplementerAgent must satisfy
Coding Agent CI Feedback Loop TesterAgent reads GitHub Actions check statuses

Project Structure

app/
├── main.py                   # FastAPI app + lifespan
├── config.py                 # All settings (pydantic-settings)
├── database.py               # SQLite persistence (aiosqlite)
│
├── llm/                      # LLM abstraction layer
│   ├── base.py               # LLMProvider ABC
│   ├── factory.py            # get_llm(), get_planning_llm()
│   ├── anthropic_provider.py
│   ├── prompt_builder.py     # Centralised (system, user) prompt construction
│   └── prompts/              # System prompts per agent
│
├── models/
│   ├── pipeline.py           # PipelineRun, PipelineStage enum
│   ├── contracts.py          # Stage handoff Pydantic models
│   └── github.py             # GitHub response models
│
├── pipeline/
│   ├── states.py             # FSM transition matrix
│   ├── machine.py            # PipelineMachine + Action dataclasses
│   └── agents/
│       ├── base.py           # BaseAgent ABC
│       ├── openclaw_adapter.py  # OpenClaw drop-in (agent_backend=openclaw)
│       ├── nanobot_adapter.py   # Nanobot drop-in (agent_backend=nanobot)
│       └── planner/designer/implementer/tester/integrator.py
│
├── channels/                 # Platform-agnostic channel abstraction
│   ├── base.py               # ChannelProvider ABC + ChannelUpdate
│   ├── telegram.py           # Bot API + inline keyboards
│   ├── whatsapp.py           # Meta Cloud API + interactive buttons
│   └── slack.py              # Slack Web API + Block Kit
│
├── voice/
│   ├── stt.py                # OpenAI Whisper (transcription)
│   └── tts.py                # OpenAI TTS + MP3→OGG conversion
│
├── integrations/
│   ├── github/
│   │   ├── client.py         # GitHub REST API client (httpx)
│   │   └── operations.py     # High-level ops: create_issue, open_pr, merge
│   ├── openclaw/
│   │   └── client.py         # OpenClaw Gateway client wrapper
│   └── nanobot/
│       └── client.py         # nanobot-ai provider wrapper
│
├── services/
│   ├── pipeline_service.py   # Main orchestrator
│   ├── approval_service.py   # Human-in-loop handler
│   └── voice_service.py      # STT → pipeline → TTS
│
└── api/
    ├── webhooks.py           # POST /webhooks/{telegram,whatsapp,slack}
    ├── admin.py              # POST /pipelines (HTTP trigger, auth required)
    ├── pipeline_api.py       # POST /api/pipelines (OpenClaw-facing routes, auth required)
    └── health.py             # GET /health

Use Cases

  • Solo developer: Send voice notes describing features while commuting; approve PRs from your phone
  • Small team: Automate boilerplate SDLC stages while humans focus on architecture decisions
  • Rapid prototyping: Turn feature ideas into scaffolded code + tests + PRs in minutes
  • Code review assistant: Each stage produces structured output reviewable via messaging apps

Setup

1. Prerequisites

  • Python 3.12+
  • uv (pip install uv)
  • ffmpeg (for voice note conversion): brew install ffmpeg
  • A public HTTPS URL for webhooks (use ngrok for local dev)

2. Clone & Install

cd /path/to/voiceable
uv sync

3. Configure Environment

cp .env.example .env

Fill in .env:

# Required for SDLC agents
ANTHROPIC_API_KEY=sk-ant-...

# Required for voice (STT + TTS)
OPENAI_API_KEY=sk-...

# Required for GitHub operations
GITHUB_TOKEN=ghp_...
GITHUB_DEFAULT_OWNER=your-org
GITHUB_DEFAULT_REPO=your-repo

# Required for at least one messaging platform (see below)
TELEGRAM_BOT_TOKEN=...

# Your public URL (ngrok or production)
APP_BASE_URL=https://abc123.ngrok.io
  1. Message @BotFather on Telegram → /newbot
  2. Copy the token → TELEGRAM_BOT_TOKEN in .env
  3. Set TELEGRAM_WEBHOOK_SECRET to any random string
  4. Telegram webhook is auto-registered on startup

5. Set Up WhatsApp (optional)

  1. Create a Meta Developer App with WhatsApp product
  2. Add WHATSAPP_TOKEN, WHATSAPP_PHONE_NUMBER_ID, WHATSAPP_VERIFY_TOKEN
  3. Register webhook URL: https://your-url/webhooks/whatsapp
  4. Subscribe to messages events

6. Set Up Slack (optional)

  1. Create a Slack App with a bot token
  2. Enable Event Subscriptions: message.channelshttps://your-url/webhooks/slack
  3. Enable Interactivity: request URL → https://your-url/webhooks/slack
  4. Add SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET

7. GitHub Token

Create a GitHub PAT with scopes:

  • repo (full control)
  • workflow (for reading CI check statuses)

8. OpenClaw Setup (optional — for agent execution via OpenClaw)

Skip this section if you are using in-process agents (VOICEABLE_AGENT_BACKEND=in_process, the default).

a. Install and run the OpenClaw Gateway

Follow the OpenClaw documentation to install and start the Gateway.
The Gateway should listen on ws://127.0.0.1:18789/gateway by default.

b. Define five agents in your Gateway config

Configure these agent IDs with their model assignments:

Agent ID Model SDLC Stage
planner anthropic/claude-opus-4-6 Planning
designer anthropic/claude-opus-4-6 Design
implementer anthropic/claude-sonnet-4-6 Implementation
tester anthropic/claude-sonnet-4-6 Testing
integrator anthropic/claude-haiku-4-5-20251001 Integration

Agents can have minimal system text (e.g. "Return valid JSON") or none — the full prompt
including the JSON schema constraint is sent by Voiceable each call.

c. Set env vars and enable

VOICEABLE_AGENT_BACKEND=openclaw
OPENCLAW_GATEWAY_WS_URL=ws://127.0.0.1:18789/gateway
VOICEABLE_API_KEY=your-secret-key   # OpenClaw agents send this as X-Voiceable-Api-Key

d. Add openclaw-sdk to dependencies

Uncomment the openclaw-sdk line in pyproject.toml (pin the exact version you need),
then run uv sync.

Rollback: Set VOICEABLE_AGENT_BACKEND=in_process to revert to in-process agents instantly.
In-progress runs resume on the in-process path — no DB migration needed.

9. Nanobot Setup (optional — for agent execution via nanobot-ai providers)

Skip this section if you are using in-process agents (VOICEABLE_AGENT_BACKEND=in_process).

a. Add nanobot-ai to dependencies

Uncomment the nanobot-ai line in pyproject.toml, then run uv sync.

b. Set env vars and enable

VOICEABLE_AGENT_BACKEND=nanobot
NANOBOT_PROVIDER=openrouter
NANOBOT_API_KEY=sk-or-...
NANOBOT_API_BASE=              # optional; set for custom gateways
NANOBOT_MODEL=anthropic/claude-sonnet-4-6
NANOBOT_TIMEOUT=300

NANOBOT_PROVIDER should be a valid nanobot provider key (for example:
openrouter, anthropic, openai, deepseek, gemini, or vllm).

10. Run

# Development (with auto-reload)
uv run uvicorn app.main:app --reload --port 8000

# In another terminal, start ngrok
ngrok http 8000
# Copy the https URL → APP_BASE_URL in .env, restart server

API Reference

Start a pipeline via HTTP (admin — requires VOICEABLE_API_KEY)

curl -X POST http://localhost:8000/pipelines \
  -H "Content-Type: application/json" \
  -H "X-Voiceable-Api-Key: your-secret-key" \
  -d '{
    "goal": "Build a health check endpoint that returns uptime and version",
    "platform": "telegram",
    "chat_id": "YOUR_TELEGRAM_CHAT_ID",
    "repo_owner": "your-org",
    "repo_name": "your-repo"
  }'

OpenClaw-facing API (requires VOICEABLE_API_KEY)

# Start a run (returns immediately; pipeline runs in background)
curl -X POST http://localhost:8000/api/pipelines \
  -H "X-Voiceable-Api-Key: your-secret-key" \
  -H "Content-Type: application/json" \
  -d '{"goal": "...", "platform": "telegram", "chat_id": "123"}'

# Poll run state
curl http://localhost:8000/api/pipelines/{run_id} \
  -H "X-Voiceable-Api-Key: your-secret-key"

# Approve current stage
curl -X POST http://localhost:8000/api/pipelines/{run_id}/approve \
  -H "X-Voiceable-Api-Key: your-secret-key"

# Submit revision
curl -X POST http://localhost:8000/api/pipelines/{run_id}/revision \
  -H "X-Voiceable-Api-Key: your-secret-key" \
  -H "Content-Type: application/json" \
  -d '{"revision_notes": "Add error handling for edge cases"}'

Health check

curl http://localhost:8000/health

Voice Usage

Sending a voice message:

  1. Open Telegram/WhatsApp/Slack
  2. Record a voice note describing the feature
  3. Send it to the bot
  4. The bot transcribes it and confirms: "Transcribed: Build a health check endpoint"
  5. The pipeline starts automatically
  6. Each approval message is also sent as a voice note summary

Text also works — send any text message as a feature request.


Running Tests

uv run python -m pytest tests/ -v

19 tests covering FSM states, agent logic, Telegram parsing, and STT.


Environment Variables Reference

Variable Required Description
ANTHROPIC_API_KEY Yes Claude API key (in-process agents)
OPENAI_API_KEY Yes Whisper STT + TTS
GITHUB_TOKEN Yes PAT with repo+workflow
GITHUB_DEFAULT_OWNER Yes Default GitHub org/user
GITHUB_DEFAULT_REPO Yes Default GitHub repo
APP_BASE_URL Yes Public HTTPS URL for webhooks
VOICEABLE_API_KEY Recommended Auth key for /pipelines and /api/pipelines routes
TELEGRAM_BOT_TOKEN For Telegram From @Botfather
TELEGRAM_WEBHOOK_SECRET For Telegram Random secret string
WHATSAPP_TOKEN For WhatsApp Meta access token
WHATSAPP_PHONE_NUMBER_ID For WhatsApp Meta phone number ID
WHATSAPP_VERIFY_TOKEN For WhatsApp Webhook verify token
SLACK_BOT_TOKEN For Slack xoxb-... bot token
SLACK_SIGNING_SECRET For Slack App signing secret
TTS_VOICE No Voice for TTS (default: nova)
PLANNING_MODEL No Override planner model
IMPLEMENTATION_MODEL No Override implementer model
VOICEABLE_AGENT_BACKEND No in_process (default), openclaw, or nanobot
OPENCLAW_GATEWAY_WS_URL For OpenClaw Gateway WebSocket URL
OPENCLAW_API_KEY For OpenClaw Optional Gateway auth token
OPENCLAW_TIMEOUT No Seconds per agent call (default: 300)
NANOBOT_PROVIDER For Nanobot Provider key (e.g. openrouter, anthropic)
NANOBOT_API_KEY For Nanobot API key used by selected Nanobot provider
NANOBOT_API_BASE No Optional provider base URL override
NANOBOT_MODEL No Optional model override for all stages
NANOBOT_TIMEOUT No Seconds per Nanobot call (default: 300)

Tech Stack

Component Technology
Web framework FastAPI + uvicorn
LLM (in-process) Anthropic Claude (opus-4-6, sonnet-4-6, haiku-4-5)
LLM (OpenClaw) openclaw-sdk → OpenClaw Gateway → any model
LLM (Nanobot) nanobot-ai LiteLLMProvider → OpenRouter/Anthropic/OpenAI/etc
STT OpenAI Whisper (whisper-1)
TTS OpenAI TTS (tts-1)
Audio conversion ffmpeg via subprocess
Database SQLite via aiosqlite
HTTP client httpx (async)
Config pydantic-settings
GitHub REST API v3 (httpx)
Messaging Telegram Bot API, Meta Cloud API, Slack Web API
Tests pytest + pytest-asyncio

vbrazo/voiceable | GitHunt