Skip to content

Reese-max/openab

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

182 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenAB β€” Open Agent Broker

A lightweight, secure, cloud-native ACP harness that bridges Discord and any Agent Client Protocol-compatible coding CLI (Kiro CLI, Claude Code, Codex, Gemini, etc.) over stdio JSON-RPC β€” delivering the next-generation development experience.

πŸͺΌ Join our community! Come say hi on Discord β€” we'd love to have you: πŸͺΌ OpenAB β€” Official πŸŽ‰

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  Gateway WS   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  ACP stdio    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Discord    │◄─────────────►│ openab       │──────────────►│  coding CLI  β”‚
β”‚   User       β”‚               β”‚   (Rust)     │◄── JSON-RPC ──│  (acp mode)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Demo

openab demo

Features

  • Pluggable agent backend β€” swap between Kiro CLI, Claude Code, Codex, Gemini via config
  • @mention trigger β€” mention the bot in an allowed channel to start a conversation
  • Thread-based multi-turn β€” auto-creates threads; no @mention needed for follow-ups
  • Edit-streaming β€” live-updates the Discord message every 1.5s as tokens arrive
  • Emoji status reactions β€” πŸ‘€β†’πŸ€”β†’πŸ”₯/πŸ‘¨β€πŸ’»/βš‘β†’πŸ‘+random mood face
  • Session pool β€” one CLI process per thread, auto-managed lifecycle
  • ACP protocol β€” JSON-RPC over stdio with tool call, thinking, and permission auto-reply support
  • Kubernetes-ready β€” Dockerfile + k8s manifests with PVC for auth persistence
  • Voice message STT β€” auto-transcribes Discord voice messages via Groq, OpenAI, or local Whisper server (docs/stt.md)

Quick Start

1. Create a Discord Bot

See docs/discord-bot-howto.md for a detailed step-by-step guide.

In short:

  1. Go to https://discord.com/developers/applications and create an application
  2. Bot tab β†’ enable Message Content Intent
  3. OAuth2 β†’ URL Generator β†’ scopes: bot + applications.commands β†’ permissions: Send Messages, Send Messages in Threads, Create Public Threads, Read Message History, Add Reactions, Manage Messages
  4. Invite the bot to your server using the generated URL

Note: applications.commands scope is required for the /model slash command. If you previously invited the bot with only bot scope, re-invite it using the new URL β€” the bot account stays the same, no data is lost.

2. Configure

cp config.toml.example config.toml

Edit config.toml:

[discord]
bot_token = "${DISCORD_BOT_TOKEN}"
allowed_channels = ["YOUR_CHANNEL_ID"]
# allowed_users = ["YOUR_USER_ID"]  # optional: restrict who can use the bot

[agent]
command = "kiro-cli"
args = ["acp", "--trust-all-tools"]
working_dir = "/tmp"

3. Build & Run

export DISCORD_BOT_TOKEN="your-token"

# Development
cargo run

# Production
cargo build --release
./target/release/openab config.toml

If no config path is given, it defaults to config.toml in the current directory.

4. Use

In your Discord channel:

@AgentBroker explain this code

The bot creates a thread. After that, just type in the thread β€” no @mention needed.

Slash Commands

Command Description
/model Show the current model and list all available models
/model <model> Switch to a specific model. Supports aliases (auto, opus, sonnet, haiku) and full model ids β€” Discord's autocomplete shows the full list as you type.

The model picker uses Discord's native autocomplete: type /m and Discord will suggest /model; tab into the field and use ↑↓ to pick from the live list of available models reported by your agent backend.

Slash commands require the applications.commands OAuth scope (see Create a Discord Bot above). If /model does not appear in your Discord client, re-invite the bot with the correct scope.

Pluggable Agent Backends

Supports Kiro CLI, Claude Code, Codex, Gemini, and any ACP-compatible CLI.

Agent key CLI ACP Adapter Auth
kiro (default) Kiro CLI Native kiro-cli acp kiro-cli login --use-device-flow
codex Codex @zed-industries/codex-acp codex login --device-auth
claude Claude Code @agentclientprotocol/claude-agent-acp claude setup-token
gemini Gemini CLI Native gemini --acp Google OAuth or GEMINI_API_KEY

Helm Install (recommended)

See the Helm chart docs for full installation instructions, values reference, and multi-agent examples.

helm repo add openab https://openabdev.github.io/openab
helm repo update

# Kiro CLI only (default)
helm install openab openab/openab \
  --set agents.kiro.discord.botToken="$DISCORD_BOT_TOKEN" \
  --set-string 'agents.kiro.discord.allowedChannels[0]=YOUR_CHANNEL_ID'

# Claude Code only (disable default kiro)
helm install openab openab/openab \
  --set agents.kiro.enabled=false \
  --set agents.claude.discord.botToken="$DISCORD_BOT_TOKEN" \
  --set-string 'agents.claude.discord.allowedChannels[0]=YOUR_CHANNEL_ID' \
  --set agents.claude.image=ghcr.io/openabdev/openab-claude:latest \
  --set agents.claude.command=claude-agent-acp \
  --set agents.claude.workingDir=/home/node

# Multi-agent (kiro + claude in one release)
helm install openab openab/openab \
  --set agents.kiro.discord.botToken="$KIRO_BOT_TOKEN" \
  --set-string 'agents.kiro.discord.allowedChannels[0]=KIRO_CHANNEL_ID' \
  --set agents.claude.discord.botToken="$CLAUDE_BOT_TOKEN" \
  --set-string 'agents.claude.discord.allowedChannels[0]=CLAUDE_CHANNEL_ID' \
  --set agents.claude.image=ghcr.io/openabdev/openab-claude:latest \
  --set agents.claude.command=claude-agent-acp \
  --set agents.claude.workingDir=/home/node

Each agent key in agents map creates its own Deployment, ConfigMap, Secret, and PVC. Set agents.<name>.enabled: false to skip creating resources for an agent.

Manual config.toml

For non-Helm deployments, configure the [agent] block per CLI:

# Kiro CLI (default)
[agent]
command = "kiro-cli"
args = ["acp", "--trust-all-tools"]
working_dir = "/home/agent"

# Codex (requires codex-acp in PATH)
[agent]
command = "codex-acp"
args = []
working_dir = "/home/node"

# Claude Code (requires claude-agent-acp in PATH)
[agent]
command = "claude-agent-acp"
args = []
working_dir = "/home/node"

# Gemini
[agent]
command = "gemini"
args = ["--acp"]
working_dir = "/home/node"
env = { GEMINI_API_KEY = "${GEMINI_API_KEY}" }

Configuration Reference

[discord]
bot_token = "${DISCORD_BOT_TOKEN}"   # supports env var expansion
allowed_channels = ["123456789"]      # channel ID allowlist
# allowed_users = ["987654321"]       # user ID allowlist (empty = all users)

[agent]
command = "kiro-cli"                  # CLI command
args = ["acp", "--trust-all-tools"]   # ACP mode args
working_dir = "/tmp"                  # agent working directory
env = {}                              # extra env vars passed to the agent

[pool]
max_sessions = 10                     # max concurrent sessions
session_ttl_hours = 24                # idle session TTL

[reactions]
enabled = true                        # enable emoji status reactions
remove_after_reply = false            # remove reactions after reply

[reactions.emojis]
queued = "πŸ‘€"
thinking = "πŸ€”"
tool = "πŸ”₯"
coding = "πŸ‘¨β€πŸ’»"
web = "⚑"
done = "πŸ†—"
error = "😱"

[reactions.timing]
debounce_ms = 700                     # intermediate state debounce
stall_soft_ms = 10000                 # 10s idle β†’ πŸ₯±
stall_hard_ms = 30000                 # 30s idle β†’ 😨
done_hold_ms = 1500                   # keep done emoji for 1.5s
error_hold_ms = 2500                  # keep error emoji for 2.5s

Kubernetes Deployment

The Docker image bundles both openab and kiro-cli in a single container (openab spawns kiro-cli as a child process).

Pod Architecture

β”Œβ”€ Kubernetes Pod ─────────────────────────────────────────────────┐
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚  openab (main process, PID 1)                           β”‚     β”‚
β”‚  β”‚                                                         β”‚     β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚     β”‚
β”‚  β”‚  β”‚ Discord      β”‚   β”‚ Session Pool β”‚   β”‚ Reaction  β”‚    β”‚     β”‚
β”‚  β”‚  β”‚ Gateway WS   β”‚   β”‚ (per thread) β”‚   β”‚ Controllerβ”‚    β”‚     β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚     β”‚
β”‚  β”‚         β”‚                  β”‚                            β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚            β”‚                  β”‚                                  β”‚
β”‚            β”‚ @mention /       β”‚ spawn + stdio                    β”‚
β”‚            β”‚ thread msg       β”‚ JSON-RPC (ACP)                   β”‚
β”‚            β”‚                  β”‚                                  β”‚
β”‚            β–Ό                  β–Ό                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  kiro-cli acp --trust-all-tools  (child process)         β”‚    β”‚
β”‚  β”‚                                                          β”‚    β”‚
β”‚  β”‚  stdin  ◄── JSON-RPC requests  (session/new, prompt)     β”‚    β”‚
β”‚  β”‚  stdout ──► JSON-RPC responses (text, tool_call, done)   β”‚    β”‚
β”‚  β”‚  stderr ──► (ignored)                                    β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€ PVC Mount (/data) ──────────────────────────────────────┐    β”‚
β”‚  β”‚  ~/.kiro/              ← settings, skills, sessions      β”‚    β”‚
β”‚  β”‚  ~/.local/share/kiro-cli/ ← OAuth tokens (data.sqlite3)  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β”‚ WebSocket (wss://gateway.discord.gg)
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Discord API     β”‚ ◄─────► β”‚  Discord     β”‚
β”‚  Gateway         β”‚         β”‚  Users       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Single container β€” openab is PID 1, spawns kiro-cli as a child process
  • stdio JSON-RPC β€” ACP communication over stdin/stdout, no network ports needed
  • Session pool β€” one kiro-cli process per Discord thread, up to max_sessions
  • PVC β€” persists OAuth tokens and settings across pod restarts

Install with Your Coding CLI

See the Helm chart docs for per-agent install commands (Kiro CLI, Claude Code, Codex, Gemini) and values reference.

Build & Push

docker build -t openab:latest .
docker tag openab:latest <your-registry>/openab:latest
docker push <your-registry>/openab:latest

Deploy

# Create the secret with your bot token
kubectl create secret generic openab-secret \
  --from-literal=discord-bot-token="your-token"

# Edit k8s/configmap.yaml with your channel IDs
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/pvc.yaml
kubectl apply -f k8s/deployment.yaml

Authenticate kiro-cli (first time only)

kiro-cli requires a one-time OAuth login. The PVC persists the tokens across pod restarts.

kubectl exec -it deployment/openab-kiro -- kiro-cli login --use-device-flow

Follow the device code flow in your browser, then restart the pod:

kubectl rollout restart deployment/openab-kiro

Manifests

File Purpose
k8s/deployment.yaml Single-container pod with config + data volume mounts
k8s/configmap.yaml config.toml mounted at /etc/openab/
k8s/secret.yaml DISCORD_BOT_TOKEN injected as env var
k8s/pvc.yaml Persistent storage for auth + settings

The PVC persists two paths via subPath:

  • ~/.kiro β€” settings, skills, sessions
  • ~/.local/share/kiro-cli β€” OAuth tokens (data.sqlite3 β†’ auth_kv table), conversation history

Project Structure

β”œβ”€β”€ Dockerfile          # multi-stage: rust build + debian-slim runtime with kiro-cli
β”œβ”€β”€ config.toml.example # example config with all agent backends
β”œβ”€β”€ k8s/                # Kubernetes manifests
β”‚   β”œβ”€β”€ deployment.yaml
β”‚   β”œβ”€β”€ configmap.yaml
β”‚   β”œβ”€β”€ secret.yaml
β”‚   └── pvc.yaml
└── src/
    β”œβ”€β”€ main.rs         # entrypoint: tokio + serenity + cleanup + shutdown
    β”œβ”€β”€ config.rs       # TOML config + ${ENV_VAR} expansion
    β”œβ”€β”€ discord.rs      # Discord bot: mention, threads, edit-streaming
    β”œβ”€β”€ format.rs       # message splitting (2000 char limit)
    β”œβ”€β”€ reactions.rs    # status reaction controller (debounce, stall detection)
    └── acp/
        β”œβ”€β”€ protocol.rs # JSON-RPC types + ACP event classification
        β”œβ”€β”€ connection.rs # spawn CLI, stdio JSON-RPC communication
        └── pool.rs     # thread_id β†’ AcpConnection map

Inspired By

License

MIT

About

A lightweight, secure, cloud-native ACP harness that bridges Discord and any ACP-compatible coding CLI.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Rust 71.5%
  • JavaScript 21.8%
  • PowerShell 3.4%
  • Batchfile 2.0%
  • Go Template 0.7%
  • Dockerfile 0.5%
  • VBScript 0.1%