Skip to content

openabdev/openab

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

61 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.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  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

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 β†’ scope: bot β†’ 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

2. Configure

cp config.toml.example config.toml

Edit config.toml:

[discord]
bot_token = "${DISCORD_BOT_TOKEN}"
allowed_channels = ["YOUR_CHANNEL_ID"]

[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.

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
helm install openab openab/openab \
  --set agents.kiro.discord.botToken="$DISCORD_BOT_TOKEN" \
  --set-string 'agents.kiro.discord.allowedChannels[0]=YOUR_CHANNEL_ID'

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/agent"

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

# Gemini
[agent]
command = "gemini"
args = ["--acp"]
working_dir = "/home/agent"
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

[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