File: README.md
OpenFang
The Agent Operating System
v0.5.10 (April 2026)
OpenFang is feature complete but still pre-1.0. Expect rough edges and breaking changes between minor versions. We ship fast and fix fast. Pin to a specific commit for production use until v1.0. Report issues here.
What is OpenFang?
OpenFang is an open-source Agent Operating System. Not a chatbot framework. Not a Python wrapper around an LLM. Not a "multi-agent orchestrator." A full operating system for autonomous agents, built from scratch in Rust.
Traditional agent frameworks wait for you to type something. OpenFang runs autonomous agents that work for you: on schedules, 24/7, building knowledge graphs, monitoring targets, generating leads, managing your social media, and reporting results to your dashboard.
The entire system compiles to a single ~32MB binary. One install, one command, your agents are live.
curl -fsSL https://openfang.sh/install | sh
openfang init
openfang start
# Dashboard live at http://localhost:4200Windows
irm https://openfang.sh/install.ps1 | iex
openfang init
openfang startHands: Agents That Actually Do Things
Hands are OpenFang's core innovation. Pre-built autonomous capability packages that run independently, on schedules, without you having to prompt them. This is not a chatbot. This is an agent that wakes up at 6 AM, researches your competitors, builds a knowledge graph, scores the findings, and delivers a report to your Telegram before you've had coffee.
Each Hand bundles:
- HAND.toml: manifest declaring tools, settings, requirements, and dashboard metrics.
- System Prompt: multi-phase operational playbook. Not a one-liner. These are 500+ word expert procedures.
- SKILL.md: domain expertise reference injected into context at runtime.
- Guardrails: approval gates for sensitive actions (e.g. Browser Hand requires approval before any purchase).
All compiled into the binary. No downloading, no pip install, no Docker pull.
The 7 Bundled Hands
| Hand | What It Actually Does |
|---|---|
| Clip | Takes a YouTube URL, downloads it, identifies the best moments, cuts them into vertical shorts with captions and thumbnails, optionally adds AI voice-over, and publishes to Telegram and WhatsApp. 8-phase pipeline. FFmpeg + yt-dlp + 5 STT backends. |
| Lead | Runs daily. Discovers prospects matching your ICP, enriches them with web research, scores 0-100, deduplicates against your existing database, and delivers qualified leads in CSV/JSON/Markdown. Builds ICP profiles over time. |
| Collector | OSINT grade intelligence. You give it a target (company, person, topic). It monitors continuously: change detection, sentiment tracking, knowledge graph construction, and critical alerts when something important shifts. |
| Predictor | Superforecasting engine. Collects signals from multiple sources, builds calibrated reasoning chains, makes predictions with confidence intervals, and tracks its own accuracy using Brier scores. Has a contrarian mode that deliberately argues against consensus. |
| Researcher | Deep autonomous researcher. Cross-references multiple sources, evaluates credibility using CRAAP criteria (Currency, Relevance, Authority, Accuracy, Purpose), generates cited reports with APA formatting, supports multiple languages. |
| Autonomous Twitter/X account manager. Creates content in 7 rotating formats, schedules posts for optimal engagement, responds to mentions, tracks performance metrics. Has an approval queue, so nothing posts without your OK. | |
| Browser | Web automation agent. Navigates sites, fills forms, clicks buttons, handles multi-step workflows. Uses Playwright bridge with session persistence. Mandatory purchase approval gate: it will never spend your money without explicit confirmation. |
# Activate the Researcher Hand. It starts working immediately.
openfang hand activate researcher
# Check its progress anytime
openfang hand status researcher
# Activate lead generation on a daily schedule
openfang hand activate lead
# Pause without losing state
openfang hand pause lead
# See all available Hands
openfang hand listBuild your own. Define a HAND.toml with tools, settings, and a system prompt. Publish to FangHub.
OpenFang vs The Landscape
Benchmarks: Measured, Not Marketed
All data from official documentation and public repositories, February 2026.
Cold Start Time (lower is better)
ZeroClaw ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 10 ms
OpenFang ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 180 ms ★
LangGraph █████████████████░░░░░░░░░░░░░░░░░░░░░░░░░ 2.5 sec
CrewAI ████████████████████░░░░░░░░░░░░░░░░░░░░░░ 3.0 sec
AutoGen ██████████████████████████░░░░░░░░░░░░░░░░░ 4.0 sec
OpenClaw █████████████████████████████████████████░░ 5.98 secIdle Memory Usage (lower is better)
ZeroClaw █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5 MB
OpenFang ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 40 MB ★
LangGraph ██████████████████░░░░░░░░░░░░░░░░░░░░░░░░░ 180 MB
CrewAI ████████████████████░░░░░░░░░░░░░░░░░░░░░░░ 200 MB
AutoGen █████████████████████████░░░░░░░░░░░░░░░░░░ 250 MB
OpenClaw ████████████████████████████████████████░░░░ 394 MBInstall Size (lower is better)
ZeroClaw █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 8.8 MB
OpenFang ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 32 MB ★
CrewAI ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 100 MB
LangGraph ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 150 MB
AutoGen ████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░ 200 MB
OpenClaw ████████████████████████████████████████░░░░ 500 MBSecurity Systems (higher is better)
OpenFang ████████████████████████████████████████████ 16 ★
ZeroClaw ███████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 6
OpenClaw ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 3
AutoGen █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2
LangGraph █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2
CrewAI ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1Channel Adapters (higher is better)
OpenFang ████████████████████████████████████████████ 40 ★
ZeroClaw ███████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 15
OpenClaw █████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 13
CrewAI ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0
AutoGen ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0
LangGraph ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0LLM Providers (higher is better)
ZeroClaw ████████████████████████████████████████████ 28
OpenFang ██████████████████████████████████████████░░ 27 ★
LangGraph ██████████████████████░░░░░░░░░░░░░░░░░░░░░ 15
CrewAI ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 10
OpenClaw ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 10
AutoGen ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 8Feature-by-Feature Comparison
| Feature | OpenFang | OpenClaw | ZeroClaw | CrewAI | AutoGen | LangGraph |
|---|---|---|---|---|---|---|
| Language | Rust | TypeScript | Rust | Python | Python | Python |
| Autonomous Hands | 7 built-in | None | None | None | None | None |
| Security Layers | 16 discrete | 3 basic | 6 layers | 1 basic | Docker | AES enc. |
| Agent Sandbox | WASM dual-metered | None | Allowlists | None | Docker | None |
| Channel Adapters | 40 | 13 | 15 | 0 | 0 | 0 |
| Built-in Tools | 53 + MCP + A2A | 50+ | 12 | Plugins | MCP | LC tools |
| Memory | SQLite + vector | File-based | SQLite FTS5 | 4-layer | External | Checkpoints |
| Desktop App | Tauri 2.0 | None | None | None | Studio | None |
| Audit Trail | Merkle hash-chain | Logs | Logs | Tracing | Logs | Checkpoints |
| Cold Start | <200ms | ~6s | ~10ms | ~3s | ~4s | ~2.5s |
| Install Size | ~32 MB | ~500 MB | ~8.8 MB | ~100 MB | ~200 MB | ~150 MB |
| License | MIT | MIT | MIT | MIT | Apache 2.0 | MIT |
16 Security Systems: Defense in Depth
OpenFang doesn't bolt security on after the fact. Every layer is independently testable and operates without a single point of failure.
| # | System | What It Does |
|---|---|---|
| 1 | WASM Dual-Metered Sandbox | Tool code runs in WebAssembly with fuel metering + epoch interruption. A watchdog thread kills runaway code. |
| 2 | Merkle Hash-Chain Audit Trail | Every action is cryptographically linked to the previous one. Tamper with one entry and the entire chain breaks. |
| 3 | Information Flow Taint Tracking | Labels propagate through execution. Secrets are tracked from source to sink. |
| 4 | Ed25519 Signed Agent Manifests | Every agent identity and capability set is cryptographically signed. |
| 5 | SSRF Protection | Blocks private IPs, cloud metadata endpoints, and DNS rebinding attacks. |
| 6 | Secret Zeroization | Zeroizing<String> auto-wipes API keys from memory the instant they're no longer needed. |
| 7 | OFP Mutual Authentication | HMAC-SHA256 nonce-based, constant-time verification for P2P networking. |
| 8 | Capability Gates | Role based access control. Agents declare required tools, the kernel enforces it. |
| 9 | Security Headers | CSP, X-Frame-Options, HSTS, X-Content-Type-Options on every response. |
| 10 | Health Endpoint Redaction | Public health check returns minimal info. Full diagnostics require authentication. |
| 11 | Subprocess Sandbox | env_clear() + selective variable passthrough. Process tree isolation with cross-platform kill. |
| 12 | Prompt Injection Scanner | Detects override attempts, data exfiltration patterns, and shell reference injection in skills. |
| 13 | Loop Guard | SHA256-based tool call loop detection with circuit breaker. Handles ping-pong patterns. |
| 14 | Session Repair | 7-phase message history validation and automatic recovery from corruption. |
| 15 | Path Traversal Prevention | Canonicalization with symlink escape prevention. ../ doesn't work here. |
| 16 | GCRA Rate Limiter | Cost-aware token bucket rate limiting with per-IP tracking and stale cleanup. |
Architecture
14 Rust crates. 137,728 lines of code. Modular kernel design.
openfang-kernel Orchestration, workflows, metering, RBAC, scheduler, budget tracking
openfang-runtime Agent loop, 3 LLM drivers, 53 tools, WASM sandbox, MCP, A2A
openfang-api 140+ REST/WS/SSE endpoints, OpenAI-compatible API, dashboard
openfang-channels 40 messaging adapters with rate limiting, DM/group policies
openfang-memory SQLite persistence, vector embeddings, canonical sessions, compaction
openfang-types Core types, taint tracking, Ed25519 manifest signing, model catalog
openfang-skills 60 bundled skills, SKILL.md parser, FangHub marketplace
openfang-hands 7 autonomous Hands, HAND.toml parser, lifecycle management
openfang-extensions 25 MCP templates, AES-256-GCM credential vault, OAuth2 PKCE
openfang-wire OFP P2P protocol with HMAC-SHA256 mutual authentication
openfang-cli CLI with daemon management, TUI dashboard, MCP server mode
openfang-desktop Tauri 2.0 native app (system tray, notifications, global shortcuts)
openfang-migrate OpenClaw, LangChain, AutoGPT migration engine
xtask Build automation40 Channel Adapters
Connect your agents to every platform your users are on.
Core: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email (IMAP/SMTP)
Enterprise: Microsoft Teams, Mattermost, Google Chat, Webex, Feishu/Lark, Zulip
Social: LINE, Viber, Facebook Messenger, Mastodon, Bluesky, Reddit, LinkedIn, Twitch
Community: IRC, XMPP, Guilded, Revolt, Keybase, Discourse, Gitter
Privacy: Threema, Nostr, Mumble, Nextcloud Talk, Rocket.Chat, Ntfy, Gotify
Workplace: Pumble, Flock, Twist, DingTalk, Zalo, Webhooks
Each adapter supports per-channel model overrides, DM/group policies, rate limiting, and output formatting.
WhatsApp Web Gateway (QR Code)
Connect your personal WhatsApp account to OpenFang via QR code, just like WhatsApp Web. No Meta Business account required.
Prerequisites
- Node.js >= 18 installed (download)
- OpenFang installed and initialized
Setup
1. Install the gateway dependencies:
cd packages/whatsapp-gateway
npm install2. Configure config.toml:
[channels.whatsapp]
mode = "web"
default_agent = "assistant"3. Set the gateway URL (choose one):
Add to your shell profile for persistence:
# macOS / Linux
echo 'export WHATSAPP_WEB_GATEWAY_URL="http://127.0.0.1:3009"' >> ~/.zshrc
source ~/.zshrcOr set it inline when starting the gateway:
export WHATSAPP_WEB_GATEWAY_URL="http://127.0.0.1:3009"4. Start the gateway:
node packages/whatsapp-gateway/index.jsThe gateway listens on port 3009 by default. Override with WHATSAPP_GATEWAY_PORT.
5. Start OpenFang:
openfang start
# Dashboard at http://localhost:42006. Scan the QR code:
Open the dashboard → Channels → WhatsApp. A QR code will appear. Scan it with your phone:
WhatsApp → Settings → Linked Devices → Link a Device
Once scanned, the status changes to connected and incoming messages are routed to your configured agent.
Gateway Environment Variables
| Variable | Description | Default |
|---|---|---|
WHATSAPP_WEB_GATEWAY_URL |
Gateway URL for OpenFang to connect to | (empty = disabled) |
WHATSAPP_GATEWAY_PORT |
Port the gateway listens on | 3009 |
OPENFANG_URL |
OpenFang API URL the gateway reports to | http://127.0.0.1:4200 |
OPENFANG_DEFAULT_AGENT |
Agent that handles incoming messages | assistant |
Gateway API Endpoints
| Method | Route | Description |
|---|---|---|
POST |
/login/start |
Generate QR code (returns base64 PNG) |
GET |
/login/status |
Connection status (disconnected, qr_ready, connected) |
POST |
/message/send |
Send a message ({ "to": "5511999999999", "text": "Hello" }) |
GET |
/health |
Health check |
Alternative: WhatsApp Cloud API
For production workloads, use the WhatsApp Cloud API with a Meta Business account. See the Cloud API configuration docs.
27 LLM Providers, 123+ Models
3 native drivers (Anthropic, Gemini, OpenAI-compatible) route to 27 providers:
Anthropic, Gemini, OpenAI, Groq, DeepSeek, OpenRouter, Together, Mistral, Fireworks, Cohere, Perplexity, xAI, AI21, Cerebras, SambaNova, HuggingFace, Replicate, Ollama, vLLM, LM Studio, Qwen, MiniMax, Zhipu, Moonshot, Qianfan, Bedrock, and more.
Intelligent routing with task complexity scoring, automatic fallback, cost tracking, and per-model pricing.
Migrate from OpenClaw
Already running OpenClaw? One command:
# Migrate everything: agents, memory, skills, configs.
openfang migrate --from openclaw
# Migrate from a specific path
openfang migrate --from openclaw --path ~/.openclaw
# Dry run first to see what would change
openfang migrate --from openclaw --dry-runThe migration engine imports your agents, conversation history, skills, and configuration. OpenFang reads SKILL.md natively and is compatible with the ClawHub marketplace.
OpenAI-Compatible API
Drop-in replacement. Point your existing tools at OpenFang:
curl -X POST localhost:4200/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "researcher",
"messages": [{"role": "user", "content": "Analyze Q4 market trends"}],
"stream": true
}'140+ REST/WS/SSE endpoints covering agents, memory, workflows, channels, models, skills, A2A, Hands, and more.
Quick Start
# 1. Install (macOS/Linux)
curl -fsSL https://openfang.sh/install | sh
# 2. Initialize. Walks you through provider setup.
openfang init
# 3. Start the daemon
openfang start
# 4. Dashboard is live at http://localhost:4200
# 5. Activate a Hand. It starts working for you.
openfang hand activate researcher
# 6. Chat with an agent
openfang chat researcher
> "What are the emerging trends in AI agent frameworks?"
# 7. Spawn a pre-built agent
openfang agent spawn coderWindows (PowerShell)
irm https://openfang.sh/install.ps1 | iex
openfang init
openfang startDevelopment
# Build the workspace
cargo build --workspace --lib
# Run all tests (1,767+)
cargo test --workspace
# Lint (must be 0 warnings)
cargo clippy --workspace --all-targets -- -D warnings
# Format
cargo fmt --all -- --checkStability Notice
OpenFang v0.5.10 is pre-1.0. The architecture is solid, the test suite is comprehensive, and the security model is deep. That said:
- Breaking changes may occur between minor versions until v1.0.
- Some Hands are more mature than others. Browser and Researcher are the most battle tested.
- Edge cases exist. If you find one, open an issue.
- Pin to a specific commit for production deployments until v1.0.
We ship fast and fix fast. The goal is a rock solid v1.0 by mid 2026.
Security
To report a security vulnerability, email [email protected]. We take all reports seriously and will respond within 48 hours.
License
MIT. Use it however you want.
Links
Built by RightNow
File: docs/agent-templates.md
Agent Templates Catalog
OpenFang ships with 30 pre-built agent templates organized into 4 performance tiers. Each template is a ready-to-spawn agent.toml manifest located in the agents/ directory. Templates cover software engineering, business operations, personal productivity, and everyday tasks.
Quick Start
Spawn any template from the CLI:
openfang spawn orchestrator
openfang spawn coder
openfang spawn --template agents/writer/agent.tomlSpawn via the REST API:
# Spawn from a built-in template name
curl -X POST http://localhost:4200/api/agents \
-H "Content-Type: application/json" \
-d '{"template": "coder"}'
# Spawn with overrides
curl -X POST http://localhost:4200/api/agents \
-H "Content-Type: application/json" \
-d '{"template": "writer", "model": "gemini-2.5-flash"}'Send a message to a running agent:
curl -X POST http://localhost:4200/api/agents/{id}/message \
-H "Content-Type: application/json" \
-d '{"content": "Write unit tests for the auth module"}'Template Tiers
Templates are organized into 4 tiers based on task complexity and the LLM models they use. Higher tiers use more capable (and more expensive) models for tasks that require deep reasoning.
Tier 1 -- Frontier (DeepSeek)
For tasks requiring the deepest reasoning: multi-agent orchestration, system architecture, and security analysis.
| Template | Provider | Model |
|---|---|---|
| orchestrator | deepseek | deepseek-chat |
| architect | deepseek | deepseek-chat |
| security-auditor | deepseek | deepseek-chat |
All Tier 1 agents fall back to groq/llama-3.3-70b-versatile if the DeepSeek API key is unavailable.
Tier 2 -- Smart (Gemini 2.5 Flash)
For tasks requiring strong analytical and coding abilities: software engineering, data science, research, testing, and legal review.
| Template | Provider | Model |
|---|---|---|
| coder | gemini | gemini-2.5-flash |
| code-reviewer | gemini | gemini-2.5-flash |
| data-scientist | gemini | gemini-2.5-flash |
| debugger | gemini | gemini-2.5-flash |
| researcher | gemini | gemini-2.5-flash |
| analyst | gemini | gemini-2.5-flash |
| test-engineer | gemini | gemini-2.5-flash |
| legal-assistant | gemini | gemini-2.5-flash |
All Tier 2 agents fall back to groq/llama-3.3-70b-versatile if the Gemini API key is unavailable.
Tier 3 -- Balanced (Groq + Gemini Fallback)
For everyday business and productivity tasks: planning, writing, email, customer support, sales, recruiting, and meetings.
| Template | Provider | Model | Fallback |
|---|---|---|---|
| planner | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| writer | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| doc-writer | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| devops-lead | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| assistant | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| email-assistant | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| social-media | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| customer-support | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| sales-assistant | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| recruiter | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
| meeting-assistant | groq | llama-3.3-70b-versatile | gemini/gemini-2.0-flash |
Tier 4 -- Fast (Groq Only)
For lightweight, high-speed tasks: ops monitoring, translation, tutoring, wellness tracking, budgeting, travel, and home automation. No fallback model configured (except ops which uses a smaller 8B model for speed).
| Template | Provider | Model |
|---|---|---|
| ops | groq | llama-3.1-8b-instant |
| hello-world | groq | llama-3.3-70b-versatile |
| translator | groq | llama-3.3-70b-versatile |
| tutor | groq | llama-3.3-70b-versatile |
| health-tracker | groq | llama-3.3-70b-versatile |
| personal-finance | groq | llama-3.3-70b-versatile |
| travel-planner | groq | llama-3.3-70b-versatile |
| home-automation | groq | llama-3.3-70b-versatile |
Template Catalog
orchestrator
Tier 1 -- Frontier | deepseek/deepseek-chat | Fallback: groq/llama-3.3-70b-versatile
Meta-agent that decomposes complex tasks, delegates to specialist agents, and synthesizes results.
The orchestrator is the command center of the agent fleet. It analyzes user requests, breaks them into subtasks, uses agent_list to discover available specialists, delegates work via agent_send, spawns new agents when needed, and synthesizes all responses into a coherent final answer. It explains its delegation strategy before executing and avoids delegating trivially simple tasks.
- Tags: none
- Temperature: 0.3
- Max tokens: 8192
- Token quota: 500,000/hour
- Schedule: Continuous check every 120 seconds
- Tools:
agent_send,agent_spawn,agent_list,agent_kill,memory_store,memory_recall,file_read,file_write - Capabilities:
agent_spawn = true,agent_message = ["*"],memory_read = ["*"],memory_write = ["*"]
openfang spawn orchestrator
# "Plan and execute a full security audit of the codebase"architect
Tier 1 -- Frontier | deepseek/deepseek-chat | Fallback: groq/llama-3.3-70b-versatile
System architect. Designs software architectures, evaluates trade-offs, creates technical specifications.
Designs systems following principles of separation of concerns, performance-aware design, simplicity over cleverness, and designing for change without over-engineering. Clarifies requirements, identifies key components, defines interfaces and data flow, evaluates trade-offs (latency, throughput, complexity, maintainability), and documents decisions with rationale. Outputs use clear headings, ASCII diagrams, and structured reasoning.
- Tags:
architecture,design,planning - Temperature: 0.3
- Max tokens: 8192
- Token quota: 200,000/hour
- Tools:
file_read,file_list,memory_store,memory_recall,agent_send - Capabilities:
agent_message = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn architect
# "Design a microservices architecture for the payment processing system"security-auditor
Tier 1 -- Frontier | deepseek/deepseek-chat | Fallback: groq/llama-3.3-70b-versatile
Security specialist. Reviews code for vulnerabilities, checks configurations, performs threat modeling.
Focuses on OWASP Top 10, input validation, auth flaws, cryptographic misuse, injection attacks (SQL, command, XSS, SSTI), insecure deserialization, secrets management, dependency vulnerabilities, race conditions, and privilege escalation. Maps the attack surface, traces data flow from untrusted inputs, checks trust boundaries, reviews error handling, and assesses cryptographic implementations. Reports findings with severity levels (CRITICAL/HIGH/MEDIUM/LOW/INFO) in the format: Finding, Impact, Evidence, Remediation.
- Tags:
security,audit,vulnerability - Temperature: 0.2
- Max tokens: 4096
- Token quota: 150,000/hour
- Schedule: Proactive on
event:agent_spawned,event:agent_terminated - Tools:
file_read,file_list,shell_exec,memory_store,memory_recall - Shell access:
cargo audit *,cargo tree *,git log * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn security-auditor
# "Audit the authentication module for vulnerabilities"coder
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Expert software engineer. Reads, writes, and analyzes code.
Writes clean, production-quality code with a step-by-step reasoning approach. Reads files first to understand context, then makes precise changes. Always writes tests for produced code. Supports Rust, Python, JavaScript, and other languages.
- Tags:
coding,implementation,rust,python - Temperature: 0.3
- Max tokens: 8192
- Token quota: 200,000/hour
- Max concurrent tools: 10
- Tools:
file_read,file_write,file_list,shell_exec - Shell access:
cargo *,rustc *,git *,npm *,python * - Capabilities:
memory_read = ["*"],memory_write = ["self.*"]
openfang spawn coder
# "Implement a rate limiter using the token bucket algorithm in Rust"code-reviewer
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Senior code reviewer. Reviews PRs, identifies issues, suggests improvements with production standards.
Reviews code by priority: correctness, security, performance, maintainability, style. Groups feedback by file with severity tags: [MUST FIX], [SHOULD FIX], [NIT], [PRAISE]. Explains WHY, not just WHAT. Suggests specific code for proposed changes. Acknowledges good code, avoids bikeshedding on style when formatters exist.
- Tags:
review,code-quality,best-practices - Temperature: 0.3
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_list,shell_exec,memory_store,memory_recall - Shell access:
cargo clippy *,cargo fmt *,git diff *,git log * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn code-reviewer
# "Review the changes in the last 3 commits for production readiness"data-scientist
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Data scientist. Analyzes datasets, builds models, creates visualizations, performs statistical analysis.
Follows a structured methodology: understand the question, explore data (shape, distributions, missing values), analyze with appropriate statistical methods, build predictive models when needed, and communicate findings clearly. Toolkit includes descriptive stats, hypothesis testing (t-test, chi-squared, ANOVA), correlation/regression, time series, clustering, dimensionality reduction, and A/B test design.
- Tags: none
- Temperature: 0.3
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_write,file_list,shell_exec,memory_store,memory_recall - Shell access:
python * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn data-scientist
# "Analyze this CSV dataset and identify the top 3 factors correlated with churn"debugger
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Expert debugger. Traces bugs, analyzes stack traces, performs root cause analysis.
Follows a strict methodology: reproduce, isolate (binary search through code/data), identify root cause (not just symptoms), fix (minimal correct fix), verify (regression tests). Looks for common patterns: off-by-one, null/None, race conditions, resource leaks. Checks error handling paths and recent changes. Presents findings as Bug Report, Root Cause, Fix, Prevention.
- Tags: none
- Temperature: 0.2
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_list,shell_exec,memory_store,memory_recall - Shell access:
cargo *,git log *,git diff *,git show * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn debugger
# "The API returns 500 on POST /api/agents when the name contains unicode -- find the root cause"researcher
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Research agent. Fetches web content and synthesizes information.
Fetches web pages, reads documents, and synthesizes findings into clear, structured reports. Always cites sources, separates facts from analysis, and flags uncertainty. Breaks research tasks into sub-questions and investigates each systematically.
- Tags:
research,analysis,web - Temperature: 0.5
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
web_fetch,file_read,file_write,file_list - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn researcher
# "Research the current state of WebAssembly component model and summarize the key proposals"analyst
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Data analyst. Processes data, generates insights, creates reports.
Analyzes data, finds patterns, generates insights, and creates structured reports. Shows methodology, uses numbers and evidence to support conclusions. Reads files first to understand data structure, then presents findings with summary, key metrics, detailed analysis, and recommendations.
- Tags: none
- Temperature: 0.4
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_write,file_list,shell_exec - Shell access:
python *,cargo * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn analyst
# "Analyze the server access logs and report traffic patterns by hour and endpoint"test-engineer
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Quality assurance engineer. Designs test strategies, writes tests, validates correctness.
Tests document behavior, not implementation. Prefers fast, deterministic tests. Designs unit tests, integration tests, property-based tests, edge case tests, and regression tests. Follows the Arrange-Act-Assert pattern with descriptive test names (test_X_when_Y_should_Z). Reviews test coverage to identify untested paths and missing edge cases.
- Tags:
testing,qa,validation - Temperature: 0.3
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_write,file_list,shell_exec,memory_store,memory_recall - Shell access:
cargo test *,cargo check * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn test-engineer
# "Write comprehensive tests for the rate limiter module covering edge cases"legal-assistant
Tier 2 -- Smart | gemini/gemini-2.5-flash | Fallback: groq/llama-3.3-70b-versatile
Legal assistant for contract review, legal research, compliance checking, and document drafting.
Systematically reviews contracts covering parties, termination provisions, payment terms, indemnification, IP provisions, confidentiality, governing law, and force majeure. Drafts NDAs, service agreements, terms of service, privacy policies, and employment agreements. Checks compliance against GDPR, SOC 2, HIPAA, PCI DSS, CCPA/CPRA, ADA, and OSHA. Always includes a disclaimer that output does not constitute legal advice.
- Tags:
legal,contracts,compliance,research,review,documents - Temperature: 0.2
- Max tokens: 8192
- Token quota: 200,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn legal-assistant
# "Review this NDA and flag any one-sided or problematic clauses"planner
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Project planner. Creates project plans, breaks down epics, estimates effort, identifies risks and dependencies.
Follows a structured methodology: scope (in/out), decompose (epics to stories to tasks), sequence (dependencies and critical path), estimate (S/M/L/XL with rationale), risk (technical and schedule), milestones (with acceptance criteria). Estimates ranges (best/likely/worst), tackles riskiest parts first, and builds in 20-30% buffer for unknowns.
- Tags: none
- Temperature: 0.3
- Max tokens: 8192
- Token quota: 200,000/hour
- Tools:
file_read,file_list,memory_store,memory_recall,agent_send - Capabilities:
agent_message = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn planner
# "Create a project plan for migrating our monolith to microservices over 6 months"writer
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Content writer. Creates documentation, articles, and technical writing.
Excels at documentation, technical writing, blog posts, and clear communication. Writes concisely with active voice, structures content with headers and bullet points. Reads existing files for context and writes output to files when asked.
- Tags: none
- Temperature: 0.7
- Max tokens: 4096
- Token quota: 100,000/hour
- Tools:
file_read,file_write,file_list - Capabilities:
memory_read = ["*"],memory_write = ["self.*"]
openfang spawn writer
# "Write a blog post about the benefits of agent-based architectures"doc-writer
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Technical writer. Creates documentation, README files, API docs, tutorials, and architecture guides.
Writes for the reader: starts with WHY, then WHAT, then HOW. Uses progressive disclosure (overview to details). Creates READMEs, API docs, architecture docs, tutorials, reference docs, and Architecture Decision Records (ADRs). Uses active voice, short sentences, and includes code examples for every non-trivial concept.
- Tags: none
- Temperature: 0.4
- Max tokens: 8192
- Token quota: 200,000/hour
- Tools:
file_read,file_write,file_list,memory_store,memory_recall - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn doc-writer
# "Write API documentation for all the /api/agents endpoints"devops-lead
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
DevOps lead. Manages CI/CD, infrastructure, deployments, monitoring, and incident response.
Covers CI/CD pipeline design, container orchestration (Docker, Kubernetes), Infrastructure as Code (Terraform, Pulumi), monitoring and observability (Prometheus, Grafana, OpenTelemetry), incident response, security hardening, and capacity planning. Designs pipelines with fast feedback loops, immutable artifacts, and automated rollback.
- Tags: none
- Temperature: 0.2
- Max tokens: 4096
- Token quota: 150,000/hour
- Tools:
file_read,file_write,file_list,shell_exec,memory_store,memory_recall,agent_send - Shell access:
docker *,git *,cargo *,kubectl * - Capabilities:
agent_message = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn devops-lead
# "Design a CI/CD pipeline for our Rust workspace with staging and production environments"assistant
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
General-purpose assistant. The default OpenFang agent for everyday tasks, questions, and conversations.
The versatile default agent covering conversational intelligence, task execution, research and synthesis, writing and communication, problem solving, agent delegation (routes specialized tasks to the right specialist), knowledge management, and creative brainstorming. Acts as the user's trusted first point of contact -- handles most tasks directly and delegates to specialists when they would do better.
- Tags:
general,assistant,default,multipurpose,conversation,productivity - Temperature: 0.5
- Max tokens: 8192
- Token quota: 300,000/hour
- Max concurrent tools: 10
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch,shell_exec,agent_send,agent_list - Shell access:
python *,cargo *,git *,npm * - Capabilities:
network = ["*"],agent_message = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn assistant
# "Help me plan my week and draft replies to these three emails"email-assistant
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Email triage, drafting, scheduling, and inbox management agent.
Rapidly triages incoming email by urgency, category, and required action. Drafts professional emails adapted to recipient and situation. Manages email-based scheduling and follow-up obligations. Recognizes recurring email patterns and generates reusable templates. Produces concise digests for long threads and high-volume inboxes.
- Tags:
email,communication,triage,drafting,scheduling,productivity - Temperature: 0.4
- Max tokens: 8192
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn email-assistant
# "Triage these 15 emails and draft responses for the urgent ones"social-media
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Social media content creation, scheduling, and engagement strategy agent.
Crafts platform-optimized content for Twitter/X, LinkedIn, Instagram, Facebook, TikTok, Reddit, Mastodon, Bluesky, and Threads. Plans content calendars, designs engagement strategies, analyzes engagement data, defines brand voice guidelines, and optimizes hashtags and SEO. Adapts tone from professional thought leadership to casual and punchy depending on platform.
- Tags:
social-media,content,marketing,engagement,scheduling,analytics - Temperature: 0.7
- Max tokens: 4096
- Token quota: 120,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn social-media
# "Create a week of LinkedIn posts about our open-source launch"customer-support
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Customer support agent for ticket handling, issue resolution, and customer communication.
Triages support tickets by category, severity, product area, and customer tier. Follows systematic troubleshooting workflows for issue diagnosis. Writes empathetic, solution-oriented customer responses. Manages knowledge base content and escalation handoffs. Monitors customer sentiment and generates support metrics summaries.
- Tags:
support,customer-service,tickets,helpdesk,communication,resolution - Temperature: 0.3
- Max tokens: 4096
- Token quota: 200,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn customer-support
# "Triage this batch of support tickets and draft responses for the top 5 urgent ones"sales-assistant
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Sales assistant for CRM updates, outreach drafting, pipeline management, and deal tracking.
Drafts personalized cold outreach emails using the AIDA framework. Manages CRM data with structured updates. Analyzes sales pipelines with weighted values, at-risk deals, and conversion rates. Prepares pre-call briefs with prospect research. Builds competitive battle cards and performs win/loss analysis.
- Tags:
sales,crm,outreach,pipeline,prospecting,deals - Temperature: 0.5
- Max tokens: 4096
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn sales-assistant
# "Draft a 3-touch outreach sequence for CTOs at mid-market SaaS companies"recruiter
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Recruiting agent for resume screening, candidate outreach, job description writing, and hiring pipeline management.
Evaluates resumes against job requirements with structured match scoring. Writes inclusive, searchable job descriptions. Drafts personalized candidate outreach sequences. Prepares structured interview guides with STAR-format behavioral questions. Tracks candidates through hiring pipeline stages and generates reports. Actively supports inclusive hiring practices.
- Tags:
recruiting,hiring,resume,outreach,talent,hr - Temperature: 0.4
- Max tokens: 4096
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn recruiter
# "Screen these 10 resumes against the senior backend engineer job requirements"meeting-assistant
Tier 3 -- Balanced | groq/llama-3.3-70b-versatile | Fallback: gemini/gemini-2.0-flash
Meeting notes, action items, agenda preparation, and follow-up tracking agent.
Creates structured, time-boxed agendas. Transforms raw meeting notes or transcripts into clean, structured minutes with executive summaries, key discussion points, decisions, and action items. Extracts every commitment with owner, deadline, and priority. Drafts follow-up emails and schedules reminders. Synthesizes across multiple related meetings to identify themes and gaps.
- Tags:
meetings,notes,action-items,agenda,follow-up,productivity - Temperature: 0.3
- Max tokens: 8192
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn meeting-assistant
# "Process this meeting transcript and extract all action items with owners and deadlines"ops
Tier 4 -- Fast | groq/llama-3.1-8b-instant | No fallback
DevOps agent. Monitors systems, runs diagnostics, manages deployments.
Monitors system health, runs diagnostics, and helps with deployments. Precise and cautious -- explains what a command does before running it. Prefers read-only operations unless explicitly asked to make changes. Reports in structured format: status, details, recommended action. Uses the smallest model in the fleet (8B) for maximum speed on routine ops checks.
- Tags: none
- Temperature: 0.2
- Max tokens: 2048
- Token quota: 50,000/hour
- Schedule: Periodic every 5 minutes
- Tools:
shell_exec,file_read,file_list - Shell access:
docker *,git *,cargo *,systemctl *,ps *,df *,free * - Capabilities:
memory_read = ["*"],memory_write = ["self.*"]
openfang spawn ops
# "Check disk usage, memory, and running containers"hello-world
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
A friendly greeting agent that can read files and fetch web pages.
The simplest agent template -- a minimal starter agent with basic read-only capabilities. No system prompt, no tags, no shell access. Useful as a starting point for custom agents or for testing that the agent system is working.
- Tags: none
- Temperature: default
- Max tokens: default
- Token quota: 100,000/hour
- Tools:
file_read,file_list,web_fetch - Capabilities:
memory_read = ["*"],memory_write = ["self.*"],agent_spawn = false
openfang spawn hello-world
# "Hello! What can you do?"translator
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Multi-language translation agent for document translation, localization, and cross-cultural communication.
Translates between 20+ major languages with high fidelity to meaning, tone, and intent. Handles contextual and cultural adaptation, document format preservation, software localization (JSON, YAML, PO/POT, XLIFF), technical/specialized translation, translation quality assurance (back-translation, consistency checks), and glossary management. Flags ambiguous phrases with multiple translation options.
- Tags:
translation,languages,localization,multilingual,communication,i18n - Temperature: 0.3
- Max tokens: 8192
- Token quota: 200,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn translator
# "Translate this README from English to Japanese and Spanish, preserving code blocks"tutor
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Teaching and explanation agent for learning, tutoring, and educational content creation.
Explains concepts at the learner's level using the Feynman Technique. Uses Socratic questioning to guide discovery. Teaches across mathematics, computer science, natural sciences, humanities, social sciences, and professional skills. Walks through problems step-by-step showing reasoning, not just solutions. Creates structured learning plans with spaced repetition. Provides practice questions with detailed, constructive feedback.
- Tags:
education,teaching,tutoring,learning,explanation,knowledge - Temperature: 0.5
- Max tokens: 8192
- Token quota: 200,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,shell_exec,web_fetch - Shell access:
python * - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn tutor
# "Teach me how binary search trees work, starting from the basics"health-tracker
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Wellness tracking agent for health metrics, medication reminders, fitness goals, and lifestyle habits.
Tracks weight, blood pressure, heart rate, sleep, water intake, steps, mood, and custom metrics. Manages medication schedules with dosage, timing, and refill dates. Sets SMART fitness goals with progressive training plans. Logs meals and estimates nutritional content. Applies evidence-based habit formation principles. Generates periodic wellness reports. Always includes a disclaimer that it is not a medical professional.
- Tags:
health,wellness,fitness,medication,habits,tracking - Temperature: 0.3
- Max tokens: 4096
- Token quota: 100,000/hour
- Max concurrent tools: 5
- Schedule: Periodic every 1 hour
- Tools:
file_read,file_write,file_list,memory_store,memory_recall - Capabilities:
memory_read = ["*"],memory_write = ["self.*"]
openfang spawn health-tracker
# "Log today's metrics: weight 175lbs, sleep 7.5 hours, mood 8/10, 8000 steps"personal-finance
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Personal finance agent for budget tracking, expense analysis, savings goals, and financial planning.
Creates detailed budgets using frameworks like 50/30/20, zero-based budgeting, and envelope method. Processes expense data in any format (CSV, manual lists) and categorizes transactions. Defines and tracks savings goals with projected timelines. Analyzes debt portfolios and models avalanche vs. snowball payoff strategies. Produces financial health reports with net worth, debt-to-income ratio, and savings rate. Always disclaims that output is not financial advice.
- Tags:
finance,budget,expenses,savings,planning,money - Temperature: 0.2
- Max tokens: 8192
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,shell_exec - Shell access:
python * - Capabilities:
memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn personal-finance
# "Analyze this month's expense CSV and show me where I'm over budget"travel-planner
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Trip planning agent for itinerary creation, booking research, budget estimation, and travel logistics.
Builds day-by-day itineraries with estimated times, transportation, meal recommendations, and contingency plans. Provides comprehensive destination guides covering best times to visit, attractions, customs, safety, cuisine, and visa requirements. Creates detailed travel budgets at multiple price tiers. Recommends accommodations by type, neighborhood, and budget. Plans transportation logistics including flights, trains, and local transit. Generates customized packing lists.
- Tags:
travel,planning,itinerary,booking,logistics,vacation - Temperature: 0.5
- Max tokens: 8192
- Token quota: 150,000/hour
- Max concurrent tools: 5
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,web_fetch - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn travel-planner
# "Plan a 10-day trip to Japan for 2 people, mid-range budget, mix of culture and food"home-automation
Tier 4 -- Fast | groq/llama-3.3-70b-versatile | No fallback
Smart home control agent for IoT device management, automation rules, and home monitoring.
Manages smart home devices (lights, thermostats, security, appliances, sensors). Designs automation workflows using event-condition-action patterns. Configures multi-device scenes for common scenarios (morning routine, movie night, bedtime, away mode). Monitors energy consumption and recommends optimizations. Configures home security workflows. Troubleshoots IoT connectivity and bridges different ecosystems (Home Assistant, HomeKit, SmartThings). Understands Matter/Thread protocol adoption.
- Tags:
smart-home,iot,automation,devices,monitoring,home - Temperature: 0.2
- Max tokens: 4096
- Token quota: 100,000/hour
- Max concurrent tools: 10
- Tools:
file_read,file_write,file_list,memory_store,memory_recall,shell_exec,web_fetch - Shell access:
curl *,python *,ping * - Capabilities:
network = ["*"],memory_read = ["*"],memory_write = ["self.*", "shared.*"]
openfang spawn home-automation
# "Create a bedtime automation: lock doors, arm cameras, dim lights, set thermostat to 68F"Custom Templates
The agents/custom/ directory is reserved for your own agent templates. Create a new agent.toml file following the manifest format below.
Manifest Format
/* Detailed source-code truncated for AI context efficiency. */Available Tools
| Tool | Description |
|---|---|
file_read |
Read file contents |
file_write |
Write/create files |
file_list |
List directory contents |
shell_exec |
Execute shell commands (restricted by shell whitelist) |
memory_store |
Persist key-value data to memory |
memory_recall |
Retrieve data from memory |
web_fetch |
Fetch content from URLs (SSRF-protected) |
agent_send |
Send a message to another agent |
agent_list |
List all running agents |
agent_spawn |
Spawn a new agent |
agent_kill |
Terminate a running agent |
Tips for Custom Agents
- Start minimal. Grant only the tools and capabilities the agent actually needs. You can always add more later.
- Write a clear system prompt. The system prompt is the most important part of the template. Be specific about the agent's role, methodology, output format, and limitations.
- Set appropriate temperature. Use 0.2 for precise/analytical tasks, 0.5 for balanced tasks, 0.7+ for creative tasks.
- Use shell whitelists. Never grant
shell = ["*"]. Whitelist specific command patterns likeshell = ["python *", "cargo test *"]. - Set token budgets. Use
max_llm_tokens_per_hourto prevent runaway costs. Start with 100,000 and adjust based on usage. - Add fallback models. If your primary model has rate limits or availability issues, add a
[[fallback_models]]entry. - Use memory for continuity. Grant
memory_storeandmemory_recallso the agent can persist context across sessions.
Spawning Agents
CLI
# Spawn by template name
openfang spawn coder
# Spawn with a custom name
openfang spawn coder --name "backend-coder"
# Spawn from a TOML file path
openfang spawn --template agents/custom/my-agent.toml
# List running agents
openfang agents
# Send a message
openfang message <agent-id> "Write a function to parse TOML files"
# Kill an agent
openfang kill <agent-id>REST API
# Spawn from template
POST /api/agents
{"template": "coder"}
# Spawn with overrides
POST /api/agents
{"template": "coder", "name": "backend-coder", "model": "deepseek-chat"}
# Send message
POST /api/agents/{id}/message
{"content": "Implement the auth module"}
# WebSocket (streaming)
WS /api/agents/{id}/ws
# List agents
GET /api/agents
# Delete agent
DELETE /api/agents/{id}OpenAI-Compatible API
# Use any agent through the OpenAI-compatible endpoint
POST /v1/chat/completions
{
"model": "openfang:coder",
"messages": [{"role": "user", "content": "Write a Rust HTTP server"}],
"stream": true
}
# List available models
GET /v1/modelsOrchestrator Delegation
The orchestrator agent can spawn and delegate to any other agent programmatically:
User: "Build a REST API with tests and documentation"
Orchestrator:
1. agent_send(coder, "Implement the REST API endpoints")
2. agent_send(test-engineer, "Write integration tests for these endpoints")
3. agent_send(doc-writer, "Document the API endpoints")
4. Synthesize all results into a final reportEnvironment Variables
Set the following API keys to enable the corresponding model providers:
| Variable | Provider | Used By |
|---|---|---|
DEEPSEEK_API_KEY |
DeepSeek | Tier 1 (orchestrator, architect, security-auditor) |
GEMINI_API_KEY |
Google Gemini | Tier 2 primary, Tier 3 fallback |
GROQ_API_KEY |
Groq | Tier 3 primary, Tier 1/2 fallback, Tier 4 |
At minimum, set GROQ_API_KEY to enable all Tier 3 and Tier 4 agents. Add GEMINI_API_KEY for Tier 2 agents. Add DEEPSEEK_API_KEY for Tier 1 frontier agents.
File: docs/api-reference.md
API Reference
OpenFang exposes a REST API, WebSocket endpoints, and SSE streaming when the daemon is running. The default listen address is http://127.0.0.1:4200.
All responses include security headers (CSP, X-Frame-Options, X-Content-Type-Options, HSTS) and are protected by a GCRA cost-aware rate limiter with per-IP token bucket tracking and automatic stale entry cleanup. OpenFang implements 16 security systems including Merkle audit trails, taint tracking, WASM dual metering, Ed25519 manifest signing, SSRF protection, subprocess sandboxing, and secret zeroization.
Table of Contents
- Authentication
- Agent Endpoints
- Workflow Endpoints
- Trigger Endpoints
- Memory Endpoints
- Channel Endpoints
- Template Endpoints
- System Endpoints
- Model Catalog Endpoints
- Provider Configuration Endpoints
- Skills & Marketplace Endpoints
- ClawHub Endpoints
- MCP & A2A Protocol Endpoints
- Audit & Security Endpoints
- Usage & Analytics Endpoints
- Migration Endpoints
- Session Management Endpoints
- Cron/Scheduler Endpoints
- WebSocket Protocol
- SSE Streaming
- OpenAI-Compatible API
- Error Responses
Authentication
When an API key is configured in config.toml, all endpoints (except /api/health and /) require a Bearer token:
Authorization: Bearer <your-api-key>Setting the API Key
Add to ~/.openfang/config.toml:
api_key = "your-secret-api-key"No Authentication
If api_key is empty or not set, the API is accessible without authentication. CORS is restricted to localhost origins in this mode.
Public Endpoints (No Auth Required)
GET /api/healthGET /(WebChat UI)
Agent Endpoints
GET /api/agents
List all running agents.
Response 200 OK:
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "hello-world",
"state": "Running",
"created_at": "2025-01-15T10:30:00Z",
"model_provider": "groq",
"model_name": "llama-3.3-70b-versatile"
}
]GET /api/agents/{id}
Returns detailed information about a single agent.
Response 200 OK:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "hello-world",
"state": "Running",
"created_at": "2025-01-15T10:30:00Z",
"session_id": "s1b2c3d4-...",
"model": {
"provider": "groq",
"model": "llama-3.3-70b-versatile"
},
"capabilities": {
"tools": ["file_read", "file_list", "web_fetch"],
"network": []
},
"description": "A friendly greeting agent",
"tags": []
}POST /api/agents
Spawn a new agent from a TOML manifest.
Request Body (JSON):
{
"manifest_toml": "name = \"my-agent\"\nversion = \"0.1.0\"\ndescription = \"Test agent\"\nauthor = \"me\"\nmodule = \"builtin:chat\"\n\n[model]\nprovider = \"groq\"\nmodel = \"llama-3.3-70b-versatile\"\n\n[capabilities]\ntools = [\"file_read\", \"web_fetch\"]\nmemory_read = [\"*\"]\nmemory_write = [\"self.*\"]\n"
}Response 201 Created:
{
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-agent"
}PUT /api/agents/{id}/update
Update an agent's configuration at runtime.
Request Body:
{
"description": "Updated description",
"system_prompt": "You are a specialized assistant.",
"tags": ["updated", "v2"]
}Response 200 OK:
{
"status": "updated",
"agent_id": "a1b2c3d4-..."
}PUT /api/agents/{id}/mode
Set an agent's operating mode. Stable mode pins the current model and freezes the skill registry. Normal mode restores default behavior.
Request Body:
{
"mode": "Stable"
}Response 200 OK:
{
"status": "updated",
"mode": "Stable",
"agent_id": "a1b2c3d4-..."
}POST /api/agents/{id}/message
Send a message to an agent and receive the complete response.
Request Body:
{
"message": "What files are in the current directory?"
}Response 200 OK:
{
"response": "Here are the files in the current directory:\n- Cargo.toml\n- README.md\n...",
"input_tokens": 142,
"output_tokens": 87,
"iterations": 1
}GET /api/agents/{id}/session
Returns the agent's conversation history.
Response 200 OK:
{
"session_id": "s1b2c3d4-...",
"agent_id": "a1b2c3d4-...",
"message_count": 4,
"context_window_tokens": 1250,
"messages": [
{
"role": "User",
"content": "Hello"
},
{
"role": "Assistant",
"content": "Hello! How can I help you?"
}
]
}DELETE /api/agents/{id}
Terminate an agent and remove it from the registry.
Response 200 OK:
{
"status": "killed",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}Workflow Endpoints
GET /api/workflows
List all registered workflows.
Response 200 OK:
[
{
"id": "w1b2c3d4-...",
"name": "code-review-pipeline",
"description": "Automated code review workflow",
"steps": 3,
"created_at": "2025-01-15T10:30:00Z"
}
]POST /api/workflows
Create a new workflow definition.
Request Body (JSON):
{
"name": "code-review-pipeline",
"description": "Review code changes with multiple agents",
"steps": [
{
"name": "analyze",
"agent_name": "coder",
"prompt": "Analyze this code for potential issues: {{input}}",
"mode": "sequential",
"timeout_secs": 120,
"error_mode": "fail",
"output_var": "analysis"
},
{
"name": "security-check",
"agent_name": "security-auditor",
"prompt": "Review this code analysis for security vulnerabilities: {{analysis}}",
"mode": "sequential",
"timeout_secs": 120,
"error_mode": "skip"
},
{
"name": "summarize",
"agent_name": "writer",
"prompt": "Write a concise code review summary based on: {{analysis}}",
"mode": "sequential",
"timeout_secs": 60,
"error_mode": "fail"
}
]
}Step configuration options:
| Field | Type | Description |
|---|---|---|
name |
string | Step name |
agent_id |
string | Agent UUID (use either this or agent_name) |
agent_name |
string | Agent name (use either this or agent_id) |
prompt |
string | Prompt template with {{input}} and {{output_var}} placeholders |
mode |
string | "sequential", "fan_out", "collect", "conditional", "loop" |
timeout_secs |
integer | Timeout per step (default: 120) |
error_mode |
string | "fail", "skip", "retry" |
max_retries |
integer | For "retry" error mode (default: 3) |
output_var |
string | Variable name to store output for later steps |
condition |
string | For "conditional" mode |
max_iterations |
integer | For "loop" mode (default: 5) |
until |
string | For "loop" mode: stop condition |
Response 201 Created:
{
"workflow_id": "w1b2c3d4-..."
}POST /api/workflows/{id}/run
Execute a workflow.
Request Body:
{
"input": "Review this pull request: ..."
}Response 200 OK:
{
"run_id": "r1b2c3d4-...",
"output": "Code review summary:\n- No critical issues found\n...",
"status": "completed"
}GET /api/workflows/{id}/runs
List execution history for a workflow.
Response 200 OK:
[
{
"id": "r1b2c3d4-...",
"workflow_name": "code-review-pipeline",
"state": "Completed",
"steps_completed": 3,
"started_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:32:15Z"
}
]Trigger Endpoints
GET /api/triggers
List all triggers. Optionally filter by agent.
Query Parameters:
agent_id(optional): Filter by agent UUID
Response 200 OK:
[
{
"id": "t1b2c3d4-...",
"agent_id": "a1b2c3d4-...",
"pattern": {"lifecycle": {}},
"prompt_template": "Event: {{event}}",
"enabled": true,
"fire_count": 5,
"max_fires": 0,
"created_at": "2025-01-15T10:30:00Z"
}
]POST /api/triggers
Create a new event trigger.
Request Body:
{
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"pattern": {
"agent_spawned": {
"name_pattern": "*"
}
},
"prompt_template": "A new agent was spawned: {{event}}. Review its capabilities.",
"max_fires": 0
}Supported pattern types:
| Pattern | Description |
|---|---|
{"lifecycle": {}} |
All lifecycle events |
{"agent_spawned": {"name_pattern": "*"}} |
Agent spawn events |
{"agent_terminated": {}} |
Agent termination events |
{"all": {}} |
All events |
Response 201 Created:
{
"trigger_id": "t1b2c3d4-...",
"agent_id": "a1b2c3d4-..."
}PUT /api/triggers/{id}
Update an existing trigger's configuration.
Request Body:
{
"prompt_template": "Updated template: {{event}}",
"enabled": false,
"max_fires": 10
}Response 200 OK:
{
"status": "updated",
"trigger_id": "t1b2c3d4-..."
}DELETE /api/triggers/{id}
Remove a trigger.
Response 200 OK:
{
"status": "removed",
"trigger_id": "t1b2c3d4-..."
}Memory Endpoints
GET /api/memory/agents/{id}/kv
List all key-value pairs for an agent.
Response 200 OK:
{
"kv_pairs": [
{"key": "preferences", "value": {"theme": "dark"}},
{"key": "state", "value": {"step": 3}}
]
}GET /api/memory/agents/{id}/kv/{key}
Get a specific key-value pair.
Response 200 OK:
{
"key": "preferences",
"value": {"theme": "dark"}
}Response 404 Not Found (key does not exist):
{
"error": "Key 'preferences' not found"
}PUT /api/memory/agents/{id}/kv/{key}
Set a key-value pair. Creates or overwrites.
Request Body:
{
"value": {"theme": "dark", "language": "en"}
}Response 200 OK:
{
"status": "stored",
"key": "preferences"
}DELETE /api/memory/agents/{id}/kv/{key}
Delete a key-value pair.
Response 200 OK:
{
"status": "deleted",
"key": "preferences"
}Channel Endpoints
GET /api/channels
List configured channel adapters and their status. Supports 40 channel adapters including Telegram, Discord, Slack, WhatsApp, Matrix, Email, Teams, Mattermost, IRC, Google Chat, Twitch, Rocket.Chat, Zulip, XMPP, LINE, Viber, Messenger, Reddit, Mastodon, Bluesky, and more.
Response 200 OK:
{
"channels": [
{
"name": "telegram",
"enabled": true,
"has_token": true
},
{
"name": "discord",
"enabled": true,
"has_token": false
}
],
"total": 2
}Template Endpoints
GET /api/templates
List available agent templates from the agents directory.
Response 200 OK:
{
"templates": [
{
"name": "hello-world",
"description": "A friendly greeting agent",
"path": "/home/user/.openfang/agents/hello-world/agent.toml"
},
{
"name": "coder",
"description": "Expert coding assistant",
"path": "/home/user/.openfang/agents/coder/agent.toml"
}
],
"total": 30
}GET /api/templates/{name}
Get a specific template's manifest and raw TOML.
Response 200 OK:
{
"name": "hello-world",
"manifest": {
"name": "hello-world",
"description": "A friendly greeting agent",
"module": "builtin:chat",
"tags": [],
"model": {
"provider": "groq",
"model": "llama-3.3-70b-versatile"
},
"capabilities": {
"tools": ["file_read", "file_list", "web_fetch"],
"network": []
}
},
"manifest_toml": "name = \"hello-world\"\nversion = \"0.1.0\"\n..."
}System Endpoints
GET /api/health
Public health check. Does not require authentication. Returns a redacted subset of system status (no database or agent_count details).
Response 200 OK:
{
"status": "ok",
"uptime_seconds": 3600,
"panic_count": 0,
"restart_count": 0
}The status field is "ok" when all systems are healthy, or "degraded" when the database is unreachable.
GET /api/health/detail
Full health check with all dependency status. Requires authentication. Unlike the public /api/health, this endpoint includes database connectivity and agent counts.
Response 200 OK:
{
"status": "ok",
"uptime_seconds": 3600,
"panic_count": 0,
"restart_count": 0,
"agent_count": 3,
"database": "connected",
"config_warnings": []
}GET /api/status
Detailed kernel status including all agents.
Response 200 OK:
{
"status": "running",
"agent_count": 2,
"data_dir": "/home/user/.openfang/data",
"default_provider": "groq",
"default_model": "llama-3.3-70b-versatile",
"uptime_seconds": 3600,
"agents": [
{
"id": "a1b2c3d4-...",
"name": "hello-world",
"state": "Running",
"created_at": "2025-01-15T10:30:00Z",
"model_provider": "groq",
"model_name": "llama-3.3-70b-versatile"
}
]
}GET /api/version
Build and version information.
Response 200 OK:
{
"name": "openfang",
"version": "0.1.0",
"build_date": "2025-01-15",
"git_sha": "abc1234",
"rust_version": "1.82.0",
"platform": "linux",
"arch": "x86_64"
}POST /api/shutdown
Initiate graceful shutdown. Agent states are preserved to SQLite for restore on next boot.
Response 200 OK:
{
"status": "shutting_down"
}GET /api/profiles
List available agent profiles (predefined configurations for common use cases).
Response 200 OK:
{
"profiles": [
{
"name": "coder",
"tier": "smart",
"description": "Expert coding assistant"
},
{
"name": "researcher",
"tier": "frontier",
"description": "Deep research and analysis"
}
]
}GET /api/tools
List all available tools that agents can use.
Response 200 OK:
{
"tools": [
"file_read",
"file_write",
"file_list",
"web_fetch",
"web_search",
"shell_exec",
"kv_get",
"kv_set",
"agent_call"
],
"total": 23
}GET /api/config
Retrieve current kernel configuration (secrets are redacted).
Response 200 OK:
{
"data_dir": "/home/user/.openfang/data",
"default_provider": "groq",
"default_model": "llama-3.3-70b-versatile",
"listen_addr": "127.0.0.1:4200",
"api_key_set": true,
"channels_configured": 2,
"mcp_servers": 1
}GET /api/peers
List OFP (OpenFang Protocol) wire peers and their connection status.
Response 200 OK:
{
"peers": [
{
"node_id": "peer-1",
"address": "192.168.1.100:4000",
"state": "connected",
"authenticated": true,
"last_seen": "2025-01-15T10:30:00Z"
}
]
}GET /api/sessions
List all active sessions across agents.
Response 200 OK:
{
"sessions": [
{
"id": "s1b2c3d4-...",
"agent_id": "a1b2c3d4-...",
"agent_name": "coder",
"message_count": 12,
"created_at": "2025-01-15T10:30:00Z"
}
]
}DELETE /api/sessions/{id}
Delete a specific session and its conversation history.
Response 200 OK:
{
"status": "deleted",
"session_id": "s1b2c3d4-..."
}Model Catalog Endpoints
OpenFang maintains a built-in catalog of 51+ models across 20 providers. These endpoints allow you to browse available models, check provider authentication status, and resolve model aliases.
GET /api/models
List the full model catalog. Returns all known models with their provider, tier, context window, and pricing information.
Response 200 OK:
{
"models": [
{
"id": "claude-sonnet-4-20250514",
"provider": "anthropic",
"display_name": "Claude Sonnet 4",
"tier": "frontier",
"context_window": 200000,
"input_cost_per_1m": 3.0,
"output_cost_per_1m": 15.0,
"supports_tools": true,
"supports_vision": true,
"supports_streaming": true
},
{
"id": "gemini-2.5-flash",
"provider": "gemini",
"display_name": "Gemini 2.5 Flash",
"tier": "smart",
"context_window": 1048576,
"input_cost_per_1m": 0.15,
"output_cost_per_1m": 0.6,
"supports_tools": true,
"supports_vision": true,
"supports_streaming": true
}
],
"total": 51
}GET /api/models/{id}
Get detailed information about a specific model.
Response 200 OK:
{
"id": "llama-3.3-70b-versatile",
"provider": "groq",
"display_name": "Llama 3.3 70B",
"tier": "fast",
"context_window": 131072,
"input_cost_per_1m": 0.59,
"output_cost_per_1m": 0.79,
"supports_tools": true,
"supports_vision": false,
"supports_streaming": true
}Response 404 Not Found:
{
"error": "Model 'unknown-model' not found in catalog"
}GET /api/models/aliases
List all model aliases. Aliases provide short names that resolve to full model IDs (e.g., sonnet resolves to claude-sonnet-4-20250514).
Response 200 OK:
{
"aliases": {
"sonnet": "claude-sonnet-4-20250514",
"opus": "claude-opus-4-20250514",
"haiku": "claude-3-5-haiku-20241022",
"flash": "gemini-2.5-flash",
"gpt4": "gpt-4o",
"llama": "llama-3.3-70b-versatile",
"deepseek": "deepseek-chat",
"grok": "grok-2",
"jamba": "jamba-1.5-large"
},
"total": 23
}GET /api/providers
List all known LLM providers and their authentication status. Auth status is detected by checking environment variable presence (never reads secret values).
Response 200 OK:
{
"providers": [
{
"name": "anthropic",
"display_name": "Anthropic",
"auth_status": "configured",
"env_var": "ANTHROPIC_API_KEY",
"base_url": "https://api.anthropic.com",
"model_count": 3
},
{
"name": "groq",
"display_name": "Groq",
"auth_status": "configured",
"env_var": "GROQ_API_KEY",
"base_url": "https://api.groq.com/openai",
"model_count": 4
},
{
"name": "ollama",
"display_name": "Ollama",
"auth_status": "no_key_needed",
"base_url": "http://localhost:11434",
"model_count": 0
}
],
"total": 20
}Provider Configuration Endpoints
Manage LLM provider API keys at runtime without editing config files or restarting the daemon.
POST /api/providers/{name}/key
Set an API key for a provider. The key is stored securely and takes effect immediately.
Request Body:
{
"api_key": "sk-..."
}Response 200 OK:
{
"status": "configured",
"provider": "anthropic"
}DELETE /api/providers/{name}/key
Remove the API key for a provider. Agents using this provider will fall back to the FallbackDriver or fail.
Response 200 OK:
{
"status": "removed",
"provider": "anthropic"
}POST /api/providers/{name}/test
Test provider connectivity by making a minimal API call. Verifies that the configured API key is valid and the provider endpoint is reachable.
Response 200 OK:
{
"status": "ok",
"provider": "anthropic",
"latency_ms": 245,
"model_tested": "claude-sonnet-4-20250514"
}Response 401 Unauthorized:
{
"status": "failed",
"provider": "anthropic",
"error": "Invalid API key"
}Skills & Marketplace Endpoints
Manage the skill registry. Skills extend agent capabilities with Python, Node.js, WASM, or prompt-only modules. All skill installations go through SHA256 verification and prompt injection scanning.
GET /api/skills
List all installed skills.
Response 200 OK:
{
"skills": [
{
"name": "github",
"version": "1.0.0",
"runtime": "prompt_only",
"description": "GitHub integration for issues, PRs, and repos",
"bundled": true
},
{
"name": "docker",
"version": "1.0.0",
"runtime": "prompt_only",
"description": "Docker container management",
"bundled": true
}
],
"total": 60
}POST /api/skills/install
Install a skill from a local path or URL. The skill manifest is verified (SHA256 checksum) and scanned for prompt injection before installation.
Request Body:
{
"source": "/path/to/skill",
"verify": true
}Response 201 Created:
{
"status": "installed",
"skill": "my-custom-skill",
"version": "1.0.0"
}POST /api/skills/uninstall
Remove an installed skill. Bundled skills cannot be uninstalled.
Request Body:
{
"name": "my-custom-skill"
}Response 200 OK:
{
"status": "uninstalled",
"skill": "my-custom-skill"
}POST /api/skills/create
Create a new skill from a template.
Request Body:
{
"name": "my-skill",
"runtime": "python",
"description": "A custom skill"
}Response 201 Created:
{
"status": "created",
"skill": "my-skill",
"path": "/home/user/.openfang/skills/my-skill"
}GET /api/marketplace/search
Search the FangHub marketplace for community skills.
Query Parameters:
q(required): Search query stringpage(optional): Page number (default: 1)
Response 200 OK:
{
"results": [
{
"name": "weather-api",
"author": "community",
"description": "Real-time weather data integration",
"downloads": 1250,
"version": "2.1.0"
}
],
"total": 1,
"page": 1
}ClawHub Endpoints
Browse and install skills from ClawHub (OpenClaw ecosystem compatibility). All installations go through the full security pipeline: SHA256 verification, SKILL.md security scanning, and trust boundary enforcement.
GET /api/clawhub/search
Search ClawHub for compatible skills.
Query Parameters:
q(required): Search query
Response 200 OK:
{
"results": [
{
"slug": "data-pipeline",
"name": "Data Pipeline",
"description": "ETL data pipeline automation",
"author": "clawhub-community",
"version": "1.2.0"
}
],
"total": 1
}GET /api/clawhub/browse
Browse ClawHub categories.
Query Parameters:
category(optional): Filter by categorypage(optional): Page number (default: 1)
Response 200 OK:
{
"skills": [
{
"slug": "data-pipeline",
"name": "Data Pipeline",
"category": "data",
"description": "ETL data pipeline automation"
}
],
"total": 15,
"page": 1
}GET /api/clawhub/skill/{slug}
Get detailed information about a specific ClawHub skill.
Response 200 OK:
{
"slug": "data-pipeline",
"name": "Data Pipeline",
"description": "ETL data pipeline automation",
"author": "clawhub-community",
"version": "1.2.0",
"runtime": "python",
"readme": "# Data Pipeline\n\nAutomated ETL...",
"sha256": "a1b2c3d4..."
}POST /api/clawhub/install
Install a skill from ClawHub. Downloads, verifies SHA256 checksum, scans for prompt injection, and converts SKILL.md format to OpenFang skill.toml automatically.
Request Body:
{
"slug": "data-pipeline"
}Response 201 Created:
{
"status": "installed",
"skill": "data-pipeline",
"version": "1.2.0",
"converted_from": "SKILL.md"
}MCP & A2A Protocol Endpoints
OpenFang supports both Model Context Protocol (MCP) for tool interoperability and Agent-to-Agent (A2A) protocol for cross-system agent communication.
GET /api/mcp/servers
List configured and connected MCP servers with their available tools.
Response 200 OK:
{
"servers": [
{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"],
"connected": true,
"tools": [
{
"name": "mcp_filesystem_read_file",
"description": "Read a file from the filesystem"
},
{
"name": "mcp_filesystem_write_file",
"description": "Write content to a file"
}
]
}
],
"total": 1
}POST /mcp
MCP HTTP transport endpoint. Accepts JSON-RPC 2.0 requests and exposes OpenFang tools via the MCP protocol to external clients.
Request Body (JSON-RPC 2.0):
{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 1
}Response 200 OK:
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"name": "file_read",
"description": "Read a file's contents",
"inputSchema": {
"type": "object",
"properties": {
"path": {"type": "string"}
}
}
}
]
},
"id": 1
}GET /.well-known/agent.json
A2A agent card discovery endpoint. Returns the server's A2A agent card, which describes its capabilities, supported protocols, and available agents.
Response 200 OK:
{
"name": "OpenFang",
"description": "OpenFang Agent Operating System",
"url": "http://127.0.0.1:4200",
"version": "0.1.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"skills": [
{
"id": "chat",
"name": "Chat",
"description": "General-purpose chat with any agent"
}
]
}GET /a2a/agents
List agents available via A2A protocol.
Response 200 OK:
{
"agents": [
{
"id": "a1b2c3d4-...",
"name": "coder",
"description": "Expert coding assistant",
"skills": ["code-review", "debugging", "refactoring"]
}
]
}POST /a2a/tasks/send
Send a task to an agent via A2A protocol. Follows the Google A2A specification for inter-agent task delegation.
Request Body:
{
"agent_id": "a1b2c3d4-...",
"message": {
"role": "user",
"parts": [
{"text": "Review this code for security issues"}
]
}
}Response 200 OK:
{
"task_id": "task-1234-...",
"status": "completed",
"result": {
"role": "agent",
"parts": [
{"text": "I found 2 potential security issues..."}
]
}
}GET /a2a/tasks/{id}
Get the status and result of an A2A task.
Response 200 OK:
{
"task_id": "task-1234-...",
"status": "completed",
"created_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:30:05Z",
"result": {
"role": "agent",
"parts": [
{"text": "Analysis complete..."}
]
}
}POST /a2a/tasks/{id}/cancel
Cancel a running A2A task.
Response 200 OK:
{
"task_id": "task-1234-...",
"status": "cancelled"
}Audit & Security Endpoints
OpenFang maintains a Merkle hash chain audit trail for all security-relevant operations. These endpoints allow inspection and verification of the audit log integrity.
GET /api/audit/recent
Retrieve recent audit log entries.
Query Parameters:
limit(optional): Number of entries to return (default: 50, max: 500)
Response 200 OK:
{
"entries": [
{
"id": 1042,
"timestamp": "2025-01-15T10:30:00Z",
"event_type": "agent_spawned",
"agent_id": "a1b2c3d4-...",
"details": "Agent 'coder' spawned with model groq/llama-3.3-70b-versatile",
"hash": "a1b2c3d4e5f6...",
"prev_hash": "f6e5d4c3b2a1..."
}
],
"total": 1042
}GET /api/audit/verify
Verify the integrity of the Merkle hash chain audit trail. Walks the entire chain and reports any broken links.
Response 200 OK:
{
"status": "valid",
"chain_length": 1042,
"first_entry": "2025-01-10T08:00:00Z",
"last_entry": "2025-01-15T10:30:00Z"
}Response 200 OK (chain broken):
{
"status": "broken",
"chain_length": 1042,
"break_at": 847,
"error": "Hash mismatch at entry 847"
}GET /api/security
Security status overview showing the state of all 16 security systems.
Response 200 OK:
{
"security_systems": {
"merkle_audit_trail": "active",
"taint_tracking": "active",
"wasm_dual_metering": "active",
"security_headers": "active",
"health_redaction": "active",
"subprocess_sandbox": "active",
"manifest_signing": "active",
"gcra_rate_limiter": "active",
"secret_zeroization": "active",
"path_traversal_prevention": "active",
"ssrf_protection": "active",
"capability_inheritance_validation": "active",
"ofp_hmac_auth": "active",
"prompt_injection_scanning": "active",
"loop_guard": "active",
"session_repair": "active"
},
"total_systems": 16,
"all_active": true
}Usage & Analytics Endpoints
Track token usage, costs, and model utilization across all agents. Powered by the metering engine with cost estimation from the model catalog.
GET /api/usage
Get overall usage statistics.
Query Parameters:
period(optional): Time period (hour,day,week,month; default:day)
Response 200 OK:
{
"period": "day",
"total_input_tokens": 125000,
"total_output_tokens": 87000,
"total_cost_usd": 0.42,
"request_count": 156,
"active_agents": 5
}GET /api/usage/summary
Get a high-level usage summary with quota information.
Response 200 OK:
{
"today": {
"input_tokens": 125000,
"output_tokens": 87000,
"cost_usd": 0.42,
"requests": 156
},
"quota": {
"hourly_token_limit": 1000000,
"hourly_tokens_used": 45000,
"hourly_reset_at": "2025-01-15T11:00:00Z"
}
}GET /api/usage/by-model
Get usage breakdown by model.
Response 200 OK:
{
"models": [
{
"model": "llama-3.3-70b-versatile",
"provider": "groq",
"input_tokens": 80000,
"output_tokens": 55000,
"cost_usd": 0.09,
"request_count": 120
},
{
"model": "gemini-2.5-flash",
"provider": "gemini",
"input_tokens": 45000,
"output_tokens": 32000,
"cost_usd": 0.33,
"request_count": 36
}
]
}Migration Endpoints
Import data from OpenClaw or other agent frameworks. The migration engine handles YAML-to-TOML manifest conversion, SKILL.md parsing, and session history import.
GET /api/migrate/detect
Auto-detect migration sources on the system. Scans common locations for OpenClaw installations, config files, and agent data.
Response 200 OK:
{
"sources": [
{
"type": "openclaw",
"path": "/home/user/.openclaw",
"version": "2.1.0",
"agents_found": 12,
"skills_found": 8
}
]
}POST /api/migrate/scan
Scan a specific path for importable data.
Request Body:
{
"path": "/home/user/.openclaw"
}Response 200 OK:
{
"agents": [
{
"name": "my-agent",
"format": "yaml",
"convertible": true
}
],
"skills": [
{
"name": "custom-skill",
"format": "SKILL.md",
"convertible": true
}
],
"sessions": 45
}POST /api/migrate
Run the migration. Converts manifests, imports skills, and optionally imports session history.
Request Body:
{
"source": "/home/user/.openclaw",
"import_agents": true,
"import_skills": true,
"import_sessions": false
}Response 200 OK:
{
"status": "completed",
"agents_imported": 12,
"skills_imported": 8,
"sessions_imported": 0,
"warnings": [
"Skill 'legacy-plugin' uses unsupported runtime 'ruby', skipped"
]
}Session Management Endpoints
POST /api/agents/{id}/session/reset
Reset an agent's session, clearing all conversation history.
Response 200 OK:
{
"status": "reset",
"agent_id": "a1b2c3d4-...",
"new_session_id": "s5e6f7g8-..."
}POST /api/agents/{id}/session/compact
Trigger LLM-based session compaction. The agent's conversation is summarized by an LLM, keeping only the most recent messages plus a generated summary.
Response 200 OK:
{
"status": "compacted",
"message": "Session compacted: 80 messages summarized, 20 kept"
}Response 200 OK (no compaction needed):
{
"status": "ok",
"message": "Session does not need compaction (below threshold)"
}POST /api/agents/{id}/stop
Cancel the agent's current LLM run. Aborts any in-progress generation.
Response 200 OK:
{
"status": "stopped",
"message": "Agent run cancelled"
}PUT /api/agents/{id}/model
Switch an agent's LLM model at runtime.
Request Body:
{
"model": "claude-sonnet-4-20250514"
}Response 200 OK:
{
"status": "updated",
"model": "claude-sonnet-4-20250514"
}Cron/Scheduler Endpoints
Manage recurring and one-shot scheduled jobs. Jobs can trigger agent turns, system events, or workflow runs on a schedule.
GET /api/cron/jobs
List all cron jobs. Optionally filter by agent with ?agent_id=.
Response 200 OK:
{
"jobs": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "daily-report",
"enabled": true,
"schedule": { "kind": "every", "every_secs": 3600 },
"action": {
"kind": "agent_turn",
"message": "Generate the daily report",
"timeout_secs": 120
},
"delivery": {
"kind": "channel",
"channel": "slack",
"to": "#reports"
},
"created_at": "2026-03-15T10:30:00Z",
"last_run": "2026-03-16T09:00:00Z",
"next_run": "2026-03-16T10:00:00Z"
}
],
"total": 1
}POST /api/cron/jobs
Create a new cron job.
Request Body:
{
"agent_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "daily-report",
"schedule": { "kind": "every", "every_secs": 3600 },
"action": {
"kind": "agent_turn",
"message": "Generate the daily report",
"timeout_secs": 120
},
"delivery": {
"kind": "channel",
"channel": "slack",
"to": "#reports"
}
}Response 201 Created:
{
"result": "{\"job_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"status\":\"created\"}"
}DELETE /api/cron/jobs/{id}
Delete a cron job by ID.
Response 200 OK:
{ "status": "deleted" }PUT /api/cron/jobs/{id}/enable
Enable or disable a cron job.
Request Body:
{ "enabled": false }Response 200 OK:
{ "status": "updated", "enabled": false }GET /api/cron/jobs/{id}/status
Get job metadata including last run time, status, and error history.
Response 200 OK:
{
"job": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "daily-report",
"enabled": true,
"schedule": { "kind": "every", "every_secs": 3600 },
"action": {
"kind": "agent_turn",
"message": "Generate the daily report",
"timeout_secs": 120
},
"delivery": { "kind": "none" },
"created_at": "2026-03-15T10:30:00Z",
"last_run": "2026-03-16T09:00:00Z",
"next_run": "2026-03-16T10:00:00Z"
},
"one_shot": false,
"last_status": "ok",
"consecutive_errors": 0
}
### POST /api/cron/jobs/{id}/run
Trigger a cron job immediately. The job executes asynchronously in the background — this endpoint returns immediately without waiting for completion. Poll `GET /api/cron/jobs/{id}/status` to check the result.
**Response** `200 OK`:
```json
{
"status": "triggered",
"job_id": "550e8400-e29b-41d4-a716-446655440000"
}Error Responses:
400 Bad Request— Invalid job ID or job is disabled404 Not Found— Job not found
WebSocket Protocol
Connecting
GET /api/agents/{id}/wsUpgrades to a WebSocket connection for real-time bidirectional chat with an agent. Returns 400 if the agent ID is invalid, or 404 if the agent does not exist.
Message Format
All messages are JSON-encoded strings.
Client to Server
Send a message:
{
"type": "message",
"content": "What is the weather like?"
}Plain text (non-JSON) is also accepted and treated as a message.
Chat commands (sent as messages with / prefix):
| Command | Description |
|---|---|
/new |
Start a new session (clear history) |
/compact |
Trigger LLM session compaction |
/model <name> |
Switch the agent's model |
/stop |
Cancel current LLM run |
/usage |
Show token usage and cost |
/think |
Toggle extended thinking mode |
/models |
List available models |
/providers |
List LLM providers and auth status |
Ping:
{
"type": "ping"
}Server to Client
Connection confirmed (sent immediately on connect):
{
"type": "connected",
"agent_id": "a1b2c3d4-..."
}Thinking indicator (sent when agent starts processing):
{
"type": "thinking"
}Text delta (streaming token, sent as the LLM generates output):
{
"type": "text_delta",
"content": "The weather"
}Tool use started (sent when the agent invokes a tool):
{
"type": "tool_start",
"tool": "web_fetch"
}Complete response (sent when agent finishes, contains final aggregated response):
{
"type": "response",
"content": "The weather today is sunny with a high of 72F.",
"input_tokens": 245,
"output_tokens": 32,
"iterations": 2,
"cost_usd": 0.0012
}Error:
{
"type": "error",
"content": "Agent not found"
}Agent list update (sent every 5 seconds with current agent states):
{
"type": "agents_updated",
"agents": [
{
"id": "a1b2c3d4-...",
"name": "hello-world",
"state": "Running",
"model_provider": "groq",
"model_name": "llama-3.3-70b-versatile"
}
]
}Pong (response to ping):
{
"type": "pong"
}Connection Lifecycle
- Client connects to
ws://host:port/api/agents/{id}/ws. - Server sends
{"type": "connected"}. - Client sends
{"type": "message", "content": "..."}. - Server sends
{"type": "thinking"}, then zero or more{"type": "text_delta"}events, then{"type": "response"}. - Server periodically sends
{"type": "agents_updated"}every 5 seconds. - Client sends a Close frame or disconnects to end the session.
SSE Streaming
POST /api/agents/{id}/message/stream
Send a message and receive the response as a Server-Sent Events stream. This enables real-time token-by-token streaming.
Request Body (JSON):
{
"message": "Explain quantum computing"
}SSE Event Stream:
event: chunk
data: {"content":"Quantum","done":false}
event: chunk
data: {"content":" computing","done":false}
event: chunk
data: {"content":" is a type","done":false}
event: tool_use
data: {"tool":"web_search"}
event: tool_result
data: {"tool":"web_search","input":{"query":"quantum computing basics"}}
event: done
data: {"done":true,"usage":{"input_tokens":150,"output_tokens":340}}SSE Event Types
| Event Name | Description |
|---|---|
chunk |
Text delta from the LLM. "done": false indicates more tokens are coming. |
tool_use |
The agent is invoking a tool. Contains the tool name. |
tool_result |
A tool invocation has completed. Contains the tool name and input. |
done |
Final event. Contains "done": true and token usage statistics. |
OpenAI-Compatible API
OpenFang exposes an OpenAI-compatible API for drop-in integration with tools that support the OpenAI API format (Cursor, Continue, Open WebUI, etc.).
POST /v1/chat/completions
Send a chat completion request using the OpenAI message format.
Request Body:
{
"model": "openfang:coder",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
"stream": false,
"temperature": 0.7,
"max_tokens": 1024
}Model resolution (the model field maps to an OpenFang agent):
| Format | Example | Behavior |
|---|---|---|
openfang:<name> |
openfang:coder |
Find agent by name |
| UUID | a1b2c3d4-... |
Find agent by ID |
| Plain string | coder |
Try as agent name |
| Any other | gpt-4o |
Falls back to first registered agent |
Image support --- messages can include image content parts:
{
"model": "openfang:analyst",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBOR..."}}
]
}
]
}Response (non-streaming) 200 OK:
{
"id": "chatcmpl-a1b2c3d4-...",
"object": "chat.completion",
"created": 1708617600,
"model": "coder",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 25,
"completion_tokens": 12,
"total_tokens": 37
}
}Streaming --- Set "stream": true for SSE:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":25,"completion_tokens":12,"total_tokens":37}}
data: [DONE]GET /v1/models
List available models (agents) in OpenAI format.
Response 200 OK:
{
"object": "list",
"data": [
{
"id": "openfang:coder",
"object": "model",
"created": 1708617600,
"owned_by": "openfang"
},
{
"id": "openfang:researcher",
"object": "model",
"created": 1708617600,
"owned_by": "openfang"
}
]
}Error Responses
All error responses use a consistent JSON format:
{
"error": "Description of what went wrong"
}HTTP Status Codes
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created (spawn agent, create workflow, create trigger, install skill) |
400 |
Bad request (invalid UUID, missing required fields, malformed TOML/JSON) |
401 |
Unauthorized (missing or invalid Authorization: Bearer header) |
404 |
Not found (agent, workflow, trigger, template, model, skill, or KV key does not exist) |
429 |
Too many requests (GCRA rate limit exceeded) |
500 |
Internal server error (agent loop failure, database error, driver error) |
Request IDs
Every response includes an x-request-id header with a UUID for tracing:
x-request-id: 550e8400-e29b-41d4-a716-446655440000Use this value when reporting issues or correlating requests in logs.
Security Headers
Every response includes security headers:
| Header | Value |
|---|---|
Content-Security-Policy |
default-src 'self' (with appropriate directives) |
X-Frame-Options |
DENY |
X-Content-Type-Options |
nosniff |
Strict-Transport-Security |
max-age=63072000; includeSubDomains |
X-Request-Id |
Unique UUID per request |
Rate Limiting
The GCRA (Generic Cell Rate Algorithm) rate limiter provides cost-aware token bucket rate limiting with per-IP tracking and automatic stale entry cleanup. Different endpoints consume different token costs (e.g., /api/agents/{id}/message costs more than /api/health). When the limit is exceeded, the server returns 429 Too Many Requests:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{"error": "Rate limit exceeded"}The Retry-After header indicates the window duration in seconds.
Endpoint Summary
76 endpoints total across 15 groups.
| Method | Path | Description |
|---|---|---|
| System | ||
| GET | / |
WebChat UI |
| GET | /api/health |
Health check (no auth, redacted) |
| GET | /api/health/detail |
Full health check (auth required) |
| GET | /api/status |
Kernel status |
| GET | /api/version |
Version info |
| POST | /api/shutdown |
Graceful shutdown |
| GET | /api/profiles |
List agent profiles |
| GET | /api/tools |
List available tools |
| GET | /api/config |
Configuration (secrets redacted) |
| GET | /api/peers |
List OFP wire peers |
| Agents | ||
| GET | /api/agents |
List agents |
| POST | /api/agents |
Spawn agent |
| GET | /api/agents/{id} |
Get agent details |
| PUT | /api/agents/{id}/update |
Update agent config |
| PUT | /api/agents/{id}/mode |
Set agent mode (Stable/Normal) |
| DELETE | /api/agents/{id} |
Kill agent |
| POST | /api/agents/{id}/message |
Send message (blocking) |
| POST | /api/agents/{id}/message/stream |
Send message (SSE stream) |
| GET | /api/agents/{id}/session |
Get conversation history |
| GET | /api/agents/{id}/ws |
WebSocket chat |
| POST | /api/agents/{id}/session/reset |
Reset session |
| POST | /api/agents/{id}/session/compact |
LLM-based compaction |
| POST | /api/agents/{id}/stop |
Cancel current run |
| PUT | /api/agents/{id}/model |
Switch model |
| Workflows | ||
| GET | /api/workflows |
List workflows |
| POST | /api/workflows |
Create workflow |
| POST | /api/workflows/{id}/run |
Run workflow |
| GET | /api/workflows/{id}/runs |
List workflow runs |
| Triggers | ||
| GET | /api/triggers |
List triggers |
| POST | /api/triggers |
Create trigger |
| PUT | /api/triggers/{id} |
Update trigger |
| DELETE | /api/triggers/{id} |
Delete trigger |
| Memory | ||
| GET | /api/memory/agents/{id}/kv |
List KV pairs |
| GET | /api/memory/agents/{id}/kv/{key} |
Get KV value |
| PUT | /api/memory/agents/{id}/kv/{key} |
Set KV value |
| DELETE | /api/memory/agents/{id}/kv/{key} |
Delete KV value |
| Channels | ||
| GET | /api/channels |
List channels (40 adapters) |
| Templates | ||
| GET | /api/templates |
List templates |
| GET | /api/templates/{name} |
Get template |
| Sessions | ||
| GET | /api/sessions |
List sessions |
| DELETE | /api/sessions/{id} |
Delete session |
| Model Catalog | ||
| GET | /api/models |
Full model catalog (51+ models) |
| GET | /api/models/{id} |
Model details |
| GET | /api/models/aliases |
List 23 model aliases |
| GET | /api/providers |
Provider list with auth status |
| Provider Config | ||
| POST | /api/providers/{name}/key |
Set provider API key |
| DELETE | /api/providers/{name}/key |
Remove provider API key |
| POST | /api/providers/{name}/test |
Test provider connectivity |
| Skills & Marketplace | ||
| GET | /api/skills |
List installed skills (60 bundled) |
| POST | /api/skills/install |
Install skill |
| POST | /api/skills/uninstall |
Uninstall skill |
| POST | /api/skills/create |
Create new skill |
| GET | /api/marketplace/search |
Search FangHub |
| ClawHub | ||
| GET | /api/clawhub/search |
Search ClawHub |
| GET | /api/clawhub/browse |
Browse ClawHub |
| GET | /api/clawhub/skill/{slug} |
Skill details |
| POST | /api/clawhub/install |
Install from ClawHub |
| MCP & A2A | ||
| GET | /api/mcp/servers |
MCP server connections |
| POST | /mcp |
MCP HTTP transport (JSON-RPC 2.0) |
| GET | /.well-known/agent.json |
A2A agent card |
| GET | /a2a/agents |
A2A agent list |
| POST | /a2a/tasks/send |
Send A2A task |
| GET | /a2a/tasks/{id} |
Get A2A task status |
| POST | /a2a/tasks/{id}/cancel |
Cancel A2A task |
| Audit & Security | ||
| GET | /api/audit/recent |
Recent audit logs |
| GET | /api/audit/verify |
Verify Merkle chain integrity |
| GET | /api/security |
Security status (16 systems) |
| Usage & Analytics | ||
| GET | /api/usage |
Usage statistics |
| GET | /api/usage/summary |
Usage summary with quota |
| GET | /api/usage/by-model |
Usage by model breakdown |
| Migration | ||
| GET | /api/migrate/detect |
Detect migration sources |
| POST | /api/migrate/scan |
Scan for importable data |
| POST | /api/migrate |
Run migration |
| OpenAI Compatible | ||
| POST | /v1/chat/completions |
OpenAI-compatible chat |
| GET | /v1/models |
OpenAI-compatible model list |
File: docs/architecture.md
OpenFang Architecture
This document describes the internal architecture of OpenFang, the open-source Agent Operating System built in Rust. It covers the crate structure, kernel boot sequence, agent lifecycle, memory substrate, LLM driver abstraction, capability-based security model, the OFP wire protocol, the security hardening stack, the channel and skill systems, and the agent stability subsystems.
Table of Contents
- Crate Structure
- Kernel Boot Sequence
- Agent Lifecycle
- Agent Loop Stability
- Memory Substrate
- LLM Driver Abstraction
- Model Catalog
- Capability-Based Security Model
- Security Hardening
- Channel System
- Skill System
- MCP and A2A Protocols
- Wire Protocol (OFP)
- Desktop Application
- Subsystem Diagram
Crate Structure
OpenFang is organized as a Cargo workspace with 14 crates (13 code crates + xtask). Dependencies flow downward (lower crates depend on nothing above them).
openfang-cli CLI interface, daemon auto-detect, MCP server
|
openfang-desktop Tauri 2.0 desktop app (WebView + system tray)
|
openfang-api REST/WS/SSE API server (Axum 0.8), 76 endpoints
|
openfang-kernel Kernel: assembles all subsystems, workflow engine, RBAC, metering
|
+-- openfang-runtime Agent loop, 3 LLM drivers, 23 tools, WASM sandbox, MCP, A2A
+-- openfang-channels 40 channel adapters, bridge, formatter, rate limiter
+-- openfang-wire OFP peer-to-peer networking with HMAC-SHA256 auth
+-- openfang-migrate Migration engine (OpenClaw YAML->TOML)
+-- openfang-skills 60 bundled skills, FangHub marketplace, ClawHub client
|
openfang-memory SQLite memory substrate, sessions, semantic search, usage tracking
|
openfang-types Shared types: Agent, Capability, Event, Memory, Message, Tool, Config,
Taint, ManifestSigning, ModelCatalog, MCP/A2A config, Web configCrate Responsibilities
| Crate | Description |
|---|---|
| openfang-types | Core type definitions used across all crates. Defines AgentManifest, AgentId, Capability, Event, ToolDefinition, KernelConfig, OpenFangError, taint tracking (TaintLabel, TaintSet), Ed25519 manifest signing, model catalog types (ModelCatalogEntry, ProviderInfo, ModelTier), tool compatibility mappings (21 OpenClaw-to-OpenFang), MCP/A2A config types, and web config types. All config structs use #[serde(default)] for forward-compatible TOML parsing. |
| openfang-memory | SQLite-backed memory substrate (schema v5). Uses Arc<Mutex<Connection>> with spawn_blocking for async bridge. Provides structured KV storage, semantic search with vector embeddings, knowledge graph (entities and relations), session management, task board, usage event persistence (usage_events table, UsageStore), and canonical sessions for cross-channel memory. Five schema versions: V1 core, V2 collab, V3 embeddings, V4 usage, V5 canonical_sessions. |
| openfang-runtime | Agent execution engine. Contains the agent loop (run_agent_loop, run_agent_loop_streaming), 3 native LLM drivers (Anthropic, Gemini, OpenAI-compatible covering 20 providers), 23 built-in tools, WASM sandbox (Wasmtime with dual fuel+epoch metering), MCP client/server (JSON-RPC 2.0 over stdio/SSE), A2A protocol (AgentCard, task management), web search engine (4 providers: Tavily/Brave/Perplexity/DuckDuckGo), web fetch with SSRF protection, loop guard (SHA256-based tool loop detection), session repair (history validation), LLM session compactor (block-aware), Merkle hash chain audit trail, and embedding driver. Defines the KernelHandle trait that enables inter-agent tools without circular crate dependencies. |
| openfang-kernel | The central coordinator. OpenFangKernel assembles all subsystems: AgentRegistry, AgentScheduler, CapabilityManager, EventBus, Supervisor, WorkflowEngine, TriggerEngine, BackgroundExecutor, WasmSandbox, ModelCatalog, MeteringEngine, ModelRouter, AuthManager (RBAC), HeartbeatMonitor, SetupWizard, SkillRegistry, MCP connections, and WebToolsContext. Implements KernelHandle for inter-agent operations. Handles agent spawn/kill, message dispatch, workflow execution, trigger evaluation, capability inheritance validation, and graceful shutdown with state persistence. |
| openfang-api | HTTP API server built on Axum 0.8 with 76 endpoints. Routes for agents, workflows, triggers, memory, channels, templates, models, providers, skills, ClawHub, MCP, health, status, version, and shutdown. WebSocket handler for real-time agent chat with streaming. SSE endpoint for streaming responses. OpenAI-compatible endpoints (POST /v1/chat/completions, GET /v1/models). A2A endpoints (/.well-known/agent.json, /a2a/*). Middleware: Bearer token auth, request ID injection, structured request logging, GCRA rate limiter (cost-aware), security headers (CSP, X-Frame-Options, etc.), health endpoint redaction. |
| openfang-channels | Channel bridge layer with 40 adapters. Each adapter implements the ChannelAdapter trait. Includes: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, SMS, Webhook, Teams, Mattermost, IRC, Google Chat, Twitch, Rocket.Chat, Zulip, XMPP, LINE, Viber, Messenger, Reddit, Mastodon, Bluesky, Feishu, Revolt, Nextcloud, Guilded, Keybase, Threema, Nostr, Webex, Pumble, Flock, Twist, Mumble, DingTalk, Discourse, Gitter, Ntfy, Gotify, LinkedIn. Features: AgentRouter for message routing, BridgeManager for lifecycle coordination, ChannelRateLimiter (per-user DashMap tracking), formatter.rs (Markdown to TelegramHTML/SlackMrkdwn/PlainText), ChannelOverrides (model/system_prompt/dm_policy/group_policy/rate_limit/threading/output_format), DM/group policy enforcement. |
| openfang-wire | OpenFang Protocol (OFP) for peer-to-peer agent communication. JSON-framed messages over TCP with HMAC-SHA256 mutual authentication (nonce + constant-time verify via subtle). PeerNode listens for connections and manages peers. PeerRegistry tracks known remote peers and their agents. |
| openfang-cli | Clap-based CLI. Supports all commands: init, start, status, doctor, agent spawn/list/chat/kill, workflow list/create/run, trigger list/create/delete, migrate, skill install/list/remove/search/create, channel list/setup/test/enable/disable, config show/edit, chat, mcp. Daemon auto-detect: checks ~/.openfang/daemon.json and health pings; uses HTTP when a daemon is running, boots an in-process kernel as fallback. Built-in MCP server mode. |
| openfang-desktop | Tauri 2.0 native desktop application. Boots the kernel in-process, runs the axum server on a background thread, and points a WebView at http://127.0.0.1:{random_port}. Features: system tray (Show/Browser/Status/Quit), single-instance enforcement, desktop notifications, hide-to-tray on close. IPC commands: get_port, get_status. Mobile-ready with #[cfg(desktop)] guards. |
| openfang-migrate | Migration engine. Supports OpenClaw (~/.openclaw/). Converts YAML configs to TOML, maps tool names, maps provider names, imports agent manifests, copies memory files, converts channel configs. Produces a MigrationReport with imported items, skipped items, and warnings. |
| openfang-skills | Skill system for pluggable tool bundles. 60 bundled skills compiled via include_str!(). Skills are skill.toml + Python/WASM/Node.js/PromptOnly code. SkillManifest defines metadata, runtime config, provided tools, and requirements. SkillRegistry manages installed and bundled skills. FangHubClient connects to FangHub marketplace. ClawHubClient connects to clawhub.ai for cross-ecosystem skill discovery. SKILL.md parser for OpenClaw compatibility (YAML frontmatter + Markdown body). SkillVerifier with SHA256 verification. Prompt injection scanner (scan_prompt_content()) detects override attempts, data exfiltration, and shell references. |
| xtask | Build automation tasks (cargo-xtask pattern). |
Kernel Boot Sequence
When OpenFangKernel::boot_with_config() is called (either by the daemon or in-process by the CLI/desktop app), the following sequence executes:
/* Detailed source-code truncated for AI context efficiency. */When the daemon wraps the kernel in Arc, additional steps occur:
15. Set self-handle (weak Arc reference for trigger dispatch)
16. Connect to MCP servers
- Background connect to configured MCP servers (stdio/SSE)
- Namespace tools as mcp_{server}_{tool}
- Store connections in kernel.mcp_connections
17. Start heartbeat monitor
- Background tokio task for agent health checks
- Publishes HealthCheckFailed events on anomalies
18. Start background agent loops (continuous, periodic, proactive)Agent Lifecycle
States
spawn message/tick kill
| | |
v v v
[Running] <------------> [Running] ---------> [Terminated]
| ^
| shutdown |
+----------> [Suspended] ---------------------+
| reboot/restore
+------> [Running]- Running: Agent is active and can receive messages.
- Suspended: Agent is paused (e.g., during daemon shutdown). Persisted to SQLite for restore on next boot.
- Terminated: Agent has been killed. Removed from registry and persistent storage.
Spawn Flow
- Generate new
AgentId(UUID v4) andSessionId. - Create a session in the memory substrate.
- Parse the manifest and extract capabilities.
- Validate capability inheritance (
validate_capability_inheritance()prevents privilege escalation). - Grant capabilities via
CapabilityManager. - Register with the
AgentScheduler(quota tracking). - Create
AgentEntryand register inAgentRegistry. - Persist to SQLite via
memory.save_agent(). - If agent has a parent, update parent's children list.
- Register proactive triggers (if schedule mode is
Proactive). - Publish
Lifecycle::Spawnedevent and evaluate triggers.
Message Flow
- RBAC check:
AuthManagerresolves channel identity and checks user role permissions. - Channel policy check:
ChannelBridgeHandle.authorize_channel_user()enforces DM/group policy. - Quota check:
AgentSchedulerverifies the agent has not exceeded its token-per-hour limit. - Entry lookup: Fetch
AgentEntryfrom the registry. - Module dispatch: Based on
manifest.module:builtin:chator unrecognized: LLM agent loopwasm:path/to/module.wasm: WASM sandbox executionpython:path/to/script.py: Python subprocess execution (env_clear() + selective vars)
- LLM agent loop (for
builtin:chat):
a. Load or create session from memory.
b. Load canonical context summary (cross-channel memory) into system prompt.
c. Append stability guidelines to system prompt.
d. Resolve LLM driver (per-agent override or kernel default).
e. Gather available tools (filtered by capabilities + skill tools + MCP tools).
f. Initialize loop guard (tool loop detection).
g. Run session repair (validate and fix message history).
h. Run iterative loop: send messages to LLM, execute tool calls, accumulate results.
i. Auto-compact session if threshold exceeded (block-aware compaction).
j. Save updated session and canonical session back to memory. - Cost estimation:
MeteringEngine.estimate_cost_with_catalog()computes cost in USD. - Record usage: Update quota tracking with token counts; persist usage event.
- Return result:
AgentLoopResultwith response text, token usage, iteration count, andcost_usd.
Kill Flow
- Check caller has
AgentKill(target_name)capability. - Remove from
AgentRegistry. - Stop background loops via
BackgroundExecutor. - Unregister from
AgentScheduler. - Revoke all capabilities.
- Unsubscribe from
EventBus. - Remove triggers.
- Remove from persistent storage (SQLite).
Agent Loop Stability
The agent loop includes multiple hardening layers to prevent runaway behavior:
Loop Guard
LoopGuard detects when an agent is stuck calling the same tool with the same parameters. Uses SHA256 hashing of (tool_name, params) to identify repetition.
- Warn threshold (default 3): Logs a warning and injects a hint to the LLM.
- Block threshold (default 5): Refuses the tool call and returns an error to the LLM.
- Circuit breaker (default 30): Terminates the agent loop entirely.
Configured via LoopGuardConfig.
Session Repair
validate_and_repair() runs before each agent loop iteration to ensure message history consistency:
- Drops orphaned
ToolResultmessages (no matchingToolUse). - Removes empty messages.
- Merges consecutive same-role messages.
Tool Result Truncation
truncate_tool_result() enforces a 50,000 character hard cap on tool output. Truncated results include a marker showing the original size.
Tool Timeout
All tool executions are wrapped in a universal 60-second tokio::time::timeout. Tools that exceed this limit return a timeout error to the LLM rather than hanging indefinitely.
Max Continuations
MAX_CONTINUATIONS = 3 prevents infinite "Please continue" loops. After 3 continuation attempts, the agent returns its partial response rather than requesting another round.
Inter-Agent Depth Limit
MAX_AGENT_CALL_DEPTH = 5 enforced via tokio::task_local! in the tool runner. Prevents unbounded recursive agent-to-agent calls.
Stability Guidelines
STABILITY_GUIDELINES are appended to every agent's system prompt. These contain anti-loop and anti-retry behavioral rules that the LLM follows to avoid degenerate patterns.
Block-Aware Compaction
The session compactor handles all content block types (Text, ToolUse, ToolResult, Image) rather than assuming text-only messages. Auto-compaction triggers when the session exceeds the configured threshold (default 80% of context window), keeping the most recent messages (default 20).
Memory Substrate
The memory substrate (openfang-memory) provides six layers of storage:
1. Structured KV Store
Per-agent key-value storage backed by SQLite. Keys are strings, values are JSON. Used by the memory_store and memory_recall tools.
A shared memory namespace (fixed agent ID 00000000-...01) enables cross-agent data sharing.
agent_id | key | value
---------|-------------|------------------
uuid-a | preferences | {"theme": "dark"}
uuid-b | state | {"step": 3}
shared | project | {"name": "foo"}2. Semantic Search
Vector embeddings for similarity-based memory retrieval. Documents are embedded using the configured embedding driver and stored with their vectors. Queries are embedded at search time and matched by cosine similarity.
3. Knowledge Graph
Entity-relation storage for structured knowledge. Agents can store entities (with types and properties) and relations between them. Supports graph traversal queries.
4. Session Manager
Conversation history storage. Each agent has a session containing its message history (user, assistant, tool use, tool result, image). Sessions track context window token counts. Sessions are persisted to SQLite and restored on kernel reboot.
5. Task Board
A shared task queue for multi-agent collaboration:
task_post: Create a task with title, description, and optional assignee.task_claim: Claim the next available task.task_complete: Mark a task as done with a result.task_list: List tasks filtered by status (pending, claimed, completed).
6. Usage and Canonical Sessions
- Usage tracking:
usage_eventstable persists token counts, cost estimates, and model usage per agent.UsageStoreprovides query and aggregation APIs. - Canonical sessions: Cross-channel memory.
CanonicalSessiontracks a user's conversation context across multiple channels. Compaction produces summaries that are injected into system prompts. Stored incanonical_sessionstable (schema v5).
SQLite Architecture
All memory operations go through Arc<Mutex<Connection>> with Tokio's spawn_blocking for async bridging. This ensures thread safety without requiring an async SQLite driver. Schema migrations run automatically through five versions.
LLM Driver Abstraction
The LlmDriver trait (openfang-runtime) provides a unified interface for all LLM providers:
#[async_trait]
pub trait LlmDriver: Send + Sync {
async fn send_message(
&self,
model: &str,
system_prompt: &str,
messages: &[Message],
tools: &[ToolDefinition],
) -> Result<LlmResponse, OpenFangError>;
async fn send_message_streaming(
&self,
model: &str,
system_prompt: &str,
messages: &[Message],
tools: &[ToolDefinition],
tx: mpsc::Sender<StreamEvent>,
) -> Result<LlmResponse, OpenFangError>;
fn key_required(&self) -> bool;
}Provider Architecture
Three native driver implementations cover all 20 providers with 51 models:
AnthropicDriver: Native Anthropic Messages API. Handles Claude-specific features (content blocks including images, tool use blocks, streaming deltas). Supports
ContentBlock::Imagewith media type validation and 5MB cap.GeminiDriver: Native Google Gemini API (v1beta). Uses
x-goog-api-keyauth,systemInstruction,functionDeclarations,streamGenerateContent?alt=sse. Maps Gemini function call responses to the unifiedToolUsestop reason.OpenAiCompatDriver: OpenAI-compatible Chat Completions API. Works with any provider that implements the OpenAI API format. Configured with different base URLs per provider. Covers 18+ providers including OpenAI, DeepSeek, Groq, Mistral, Together, and local runners.
Provider Configuration
| Provider | Driver | Base URL | Key Required |
|---|---|---|---|
anthropic |
Anthropic | https://api.anthropic.com |
Yes |
gemini |
Gemini | https://generativelanguage.googleapis.com |
Yes |
openai |
OpenAI-compat | https://api.openai.com |
Yes |
deepseek |
OpenAI-compat | https://api.deepseek.com |
Yes |
groq |
OpenAI-compat | https://api.groq.com/openai |
Yes |
openrouter |
OpenAI-compat | https://openrouter.ai/api |
Yes |
mistral |
OpenAI-compat | https://api.mistral.ai |
Yes |
together |
OpenAI-compat | https://api.together.xyz |
Yes |
fireworks |
OpenAI-compat | https://api.fireworks.ai/inference |
Yes |
perplexity |
OpenAI-compat | https://api.perplexity.ai |
Yes |
cohere |
OpenAI-compat | https://api.cohere.ai |
Yes |
ai21 |
OpenAI-compat | https://api.ai21.com |
Yes |
cerebras |
OpenAI-compat | https://api.cerebras.ai |
Yes |
sambanova |
OpenAI-compat | https://api.sambanova.ai |
Yes |
huggingface |
OpenAI-compat | https://api-inference.huggingface.co |
Yes |
xai |
OpenAI-compat | https://api.x.ai |
Yes |
replicate |
OpenAI-compat | https://api.replicate.com |
Yes |
ollama |
OpenAI-compat | http://localhost:11434 |
No |
vllm |
OpenAI-compat | http://localhost:8000 |
No |
lmstudio |
OpenAI-compat | http://localhost:1234 |
No |
Per-Agent Driver Resolution
Each agent can override the kernel's default provider:
[model]
provider = "openai" # Different from kernel default
model = "gpt-4o"
api_key_env = "OPENAI_API_KEY" # Custom key env var
base_url = "https://custom.api.com" # Optional custom endpointWhen resolving the driver for an agent:
- If the agent uses the same provider as the kernel default (and no custom key/URL), reuse the kernel's shared driver instance.
- Otherwise, create a dedicated driver for that agent.
Retry and Rate Limiting
LLM calls use exponential backoff for rate-limited (429) and overloaded (529) responses. The retry logic is built into the driver layer. All API key fields use Zeroizing<String> for automatic memory wipe on drop.
Model Catalog
The ModelCatalog (openfang-runtime/src/model_catalog.rs) provides a registry of all known models, providers, and aliases.
Registry Contents
- 51 builtin models across 20+ model families (Claude, GPT, Gemini, DeepSeek, Llama, Mixtral, Command, Jamba, Grok, etc.)
- 20+ aliases for convenience (e.g.,
claude->claude-sonnet-4-20250514,grok->grok-2) - 20 providers with authentication status detection
Types
ModelCatalogEntry: Model ID, display name, provider, tier, context window, cost rates.ProviderInfo: Provider name, driver type, base URL, key env var, auth status.ModelTier: Frontier, Smart, Balanced, Fast (maps to cost and capability tiers).AuthStatus: Detected, NotDetected (based on env var presence without reading secrets).
Integration Points
- Metering:
estimate_cost_with_catalog()uses catalog entries as the pricing source. - Router:
ModelRouter.validate_models()andresolve_aliases()reference the catalog. - API: 4 endpoints (
/api/models,/api/models/{id},/api/models/aliases,/api/providers). - Channels:
/modelsand/providerschat commands viaChannelBridgeHandle.
Capability-Based Security Model
Every agent operation is subject to capability checks. Capabilities are declared in the agent manifest and enforced at runtime.
Capability Types
pub enum Capability {
// Tool access
ToolInvoke(String), // Access to a specific tool (e.g., "file_read")
ToolAll, // Access to all tools
// Memory access
MemoryRead(String), // Read scope (e.g., "*", "self.*")
MemoryWrite(String), // Write scope
// Network access
NetConnect(String), // Connect to host (e.g., "api.example.com", "*")
// Agent operations
AgentSpawn, // Can spawn new agents
AgentMessage(String), // Can message agents matching pattern
AgentKill(String), // Can kill agents matching pattern
// Shell access
ShellExec(String), // Can execute shell commands matching pattern
// OFP networking
OfpDiscover, // Can discover remote peers
OfpConnect(String), // Can connect to specific peers
OfpAdvertise, // Can advertise to peers
}Capability Inheritance Validation
validate_capability_inheritance() prevents privilege escalation when agents spawn child agents. A child agent can never receive capabilities that its parent does not hold. This is enforced at spawn time before any capabilities are granted.
Manifest Declaration
[capabilities]
tools = ["file_read", "file_list", "web_fetch"]
memory_read = ["*"]
memory_write = ["self.*"]
network = ["api.anthropic.com"]
shell = []
agent_spawn = false
agent_message = ["coder", "researcher"]
agent_kill = []
ofp_discover = false
ofp_connect = []Enforcement Flow
Tool invocation request
|
v
CapabilityManager.check(agent_id, ToolInvoke("file_read"))
|
+-- Granted --> Validate path (traversal check) --> Execute tool
|
+-- Denied --> Return "Permission denied" error to LLMThe CapabilityManager uses a DashMap<AgentId, Vec<Capability>> for lock-free concurrent access. Capabilities are granted at spawn time (after inheritance validation) and revoked at kill time.
The tool runner also enforces capabilities by filtering the tool list before passing it to the LLM. If the LLM hallucinates a tool name outside the agent's granted list, the tool runner rejects it with a permission error.
Security Hardening
OpenFang implements 16 security systems organized into critical fixes and state-of-the-art defenses:
Path Traversal Prevention
safe_resolve_path() and safe_resolve_parent() in WASM host functions prevent directory traversal attacks. Path validation in tool_runner.rs (validate_path) protects file tools. Capability check runs BEFORE path resolution (deny first, then validate).
Subprocess Isolation
subprocess_sandbox.rs provides a secure execution environment for Python/Node skill runtimes. All subprocess invocations use cmd.env_clear() followed by selective environment variable injection, preventing secret leakage.
SSRF Protection
is_ssrf_target() and is_private_ip() block requests to private IPs and cloud metadata endpoints (169.254.169.254, etc.). DNS resolution is checked to prevent DNS rebinding attacks. Applied in host_net_fetch and web_fetch.rs.
WASM Dual Metering
WASM sandbox uses both Wasmtime fuel metering (instruction count) and epoch interruption (wall-clock timeout via watchdog thread). This prevents both CPU-bound and time-bound runaway modules.
Merkle Audit Trail
audit.rs implements a Merkle hash chain where each audit entry includes a hash of the previous entry. This provides tamper-evident logging of all agent actions.
Information Flow Taint Tracking
taint.rs in openfang-types implements taint labels and taint sets. Data from external sources carries taint labels that propagate through operations, enabling information flow analysis.
Ed25519 Manifest Signing
manifest_signing.rs provides Ed25519 digital signatures for agent manifests. Ensures manifest integrity and authenticity.
OFP HMAC-SHA256 Mutual Auth
Wire protocol authentication uses hmac_sign(secret, nonce + node_id) on both handshake sides. Nonce prevents replay attacks. Constant-time verification via the subtle crate prevents timing attacks.
Security Headers Middleware
CSP, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, and Permissions-Policy headers on all API responses.
GCRA Rate Limiter
Generic Cell Rate Algorithm with cost-aware token buckets. Per-IP tracking with stale entry cleanup. Configurable burst and sustained rates.
Health Endpoint Redaction
Public health endpoint (/api/health) returns minimal status. Detailed health (/api/health/detail) requires authentication and shows database stats, agent counts, and subsystem status.
Prompt Injection Scanner
scan_prompt_content() in the skills crate detects override attempts, data exfiltration patterns, and shell references in skill content. Applied to all bundled and installed skills and to SKILL.md auto-conversion.
Secret Zeroization
All LLM driver API key fields use Zeroizing<String> from the zeroize crate. Keys are automatically wiped from memory when the driver is dropped. Debug impls on config structs redact secret fields.
Localhost-Only Fallback
When no API key is configured, the system falls back to localhost-only mode, preventing accidental exposure of unauthenticated endpoints.
Loop Guard and Session Repair
See Agent Loop Stability above.
Security Dependencies
sha2, hmac, hex, subtle, ed25519-dalek, rand, zeroize, governor
Channel System
The channel system (openfang-channels) provides 40 adapters for messaging platform integration.
Adapter List
| Wave | Channels |
|---|---|
| Original (15) | Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, SMS, Webhook, Teams, Mattermost, IRC, Google Chat, Twitch, Rocket.Chat |
| Wave 2 (8) | Zulip, XMPP, LINE, Viber, Messenger, Reddit, Mastodon, Bluesky |
| Wave 3 (8) | Feishu, Revolt, Nextcloud, Guilded, Keybase, Threema, Nostr, Webex |
| Wave 4 (9) | Pumble, Flock, Twist, Mumble, DingTalk, Discourse, Gitter, Ntfy, Gotify, LinkedIn |
Channel Features
- Channel Overrides: Per-channel configuration of model, system prompt, DM policy, group policy, rate limit, threading, and output format.
- DM/Group Policy:
DmPolicyandGroupPolicyenums enforce who can interact with agents in direct messages vs. group chats. - Formatter:
formatter.rsconverts Markdown to platform-specific formats (TelegramHTML, SlackMrkdwn, PlainText). - Rate Limiter:
ChannelRateLimiterwith per-user DashMap tracking prevents message flooding. - Threading:
send_in_thread()trait method for platforms that support threaded conversations. - Chat Commands:
/models,/providers,/new,/compact,/model,/stop,/usage,/thinkhandled byChannelBridgeHandle.
Skill System
The skill system (openfang-skills) provides 60 bundled skills and supports external skill installation.
Skill Types
- Python: Python scripts executed in subprocess sandbox.
- Node.js: Node.js scripts (OpenClaw compatibility).
- WASM: WebAssembly modules executed in the WASM sandbox.
- PromptOnly: Skills that inject context into the LLM system prompt without code execution.
Bundled Skills (60)
Compiled into the binary via include_str!() in bundled.rs. Three tiers:
- Tier 1 (8): github, docker, web-search, code-reviewer, sql-analyst, git-expert, sysadmin, writing-coach
- Tier 2 (6): kubernetes, terraform, aws, jira, data-analyst, api-tester
- Tier 3 (6): pdf-reader, slack-tools, notion, sentry, mongodb, regex-expert
- Plus 40 additional skills added in the expansion phase
Security Pipeline
All skills pass through a security pipeline before activation:
- SHA256 verification (
SkillVerifier): Ensures skill content matches its declared hash. - Prompt injection scan (
scan_prompt_content()): Detects malicious patterns in skill prompts and descriptions. - Trust boundary markers: Skill-injected context in system prompts is wrapped with trust boundary markers.
- Subprocess env_clear(): Skill code execution uses environment isolation.
Ecosystem Bridges
- FangHub: Native OpenFang marketplace (
FangHubClient). - ClawHub: Cross-ecosystem compatibility (
ClawHubClientconnects to clawhub.ai). - SKILL.md Parser: Auto-converts OpenClaw SKILL.md format (YAML frontmatter + Markdown body) to
skill.toml. - Tool Compat: 21 OpenClaw-to-OpenFang tool name mappings in
tool_compat.rs.
MCP and A2A Protocols
Model Context Protocol (MCP)
OpenFang implements both MCP client and server:
- MCP Client (
mcp.rs): JSON-RPC 2.0 over stdio or SSE transports. Connects to external MCP servers. Tools are namespaced asmcp_{server}_{tool}to prevent collisions. Background connection instart_background_agents(). - MCP Server (
mcp_server.rs): Exposes OpenFang's 23 built-in tools via the MCP protocol. Enables external tools to use OpenFang as a tool provider. - Configuration:
KernelConfig.mcp_servers(Vec ofMcpServerConfigEntrywith name, command, args, env, transport). - API:
/api/mcp/serversreturns configured and connected servers with their tool lists.
Agent-to-Agent Protocol (A2A)
Google's A2A protocol for inter-system agent communication:
- A2A Server (
a2a.rs): PublishesAgentCardat/.well-known/agent.json. Handles task lifecycle (send, get, cancel). - A2A Client (
a2a.rs): Discovers and communicates with remote A2A-compatible agents. - Endpoints:
/.well-known/agent.json,/a2a/agents,/a2a/tasks/send,/a2a/tasks/{id},/a2a/tasks/{id}/cancel. - Configuration:
KernelConfig.a2a(optionalA2aConfig).
Wire Protocol (OFP)
The OpenFang Protocol (OFP) enables peer-to-peer agent communication across machines.
Architecture
Machine A Machine B
+-----------+ +-----------+
| PeerNode | ---TCP (JSON)------> | PeerNode |
| port 4200 | <---TCP (JSON)------ | port 4200 |
+-----------+ +-----------+
| PeerRegistry | | PeerRegistry |
| - Known peers | | - Known peers |
| - Remote agents | | - Remote agents |
+---------------+ +---------------+HMAC-SHA256 Mutual Authentication
Before any protocol messages are exchanged, both peers authenticate:
- Initiator sends
{nonce, node_id, hmac_sign(shared_secret, nonce + node_id)}. - Responder verifies HMAC using constant-time comparison (
subtlecrate). - Responder sends its own
{nonce, node_id, hmac}challenge. - Initiator verifies.
- On mutual success, the connection is established.
Configured via PeerConfig.shared_secret (required) and NetworkConfig.shared_secret in config.toml.
Protocol Messages
All messages are JSON-framed (newline-delimited JSON over TCP):
WireMessage {
id: UUID,
sender: PeerId,
payload: WireRequest | WireResponse
}Request types:
Discover-- Request peer information and agent listAdvertise-- Announce local agents to a peerRouteMessage-- Send a message to a remote agentPing-- Keepalive
Response types:
DiscoverResponse-- Peer info and agent listRouteResponse-- Agent's response to a routed messagePong-- Keepalive response
PeerRegistry
Tracks all known peers and their advertised agents:
pub struct PeerEntry {
pub id: PeerId,
pub addr: SocketAddr,
pub agents: Vec<RemoteAgent>,
pub last_seen: Instant,
}
pub struct RemoteAgent {
pub agent_id: String,
pub name: String,
pub description: String,
pub tags: Vec<String>,
}Capability Gating
OFP operations require capabilities:
OfpDiscover-- Required to send discover requestsOfpConnect(addr)-- Required to connect to a specific peerOfpAdvertise-- Required to advertise agents to peers
Desktop Application
The desktop app (openfang-desktop) wraps the full OpenFang stack in a native Tauri 2.0 application.
Architecture
+-------------------------------------------+
| Tauri 2.0 Shell |
| +---------------------------------------+ |
| | WebView (WebKit/WebView2) | |
| | -> http://127.0.0.1:{random_port} | |
| +---------------------------------------+ |
| +---------------------------------------+ |
| | System Tray | |
| | Show | Browser | Status | Quit | |
| +---------------------------------------+ |
| +---------------------------------------+ |
| | Background Thread | |
| | +- Own Tokio Runtime | |
| | +- OpenFangKernel (in-process) | |
| | +- Axum Server (build_router()) | |
| | +- ServerHandle { port, shutdown } | |
| +---------------------------------------+ |
+-------------------------------------------+Features
- In-process kernel: No separate daemon needed. The kernel boots inside the app process.
- Random port: Avoids port conflicts. Port communicated via IPC command
get_port. - System tray: Show Window, Open in Browser, Status indicator, Quit. Double-click to show.
- Single instance:
tauri-plugin-single-instanceprevents multiple app instances. - Notifications:
tauri-plugin-notificationfor desktop alerts. - Hide to tray: Window close hides to tray instead of quitting (desktop platforms).
- Mobile ready:
#[cfg(desktop)]guards on tray and single-instance;#[cfg_attr(mobile, tauri::mobile_entry_point)].
Subsystem Diagram
/* Detailed source-code truncated for AI context efficiency. */File: docs/channel-adapters.md
Channel Adapters
OpenFang connects to messaging platforms through 40 channel adapters, allowing users to interact with their agents across every major communication platform. Adapters span consumer messaging, enterprise collaboration, social media, community platforms, privacy-focused protocols, and generic webhooks.
All adapters share a common foundation: graceful shutdown via watch::channel, exponential backoff on connection failures, Zeroizing<String> for secrets, automatic message splitting for platform limits, per-channel model/prompt overrides, DM/group policy enforcement, per-user rate limiting, and output formatting (Markdown, TelegramHTML, SlackMrkdwn, PlainText).
Table of Contents
- All 40 Channels
- Channel Configuration
- Channel Overrides
- Formatter, Rate Limiter, and Policies
- Telegram
- Discord
- Slack
- Feishu / Lark
- Signal
- Matrix
- WebChat (Built-in)
- Agent Routing
- Writing Custom Adapters
All 40 Channels
Core (7)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Telegram | Bot API long-polling | TELEGRAM_BOT_TOKEN |
Telegram |
| Discord | Gateway WebSocket v10 | DISCORD_BOT_TOKEN |
Discord |
| Slack | Socket Mode WebSocket | SLACK_BOT_TOKEN, SLACK_APP_TOKEN |
Slack |
| Cloud API webhook | WA_ACCESS_TOKEN, WA_PHONE_ID, WA_VERIFY_TOKEN |
WhatsApp |
|
| Signal | signal-cli REST/JSON-RPC | (system service) | Signal |
| Matrix | Client-Server API /sync |
MATRIX_TOKEN |
Matrix |
| IMAP + SMTP | EMAIL_PASSWORD |
Email |
Enterprise (8)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Microsoft Teams | Bot Framework v3 webhook + OAuth2 | TEAMS_APP_ID, TEAMS_APP_SECRET |
Teams |
| Mattermost | WebSocket + REST v4 | MATTERMOST_TOKEN, MATTERMOST_URL |
Mattermost |
| Google Chat | Service account webhook | GOOGLE_CHAT_SA_KEY, GOOGLE_CHAT_SPACE |
Custom("google_chat") |
| Webex | Bot SDK WebSocket | WEBEX_BOT_TOKEN |
Custom("webex") |
| Feishu / Lark | Open Platform Webhook / WebSocket | FEISHU_APP_ID, FEISHU_APP_SECRET |
Custom("feishu") |
| Rocket.Chat | REST polling | ROCKETCHAT_TOKEN, ROCKETCHAT_URL |
Custom("rocketchat") |
| Zulip | Event queue long-polling | ZULIP_EMAIL, ZULIP_API_KEY, ZULIP_URL |
Custom("zulip") |
| XMPP | XMPP protocol (stub) | XMPP_JID, XMPP_PASSWORD, XMPP_SERVER |
Custom("xmpp") |
Social (8)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| LINE | Messaging API webhook | LINE_CHANNEL_SECRET, LINE_CHANNEL_TOKEN |
Custom("line") |
| Viber | Bot API webhook | VIBER_AUTH_TOKEN |
Custom("viber") |
| Facebook Messenger | Platform API webhook | MESSENGER_PAGE_TOKEN, MESSENGER_VERIFY_TOKEN |
Custom("messenger") |
| Mastodon | Streaming API WebSocket | MASTODON_TOKEN, MASTODON_INSTANCE |
Custom("mastodon") |
| Bluesky | AT Protocol WebSocket | BLUESKY_HANDLE, BLUESKY_APP_PASSWORD |
Custom("bluesky") |
| OAuth2 polling | REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USERNAME, REDDIT_PASSWORD |
Custom("reddit") |
|
| Messaging API polling | LINKEDIN_ACCESS_TOKEN |
Custom("linkedin") |
|
| Twitch | IRC gateway | TWITCH_TOKEN, TWITCH_CHANNEL |
Custom("twitch") |
Community (6)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| IRC | Raw TCP PRIVMSG | IRC_SERVER, IRC_NICK, IRC_PASSWORD |
Custom("irc") |
| Guilded | WebSocket | GUILDED_BOT_TOKEN |
Custom("guilded") |
| Revolt | WebSocket | REVOLT_BOT_TOKEN |
Custom("revolt") |
| Keybase | Bot API polling | KEYBASE_USERNAME, KEYBASE_PAPERKEY |
Custom("keybase") |
| Discourse | REST polling | DISCOURSE_API_KEY, DISCOURSE_URL |
Custom("discourse") |
| Gitter | Streaming API | GITTER_TOKEN |
Custom("gitter") |
Self-hosted (1)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Nextcloud Talk | REST polling | NEXTCLOUD_TOKEN, NEXTCLOUD_URL |
Custom("nextcloud") |
Privacy (3)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Threema | Gateway API webhook | THREEMA_ID, THREEMA_SECRET |
Custom("threema") |
| Nostr | NIP-01 relay WebSocket | NOSTR_PRIVATE_KEY, NOSTR_RELAY |
Custom("nostr") |
| Mumble | TCP text protocol | MUMBLE_SERVER, MUMBLE_USERNAME, MUMBLE_PASSWORD |
Custom("mumble") |
Workplace (4)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Pumble | Webhook | PUMBLE_WEBHOOK_URL, PUMBLE_TOKEN |
Custom("pumble") |
| Flock | Webhook | FLOCK_TOKEN |
Custom("flock") |
| Twist | API v3 polling | TWIST_TOKEN |
Custom("twist") |
| DingTalk | Robot API webhook | DINGTALK_TOKEN, DINGTALK_SECRET |
Custom("dingtalk") |
Notification (2)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| ntfy | SSE pub/sub | NTFY_TOPIC, NTFY_SERVER |
Custom("ntfy") |
| Gotify | WebSocket | GOTIFY_TOKEN, GOTIFY_URL |
Custom("gotify") |
Integration (1)
| Channel | Protocol | Env Vars | ChannelType Variant |
|---|---|---|---|
| Webhook | Generic HTTP with HMAC-SHA256 | WEBHOOK_URL, WEBHOOK_SECRET |
Custom("webhook") |
Channel Configuration
All channel configurations live in ~/.openfang/config.toml under the [channels] section. Each channel is a subsection:
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
default_agent = "assistant"
allowed_users = ["123456789"]
[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
default_agent = "coder"
[channels.slack]
bot_token_env = "SLACK_BOT_TOKEN"
app_token_env = "SLACK_APP_TOKEN"
default_agent = "ops"
# Enterprise example
[channels.teams]
app_id_env = "TEAMS_APP_ID"
app_secret_env = "TEAMS_APP_SECRET"
default_agent = "ops"
# Social example
[channels.mastodon]
token_env = "MASTODON_TOKEN"
instance = "https://mastodon.social"
default_agent = "social-media"Common Fields
bot_token_env/token_env-- The environment variable holding the bot/access token. OpenFang reads the token from this env var at startup. All secrets are stored asZeroizing<String>and wiped from memory on drop.default_agent-- The agent name (or ID) that receives messages when no specific routing applies.allowed_users-- Optional list of platform user IDs allowed to interact. Empty means allow all.overrides-- Optional per-channel behavior overrides (see Channel Overrides below).
Environment Variables Reference (Core Channels)
| Channel | Required Env Vars |
|---|---|
| Telegram | TELEGRAM_BOT_TOKEN |
| Discord | DISCORD_BOT_TOKEN |
| Slack | SLACK_BOT_TOKEN, SLACK_APP_TOKEN |
WA_ACCESS_TOKEN, WA_PHONE_ID, WA_VERIFY_TOKEN |
|
| Matrix | MATRIX_TOKEN |
EMAIL_PASSWORD |
Env vars for all other channels are listed in the All 40 Channels tables above.
Channel Overrides
Every channel adapter supports ChannelOverrides, which let you customize behavior per channel without modifying the agent manifest. Add an [channels.<name>.overrides] section in config.toml:
[channels.telegram.overrides]
model = "gemini-2.5-flash"
system_prompt = "You are a concise Telegram assistant. Keep replies under 200 words."
dm_policy = "respond"
group_policy = "mention_only"
rate_limit_per_user = 10
threading = true
output_format = "telegram_html"
usage_footer = "compact"Override Fields
| Field | Type | Default | Description |
|---|---|---|---|
model |
Option<String> |
Agent default | Override the LLM model for this channel. |
system_prompt |
Option<String> |
Agent default | Override the system prompt for this channel. |
dm_policy |
DmPolicy |
Respond |
How to handle direct messages. |
group_policy |
GroupPolicy |
MentionOnly |
How to handle group/channel messages. |
rate_limit_per_user |
u32 |
0 (unlimited) |
Max messages per minute per user. |
threading |
bool |
false |
Send replies as thread responses (platforms that support it). |
output_format |
Option<OutputFormat> |
Markdown |
Output format for this channel. |
usage_footer |
Option |
None | Whether to append token usage to responses. |
Formatter, Rate Limiter, and Policies
Output Formatter
The formatter module (openfang-channels/src/formatter.rs) converts Markdown output from the LLM into platform-native formats:
| OutputFormat | Target | Notes |
|---|---|---|
Markdown |
Standard Markdown | Default; passed through as-is. |
TelegramHtml |
Telegram HTML subset | Converts **bold** to , code `` to <code>, etc. |
SlackMrkdwn |
Slack mrkdwn | Converts **bold** to *bold*, links to ``, etc. |
PlainText |
Plain text | Strips all formatting. |
Per-User Rate Limiter
The ChannelRateLimiter (openfang-channels/src/rate_limiter.rs) uses a DashMap to track per-user message counts. When rate_limit_per_user is set on a channel's overrides, the limiter enforces a sliding-window cap of N messages per minute. Excess messages receive a polite rejection.
DM Policy
Controls how the adapter handles direct messages:
| DmPolicy | Behavior |
|---|---|
Respond |
Respond to all DMs (default). |
AllowedOnly |
Only respond to DMs from users in allowed_users. |
Ignore |
Silently drop all DMs. |
Group Policy
Controls how the adapter handles messages in group chats, channels, and rooms:
| GroupPolicy | Behavior |
|---|---|
All |
Respond to every message in the group. |
MentionOnly |
Only respond when the bot is @mentioned (default). |
CommandsOnly |
Only respond to /command messages. |
Ignore |
Silently ignore all group messages. |
Policy enforcement happens in dispatch_message() before the message reaches the agent loop. This means ignored messages consume zero LLM tokens.
Telegram
Prerequisites
- A Telegram bot token (from @BotFather)
Setup
- Open Telegram and message
@BotFather. - Send
/newbotand follow the prompts to create a new bot. - Copy the bot token.
- Set the environment variable:
export TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz- Add to config:
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
default_agent = "assistant"
# Optional: restrict to specific Telegram user IDs
# allowed_users = ["123456789"]
[channels.telegram.overrides]
# Optional: Telegram-native HTML formatting
# output_format = "telegram_html"
# group_policy = "mention_only"- Restart the daemon:
openfang startHow It Works
The Telegram adapter uses long-polling via the getUpdates API. It polls every few seconds with a 30-second long-poll timeout. On API failures, it applies exponential backoff (starting at 1 second, up to 60 seconds). Shutdown is coordinated via a watch::channel.
Messages from authorized users are converted to ChannelMessage events and routed to the configured agent. Responses are sent back via the sendMessage API. Long responses are automatically split into multiple messages to respect Telegram's 4096-character limit using the shared split_message() utility.
Per-User Identity (`telegram_user_id`)
Every inbound Telegram message exposes the sender's numeric Telegram user_id under message.metadata["telegram_user_id"] as a string. This is the stable, permanent identifier from message.from.id (or message.sender_chat.id for channel/group posts).
Display names are not unique and can change, so agents that need deterministic per-user behavior — RBAC, per-user workspaces, family-assistant style memory keyed by person — should key on telegram_user_id, not sender.display_name.
The bridge also injects the id into the prompt prefix when no sender_email is set:
[From: Alena (tg_id:554772934)] Hello!Agents can read the raw metadata field via tool calls that expose ChannelMessage.metadata (the prompt prefix is a convenience for plain LLM context). sender.platform_id continues to hold the chat_id (not user_id), since replies are addressed to the chat, not the user.
Interactive Setup
openfang channel setup telegramThis walks you through the setup interactively.
Discord
Prerequisites
- A Discord application and bot (from the Discord Developer Portal)
Setup
- Go to Discord Developer Portal.
- Click "New Application" and name it.
- Go to the Bot section and click "Add Bot".
- Copy the bot token.
- Under Privileged Gateway Intents, enable:
- Message Content Intent (required to read message content)
- Go to OAuth2 > URL Generator:
- Select scopes:
bot - Select permissions:
Send Messages,Read Message History - Copy the generated URL and open it to invite the bot to your server.
- Select scopes:
- Set the environment variable:
export DISCORD_BOT_TOKEN=MTIzNDU2Nzg5.ABCDEF.ghijklmnop- Add to config:
[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
default_agent = "coder"- Restart the daemon.
How It Works
The Discord adapter connects to the Discord Gateway via WebSocket (v10). It listens for MESSAGE_CREATE events and routes messages to the configured agent. Responses are sent via the REST API's channels/{id}/messages endpoint.
The adapter handles Gateway reconnection, heartbeating, and session resumption automatically.
Slack
Prerequisites
- A Slack app with Socket Mode enabled
Setup
- Go to Slack API and click "Create New App" > "From Scratch".
- Enable Socket Mode (Settings > Socket Mode):
- Generate an App-Level Token with scope
connections:write. - Copy the token (
xapp-...).
- Generate an App-Level Token with scope
- Go to OAuth & Permissions and add Bot Token Scopes:
chat:writeapp_mentions:readim:historyim:readim:write
- Install the app to your workspace.
- Copy the Bot User OAuth Token (
xoxb-...). - Set the environment variables:
export SLACK_APP_TOKEN=xapp-1-...
export SLACK_BOT_TOKEN=xoxb-...- Add to config:
[channels.slack]
bot_token_env = "SLACK_BOT_TOKEN"
app_token_env = "SLACK_APP_TOKEN"
default_agent = "ops"
[channels.slack.overrides]
# Optional: Slack-native mrkdwn formatting
# output_format = "slack_mrkdwn"
# threading = true- Restart the daemon.
How It Works
The Slack adapter uses Socket Mode, which establishes a WebSocket connection to Slack's servers. This avoids the need for a public webhook URL. The adapter receives events (app mentions, direct messages) and routes them to the configured agent. Responses are posted via the chat.postMessage Web API. When threading = true, replies are sent to the message's thread via thread_ts.
Prerequisites
- A Meta Business account with WhatsApp Cloud API access
Setup
- Go to Meta for Developers.
- Create a Business App.
- Add the WhatsApp product.
- Set up a test phone number (or use a production one).
- Copy:
- Phone Number ID
- Permanent Access Token
- Choose a Verify Token (any string you choose)
- Set environment variables:
export WA_PHONE_ID=123456789012345
export WA_ACCESS_TOKEN=EAABs...
export WA_VERIFY_TOKEN=my-secret-verify-token- Add to config:
[channels.whatsapp]
mode = "cloud_api"
phone_number_id_env = "WA_PHONE_ID"
access_token_env = "WA_ACCESS_TOKEN"
verify_token_env = "WA_VERIFY_TOKEN"
webhook_port = 8443
default_agent = "assistant"Set up a webhook in the Meta dashboard pointing to your server's public URL:
- URL:
https://your-domain.com:8443/webhook/whatsapp - Verify Token: the value you chose above
- Subscribe to:
messages
- URL:
Restart the daemon.
How It Works
The WhatsApp adapter runs an HTTP server (on the configured webhook_port) that receives incoming webhooks from the WhatsApp Cloud API. It handles webhook verification (GET) and message reception (POST). Responses are sent via the Cloud API's messages endpoint.
Feishu / Lark
Prerequisites
- A Feishu/Lark app created in open.feishu.cn
- App ID and App Secret
Setup
- Create a custom app in Feishu Open Platform.
- Enable the IM message event subscription for your app.
- Set environment variable:
export FEISHU_APP_SECRET=cli_xxx_secret- Add to config (default:
websocketmode):
[channels.feishu]
app_id = "cli_xxx"
app_secret_env = "FEISHU_APP_SECRET"
mode = "websocket"
default_agent = "assistant"- Restart the daemon.
Webhook Compatibility Mode
If you need the legacy callback flow, switch to webhook and expose a public callback URL:
[channels.feishu]
app_id = "cli_xxx"
app_secret_env = "FEISHU_APP_SECRET"
mode = "webhook"
webhook_port = 8453
default_agent = "assistant"Then configure Feishu event callback to:
https://<your-domain>:8453/feishu/webhook
How It Works
- websocket mode: OpenFang obtains endpoint from Feishu and receives events via long connection (no public inbound webhook needed).
- webhook mode: OpenFang starts an HTTP callback server and receives Feishu push events.
- send path (both modes): outbound messages still go through Feishu OpenAPI HTTP
im/v1/messages.
Signal
Prerequisites
- Signal CLI installed and linked to a phone number
Setup
- Install signal-cli.
- Register or link a phone number.
- Add to config:
[channels.signal]
signal_cli_path = "/usr/local/bin/signal-cli"
phone_number = "+1234567890"
default_agent = "assistant"- Restart the daemon.
How It Works
The Signal adapter spawns signal-cli as a subprocess in daemon mode and communicates via JSON-RPC. Incoming messages are read from the signal-cli output stream and routed to the configured agent.
Matrix
Prerequisites
- A Matrix homeserver account and access token
Setup
- Create a bot account on your Matrix homeserver.
- Generate an access token.
- Set the environment variable:
export MATRIX_TOKEN=syt_...- Add to config:
[channels.matrix]
homeserver_url = "https://matrix.org"
access_token_env = "MATRIX_TOKEN"
user_id = "@openfang-bot:matrix.org"
default_agent = "assistant"- Invite the bot to the rooms you want it to monitor.
- Restart the daemon.
How It Works
The Matrix adapter uses the Matrix Client-Server API. It syncs with the homeserver using long-polling (/sync with a timeout) and processes new messages from joined rooms. Responses are sent via the /rooms/{roomId}/send endpoint.
Prerequisites
- An email account with IMAP and SMTP access
Setup
- For Gmail, create an App Password.
- Set the environment variable:
export EMAIL_PASSWORD=abcd-efgh-ijkl-mnop- Add to config:
[channels.email]
imap_host = "imap.gmail.com"
imap_port = 993
smtp_host = "smtp.gmail.com"
smtp_port = 587
username = "[email protected]"
password_env = "EMAIL_PASSWORD"
poll_interval = 30
default_agent = "email-assistant"- Restart the daemon.
How It Works
The email adapter polls the IMAP inbox at the configured interval. New emails are parsed (subject + body) and routed to the configured agent. Responses are sent as reply emails via SMTP, preserving the subject line threading.
WebChat (Built-in)
The WebChat UI is embedded in the daemon and requires no configuration. When the daemon is running:
http://127.0.0.1:4200/Features:
- Real-time chat via WebSocket
- Streaming responses (text deltas as they arrive)
- Agent selection (switch between running agents)
- Token usage display
- No authentication required on localhost (protected by CORS)
Agent Routing
The AgentRouter determines which agent receives an incoming message. The routing logic is:
- Bindings (most specific first). Declarative
[[bindings]]rules inconfig.tomlmap message attributes (channel, channel_id, peer_id, guild_id, account_id, roles) to agents. The router scores each rule by specificity and picks the highest-scoring match. - Per-channel default: Each channel config has a
default_agentfield. Messages from that channel go to that agent. - User-agent binding: If a user has previously been associated with a specific agent (via commands or configuration), messages from that user route to that agent.
- Command prefix: Users can switch agents by sending a command like
/agent coderin the chat. Subsequent messages will be routed to the "coder" agent. - Fallback: If no routing applies, messages go to the first available agent.
Bindings
A binding has an agent (the target) and a match_rule (the criteria). All non-empty fields in the rule must match.
# Route a specific Discord channel to a dedicated agent.
[[bindings]]
agent = "researcher-medical"
match_rule = { channel = "discord", channel_id = "1234567890" }
[[bindings]]
agent = "researcher-business"
match_rule = { channel = "discord", channel_id = "9876543210" }
# Catch-all for the same user on any other channel.
[[bindings]]
agent = "assistant"
match_rule = { channel = "discord", peer_id = "user_discord_id" }peer_id vs channel_id — these are easy to confuse and the difference matters:
peer_idmatches the user (Discord user ID, Slack user ID, etc.).channel_idmatches the channel/conversation (Discord text channel, Slack conversation, Telegram chat).
Use peer_id for "messages from this person." Use channel_id for "messages in this room."
Specificity scores (higher wins):
| Field | Score |
|---|---|
peer_id |
8 |
channel_id |
8 |
guild_id |
4 |
roles |
2 |
account_id |
2 |
channel |
1 |
A binding's score is the sum of its set fields. peer_id and channel_id are equally specific, so a rule with both (16) beats either alone (8). Ties are broken by declaration order in the config.
Adapter coverage for channel_id — the following adapters populate ctx.channel_id directly from sender.platform_id (their "user" field is overloaded as a channel/conversation/room/space ID because that field doubles as the send target):
discord, slack, telegram, matrix, mattermost, teams, webex, rocketchat, nextcloud, pumble, revolt, guilded, feishu, lark, keybase, google_chat, line, twist, flock, twitch.
(Feishu Intl region emits Custom("lark") rather than Custom("feishu"); both spellings are recognized.)
Adapters not on this list (Reddit, Bluesky, Mastodon, Signal, Email, ntfy, Discourse, etc.) carry a user ID in platform_id and have no per-conversation concept, or use a hybrid scheme (IRC, Zulip flip between channel and user based on is_group). Bindings targeting channel_id on those platforms will only match if the adapter writes a channel_id key into message metadata.
The kernel emits a startup warning when a binding sets channel_id for a non-supporting adapter, so misconfigurations surface early instead of silently routing nowhere. The single source of truth for this list is CHANNELS_WITH_PLATFORM_ID_AS_CHANNEL in openfang-types::config, consumed by both routing (ChannelMessage::channel_id()) and config validation.
Strict parsing — AgentBinding and BindingMatchRule use #[serde(deny_unknown_fields)]. Typos at the binding level (e.g. match_rules for match_rule, channnel_id for channel_id) fail config load with a clear error rather than parsing into a no-op rule that silently matches every message. Existing configs that work today are unaffected; only configs with stray/misspelled fields inside a [[bindings]] block need a fix. The top-level KernelConfig deliberately stays permissive so unrecognized top-level keys (forward-compat, downstream forks) don't break startup.
Writing Custom Adapters
To add support for a new messaging platform, implement the ChannelAdapter trait. The trait is defined in crates/openfang-channels/src/types.rs.
The ChannelAdapter Trait
pub trait ChannelAdapter: Send + Sync {
/// Human-readable name of this adapter.
fn name(&self) -> &str;
/// The channel type this adapter handles.
fn channel_type(&self) -> ChannelType;
/// Start receiving messages. Returns a stream of incoming messages.
async fn start(
&self,
) -> Result + Send>>, Box<dyn std::error::Error>>;
/// Send a response back to a user on this channel.
async fn send(
&self,
user: &ChannelUser,
content: ChannelContent,
) -> Result<(), Box<dyn std::error::Error>>;
/// Send a typing indicator (optional -- default no-op).
async fn send_typing(&self, _user: &ChannelUser) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
/// Stop the adapter and clean up resources.
async fn stop(&self) -> Result<(), Box<dyn std::error::Error>>;
/// Get the current health status of this adapter (optional -- default returns disconnected).
fn status(&self) -> ChannelStatus {
ChannelStatus::default()
}
/// Send a response as a thread reply (optional -- default falls back to `send()`).
async fn send_in_thread(
&self,
user: &ChannelUser,
content: ChannelContent,
_thread_id: &str,
) -> Result<(), Box<dyn std::error::Error>> {
self.send(user, content).await
}
}1. Define Your Adapter
Create crates/openfang-channels/src/myplatform.rs:
use crate::types::{
ChannelAdapter, ChannelContent, ChannelMessage, ChannelStatus, ChannelType, ChannelUser,
};
use futures::stream::{self, Stream};
use std::pin::Pin;
use tokio::sync::watch;
use zeroize::Zeroizing;
pub struct MyPlatformAdapter {
token: Zeroizing<String>,
client: reqwest::Client,
shutdown: watch::Receiver,
}
impl MyPlatformAdapter {
pub fn new(token: String, shutdown: watch::Receiver) -> Self {
Self {
token: Zeroizing::new(token),
client: reqwest::Client::new(),
shutdown,
}
}
}
impl ChannelAdapter for MyPlatformAdapter {
fn name(&self) -> &str {
"MyPlatform"
}
fn channel_type(&self) -> ChannelType {
ChannelType::Custom("myplatform".to_string())
}
async fn start(
&self,
) -> Result + Send>>, Box<dyn std::error::Error>> {
// Return a stream that yields ChannelMessage items.
// Use self.shutdown to detect when the daemon is stopping.
// Apply exponential backoff on connection failures.
let stream = stream::empty(); // Replace with your polling/WebSocket logic
Ok(Box::pin(stream))
}
async fn send(
&self,
user: &ChannelUser,
content: ChannelContent,
) -> Result<(), Box<dyn std::error::Error>> {
// Send the response back to the platform.
// Use split_message() if the platform has message length limits.
// Use self.client and self.token to call the platform's API.
Ok(())
}
async fn stop(&self) -> Result<(), Box<dyn std::error::Error>> {
// Clean shutdown: close connections, stop polling.
Ok(())
}
fn status(&self) -> ChannelStatus {
ChannelStatus::default()
}
}Key points for new adapters:
- Use
ChannelType::Custom("myplatform".to_string())for the channel type. Only the 9 most common channels have namedChannelTypevariants (Telegram,WhatsApp,Slack,Discord,Signal,Matrix,Email,Teams,Mattermost). All others useCustom(String). - Wrap secrets in
Zeroizing<String>so they are wiped from memory on drop. - Accept a
watch::Receiverfor coordinated shutdown with the daemon. - Use exponential backoff for resilience on connection failures.
- Use the shared
split_message(text, max_len)utility for platforms with message length limits.
2. Register the Module
In crates/openfang-channels/src/lib.rs:
pub mod myplatform;3. Wire It Into the Bridge
In crates/openfang-api/src/channel_bridge.rs, add initialization logic for your adapter alongside the existing adapters.
4. Add Config Support
In openfang-types, add a config struct:
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct MyPlatformConfig {
pub token_env: String,
pub default_agent: Option<String>,
#[serde(default)]
pub overrides: ChannelOverrides,
}Add it to the ChannelsConfig struct and config.toml parsing. The overrides field gives your channel automatic support for model/prompt overrides, DM/group policies, rate limiting, threading, and output format selection.
5. Add CLI Setup Wizard
In crates/openfang-cli/src/main.rs, add a case to cmd_channel_setup with step-by-step instructions for your platform.
6. Test
Write integration tests. Use the ChannelMessage type to simulate incoming messages without connecting to the real platform.
File: docs/cli-reference.md
OpenFang CLI Reference
Complete command-line reference for openfang, the CLI tool for the OpenFang Agent OS.
Overview
The openfang binary is the primary interface for managing the OpenFang Agent OS. It supports two modes of operation:
- Daemon mode -- When a daemon is running (
openfang start), CLI commands communicate with it over HTTP. This is the recommended mode for production use. - In-process mode -- When no daemon is detected, commands that support it will boot an ephemeral in-process kernel. Agents spawned in this mode are not persisted and will be lost when the process exits.
Running openfang with no subcommand launches the interactive TUI (terminal user interface) built with ratatui, which provides a full dashboard experience in the terminal.
Installation
From source (cargo)
cargo install --path crates/openfang-cliBuild from workspace
cargo build --release -p openfang-cli
# Binary: target/release/openfang (or openfang.exe on Windows)Docker
docker run -it openfang/openfang:latestShell installer
curl -fsSL https://get.openfang.ai | shGlobal Options
These options apply to all commands.
| Option | Description |
|---|---|
--config |
Path to a custom config file. Overrides the default ~/.openfang/config.toml. |
--help |
Print help information for any command or subcommand. |
--version |
Print the version of the openfang binary. |
Environment variables:
| Variable | Description |
|---|---|
RUST_LOG |
Controls log verbosity (e.g. info, debug, openfang_kernel=trace). |
OPENFANG_AGENTS_DIR |
Override the agent templates directory. |
EDITOR / VISUAL |
Editor used by openfang config edit. Falls back to notepad (Windows) or vi (Unix). |
Command Reference
openfang (no subcommand)
Launch the interactive TUI dashboard.
openfang [--config ]The TUI provides a full-screen terminal interface with panels for agents, chat, workflows, channels, skills, settings, and more. Tracing output is redirected to ~/.openfang/tui.log to avoid corrupting the terminal display.
Press Ctrl+C to exit. A second Ctrl+C force-exits the process.
openfang init
Initialize the OpenFang workspace. Creates ~/.openfang/ with subdirectories (data/, agents/) and a default config.toml.
openfang init [--quick]Options:
| Option | Description |
|---|---|
--quick |
Skip interactive prompts. Auto-detects the best available LLM provider and writes config immediately. Suitable for CI/scripts. |
Behavior:
- Without
--quick: Launches an interactive 5-step onboarding wizard (ratatui TUI) that walks through provider selection, API key configuration, and optionally starts the daemon. - With
--quick: Auto-detects providers by checking environment variables in priority order: Groq, Gemini, DeepSeek, Anthropic, OpenAI, OpenRouter. Falls back to Groq if none are found. - File permissions are restricted to owner-only (
0600for files,0700for directories) on Unix.
Example:
# Interactive setup
openfang init
# Non-interactive (CI/scripts)
export GROQ_API_KEY="gsk_..."
openfang init --quickopenfang start
Start the OpenFang daemon (kernel + API server).
openfang start [--config ]Behavior:
- Checks if a daemon is already running; exits with an error if so.
- Boots the OpenFang kernel (loads config, initializes SQLite database, loads agents, connects MCP servers, starts background tasks).
- Starts the HTTP API server on the address specified in
config.toml(default:127.0.0.1:4200). - Writes
daemon.jsonto~/.openfang/so other CLI commands can discover the running daemon. - Blocks until interrupted with
Ctrl+C.
Output:
OpenFang Agent OS v0.1.0
Starting daemon...
[ok] Kernel booted (groq/llama-3.3-70b-versatile)
[ok] 50 models available
[ok] 3 agent(s) loaded
API: http://127.0.0.1:4200
Dashboard: http://127.0.0.1:4200/
Provider: groq
Model: llama-3.3-70b-versatile
hint: Open the dashboard in your browser, or run `openfang chat`
hint: Press Ctrl+C to stop the daemonExample:
# Start with default config
openfang start
# Start with custom config
openfang start --config /path/to/config.tomlopenfang status
Show the current kernel/daemon status.
openfang status [--json]Options:
| Option | Description |
|---|---|
--json |
Output machine-readable JSON for scripting. |
Behavior:
- If a daemon is running: queries
GET /api/statusand displays agent count, provider, model, uptime, API URL, data directory, and lists active agents. - If no daemon is running: boots an in-process kernel and shows persisted state. Displays a warning that the daemon is not running.
Example:
openfang status
openfang status --json | jq '.agent_count'openfang doctor
Run diagnostic checks on the OpenFang installation.
openfang doctor [--json] [--repair]Options:
| Option | Description |
|---|---|
--json |
Output results as JSON for scripting. |
--repair |
Attempt to auto-fix issues (create missing directories, config, remove stale files). Prompts for confirmation before each repair. |
Checks performed:
- OpenFang directory --
~/.openfang/exists - .env file -- exists and has correct permissions (0600 on Unix)
- Config TOML syntax --
config.tomlparses without errors - Daemon status -- whether a daemon is running
- Port 4200 availability -- if daemon is not running, checks if the port is free
- Stale daemon.json -- leftover
daemon.jsonfrom a crashed daemon - Database file -- SQLite magic bytes validation
- Disk space -- warns if less than 100MB available (Unix only)
- Agent manifests -- validates all
.tomlfiles in~/.openfang/agents/ - LLM provider keys -- checks env vars for 10 providers (Groq, OpenRouter, Anthropic, OpenAI, DeepSeek, Gemini, Google, Together, Mistral, Fireworks), performs live validation (401/403 detection)
- Channel tokens -- format validation for Telegram, Discord, Slack tokens
- Config consistency -- checks that
api_key_envreferences in config match actual environment variables - Rust toolchain --
rustc --version
Example:
openfang doctor
openfang doctor --repair
openfang doctor --jsonopenfang dashboard
Open the web dashboard in the default browser.
openfang dashboardBehavior:
- Requires a running daemon.
- Opens the daemon URL (e.g.
http://127.0.0.1:4200/) in the system browser. - Copies the URL to the system clipboard (uses PowerShell on Windows,
pbcopyon macOS,xclip/xselon Linux).
Example:
openfang dashboardopenfang completion
Generate shell completion scripts.
openfang completion <SHELL>Arguments:
| Argument | Description |
|---|---|
<SHELL> |
Target shell. One of: bash, zsh, fish, elvish, powershell. |
Example:
# Bash
openfang completion bash > ~/.bash_completion.d/openfang
# Zsh
openfang completion zsh > ~/.zfunc/_openfang
# Fish
openfang completion fish > ~/.config/fish/completions/openfang.fish
# PowerShell
openfang completion powershell > openfang.ps1Agent Commands
openfang agent new
Spawn an agent from a built-in template.
openfang agent new [<TEMPLATE>]Arguments:
| Argument | Description |
|---|---|
<TEMPLATE> |
Template name (e.g. coder, assistant, researcher). If omitted, displays an interactive picker listing all available templates. |
Behavior:
- Templates are discovered from: the repo
agents/directory (dev builds),~/.openfang/agents/(installed), andOPENFANG_AGENTS_DIR(env override). - Each template is a directory containing an
agent.tomlmanifest. - In daemon mode: sends
POST /api/agentswith the manifest. Agent is persistent. - In standalone mode: boots an in-process kernel. Agent is ephemeral.
Example:
# Interactive picker
openfang agent new
# Spawn by name
openfang agent new coder
# Spawn the assistant template
openfang agent new assistantopenfang agent spawn
Spawn an agent from a custom manifest file.
openfang agent spawn <MANIFEST>Arguments:
| Argument | Description |
|---|---|
<MANIFEST> |
Path to an agent manifest TOML file. |
Behavior:
- Reads and parses the TOML manifest file.
- In daemon mode: sends the raw TOML to
POST /api/agents. - In standalone mode: boots an in-process kernel and spawns the agent locally.
Example:
openfang agent spawn ./my-agent/agent.tomlopenfang agent list
List all running agents.
openfang agent list [--json]Options:
| Option | Description |
|---|---|
--json |
Output as JSON array for scripting. |
Output columns: ID, NAME, STATE, PROVIDER, MODEL (daemon mode) or ID, NAME, STATE, CREATED (in-process mode).
Example:
openfang agent list
openfang agent list --json | jq '.[].name'openfang agent chat
Start an interactive chat session with a specific agent.
openfang agent chat <AGENT_ID>Arguments:
| Argument | Description |
|---|---|
<AGENT_ID> |
Agent UUID. Obtain from openfang agent list. |
Behavior:
- Opens a REPL-style chat loop.
- Type messages at the
you>prompt. - Agent responses display at the
agent>prompt, followed by token usage and iteration count. - Type
exit,quit, or pressCtrl+Cto end the session.
Example:
openfang agent chat a1b2c3d4-e5f6-7890-abcd-ef1234567890openfang agent kill
Terminate a running agent.
openfang agent kill <AGENT_ID>Arguments:
| Argument | Description |
|---|---|
<AGENT_ID> |
Agent UUID to terminate. |
Example:
openfang agent kill a1b2c3d4-e5f6-7890-abcd-ef1234567890Workflow Commands
All workflow commands require a running daemon.
openfang workflow list
List all registered workflows.
openfang workflow listOutput columns: ID, NAME, STEPS, CREATED.
openfang workflow create
Create a workflow from a JSON definition file.
openfang workflow create <FILE>Arguments:
| Argument | Description |
|---|---|
<FILE> |
Path to a JSON file describing the workflow steps. |
Example:
openfang workflow create ./my-workflow.jsonopenfang workflow run
Execute a workflow by ID.
openfang workflow run <WORKFLOW_ID>Arguments:
| Argument | Description |
|---|---|
<WORKFLOW_ID> |
Workflow UUID. Obtain from openfang workflow list. |
| `` | Input text to pass to the workflow. |
Example:
openfang workflow run abc123 "Analyze this code for security issues"Trigger Commands
All trigger commands require a running daemon.
openfang trigger list
List all event triggers.
openfang trigger list [--agent-id ]Options:
| Option | Description |
|---|---|
--agent-id |
Filter triggers by the owning agent's UUID. |
Output columns: TRIGGER ID, AGENT ID, ENABLED, FIRES, PATTERN.
openfang trigger create
Create an event trigger for an agent.
openfang trigger create <AGENT_ID> [--prompt <TEMPLATE>] [--max-fires <N>]Arguments:
| Argument | Description |
|---|---|
<AGENT_ID> |
UUID of the agent that owns the trigger. |
| `` | Trigger pattern as a JSON string. |
Options:
| Option | Default | Description |
|---|---|---|
--prompt <TEMPLATE> |
"Event: {{event}}" |
Prompt template. Use {{event}} as a placeholder for the event data. |
--max-fires <N> |
0 (unlimited) |
Maximum number of times the trigger will fire. |
Pattern examples:
# Fire on any lifecycle event
openfang trigger create <AGENT_ID> '{"lifecycle":{}}'
# Fire when a specific agent is spawned
openfang trigger create <AGENT_ID> '{"agent_spawned":{"name_pattern":"*"}}'
# Fire on agent termination
openfang trigger create <AGENT_ID> '{"agent_terminated":{}}'
# Fire on all events (limited to 10 fires)
openfang trigger create <AGENT_ID> '{"all":{}}' --max-fires 10openfang trigger delete
Delete a trigger by ID.
openfang trigger deleteArguments:
| Argument | Description |
|---|---|
| `` | UUID of the trigger to delete. |
Skill Commands
openfang skill list
List all installed skills.
openfang skill listOutput columns: NAME, VERSION, TOOLS, DESCRIPTION.
Loads skills from ~/.openfang/skills/ plus bundled skills compiled into the binary.
openfang skill install
Install a skill from a local directory, git URL, or FangHub marketplace.
openfang skill installArguments:
| Argument | Description |
|---|---|
| `` | Skill name (FangHub), local directory path, or git URL. |
Behavior:
- Local directory: Looks for
skill.tomlin the directory. If not found, checks for OpenClaw-format skills (SKILL.md with YAML frontmatter) and auto-converts them. - Remote (FangHub): Fetches and installs from the FangHub marketplace. Skills pass through SHA256 verification and prompt injection scanning.
Example:
# Install from local directory
openfang skill install ./my-skill/
# Install from FangHub
openfang skill install web-search
# Install an OpenClaw-format skill
openfang skill install ./openclaw-skill/openfang skill remove
Remove an installed skill.
openfang skill remove <NAME>Arguments:
| Argument | Description |
|---|---|
<NAME> |
Name of the skill to remove. |
Example:
openfang skill remove web-searchopenfang skill search
Search the FangHub marketplace for skills.
openfang skill search <QUERY>Arguments:
| Argument | Description |
|---|---|
<QUERY> |
Search query string. |
Example:
openfang skill search "docker kubernetes"openfang skill create
Interactively scaffold a new skill project.
openfang skill createBehavior:
Prompts for:
- Skill name
- Description
- Runtime (
python,node, orwasm; defaults topython)
Creates a directory under ~/.openfang/skills/<name>/ with:
skill.toml-- manifest filesrc/main.py(orsrc/index.js) -- entry point with boilerplate
Example:
openfang skill create
# Skill name: my-tool
# Runtime (python/node/wasm) [python]: pythonChannel Commands
openfang channel list
List configured channels and their status.
openfang channel listOutput columns: CHANNEL, ENV VAR, STATUS.
Checks config.toml for channel configuration sections and environment variables for required tokens. Status is one of: Ready, Missing env, Not configured.
Channels checked: webchat, telegram, discord, slack, whatsapp, signal, matrix, email.
openfang channel setup
Interactive setup wizard for a channel integration.
openfang channel setup [<CHANNEL>]Arguments:
| Argument | Description |
|---|---|
<CHANNEL> |
Channel name. If omitted, displays an interactive picker. |
Supported channels: telegram, discord, slack, whatsapp, email, signal, matrix.
Each wizard:
- Displays step-by-step instructions for obtaining credentials.
- Prompts for tokens/credentials.
- Saves tokens to
~/.openfang/.envwith owner-only permissions. - Appends the channel configuration block to
config.toml(prompts for confirmation). - Warns to restart the daemon if one is running.
Example:
# Interactive picker
openfang channel setup
# Direct setup
openfang channel setup telegram
openfang channel setup discord
openfang channel setup slackopenfang channel test
Send a test message through a configured channel.
openfang channel test <CHANNEL>Arguments:
| Argument | Description |
|---|---|
<CHANNEL> |
Channel name to test. |
Requires a running daemon. Sends POST /api/channels/<channel>/test.
Example:
openfang channel test telegramopenfang channel enable
Enable a channel integration.
openfang channel enable <CHANNEL>Arguments:
| Argument | Description |
|---|---|
<CHANNEL> |
Channel name to enable. |
In daemon mode: sends POST /api/channels/<channel>/enable. Without a daemon: prints a note that the change will take effect on next start.
openfang channel disable
Disable a channel without removing its configuration.
openfang channel disable <CHANNEL>Arguments:
| Argument | Description |
|---|---|
<CHANNEL> |
Channel name to disable. |
In daemon mode: sends POST /api/channels/<channel>/disable. Without a daemon: prints a note to edit config.toml.
Config Commands
openfang config show
Display the current configuration file.
openfang config showPrints the contents of ~/.openfang/config.toml with the file path as a header comment.
openfang config edit
Open the configuration file in your editor.
openfang config editUses $EDITOR, then $VISUAL, then falls back to notepad (Windows) or vi (Unix).
openfang config get
Get a single configuration value by dotted key path.
openfang config get <KEY>Arguments:
| Argument | Description |
|---|---|
<KEY> |
Dotted key path into the TOML structure. |
Example:
openfang config get default_model.provider
# groq
openfang config get api_listen
# 127.0.0.1:4200
openfang config get memory.decay_rate
# 0.05openfang config set
Set a configuration value by dotted key path.
openfang config set <KEY> <VALUE>Arguments:
| Argument | Description |
|---|---|
<KEY> |
Dotted key path. |
<VALUE> |
New value. Type is inferred from the existing value (integer, float, boolean, or string). |
Warning: This command re-serializes the TOML file, which strips all comments.
Example:
openfang config set default_model.provider anthropic
openfang config set default_model.model claude-sonnet-4-20250514
openfang config set api_listen "0.0.0.0:4200"openfang config set-key
Save an LLM provider API key to ~/.openfang/.env.
openfang config set-keyArguments:
| Argument | Description |
|---|---|
| `` | Provider name (e.g. groq, anthropic, openai, gemini, deepseek, openrouter, together, mistral, fireworks, perplexity, cohere, xai, brave, tavily). |
Behavior:
- Prompts interactively for the API key.
- Saves to
~/.openfang/.envas_API_KEY=<value>. - Runs a live validation test against the provider's API.
- File permissions are restricted to owner-only on Unix.
Example:
openfang config set-key groq
# Paste your groq API key: gsk_...
# [ok] Saved GROQ_API_KEY to ~/.openfang/.env
# Testing key... OKopenfang config delete-key
Remove an API key from ~/.openfang/.env.
openfang config delete-keyArguments:
| Argument | Description |
|---|---|
| `` | Provider name. |
Example:
openfang config delete-key openaiopenfang config test-key
Test provider connectivity with the stored API key.
openfang config test-keyArguments:
| Argument | Description |
|---|---|
| `` | Provider name. |
Behavior:
- Reads the API key from the environment (loaded from
~/.openfang/.env). - Hits the provider's models/health endpoint.
- Reports
OK(key accepted) orFAILED (401/403)(key rejected). - Exits with code 1 on failure.
Example:
openfang config test-key groq
# Testing groq (GROQ_API_KEY)... OKQuick Chat
openfang chat
Quick alias for starting a chat session.
openfang chat [<AGENT>]Arguments:
| Argument | Description |
|---|---|
<AGENT> |
Optional agent name or UUID. |
Behavior:
- Daemon mode: Finds the agent by name or ID among running agents. If no agent name is given, uses the first available agent. If no agents exist, suggests
openfang agent new. - Standalone mode (no daemon): Boots an in-process kernel and auto-spawns an agent from templates. Searches for an agent matching the given name, then falls back to
assistant, then to the first available template.
This is the simplest way to start chatting -- it works with or without a daemon.
Example:
# Chat with the default agent
openfang chat
# Chat with a specific agent by name
openfang chat coder
# Chat with a specific agent by UUID
openfang chat a1b2c3d4-e5f6-7890-abcd-ef1234567890Migration
openfang migrate
Migrate configuration and agents from another agent framework.
openfang migrate --from <FRAMEWORK> [--source-dir ] [--dry-run]Options:
| Option | Description |
|---|---|
--from <FRAMEWORK> |
Source framework. One of: openclaw, langchain, autogpt. |
--source-dir |
Path to the source workspace. Auto-detected if not set (e.g. ~/.openclaw, ~/.langchain, ~/Auto-GPT). |
--dry-run |
Show what would be imported without making changes. |
Behavior:
- Converts agent configurations, YAML manifests, and settings from the source framework into OpenFang format.
- Saves imported data to
~/.openfang/. - Writes a
migration_report.mdsummarizing what was imported.
Example:
# Dry run migration from OpenClaw
openfang migrate --from openclaw --dry-run
# Migrate from OpenClaw (auto-detect source)
openfang migrate --from openclaw
# Migrate from LangChain with explicit source
openfang migrate --from langchain --source-dir /home/user/.langchain
# Migrate from AutoGPT
openfang migrate --from autogptMCP Server
openfang mcp
Start an MCP (Model Context Protocol) server over stdio.
openfang mcpBehavior:
- Exposes running OpenFang agents as MCP tools via JSON-RPC 2.0 over stdin/stdout with Content-Length framing.
- Each agent becomes a callable tool named
openfang_agent_<name>(hyphens replaced with underscores). - Connects to a running daemon via HTTP if available; otherwise boots an in-process kernel.
- Protocol version:
2024-11-05. - Maximum message size: 10MB (security limit).
Supported MCP methods:
| Method | Description |
|---|---|
initialize |
Returns server capabilities and info. |
tools/list |
Lists all available agent tools. |
tools/call |
Sends a message to an agent and returns the response. |
Tool input schema:
Each agent tool accepts a single message (string) argument.
Integration with Claude Desktop / other MCP clients:
Add to your MCP client configuration:
{
"mcpServers": {
"openfang": {
"command": "openfang",
"args": ["mcp"]
}
}
}Daemon Auto-Detect
The CLI uses a two-step mechanism to detect a running daemon:
Read
daemon.json: On startup, the daemon writes~/.openfang/daemon.jsoncontaining the listen address (e.g.127.0.0.1:4200). The CLI reads this file to learn where the daemon is.Health check: The CLI sends
GET http://<listen_addr>/api/healthwith a 2-second timeout. If the health check succeeds, the daemon is considered running and the CLI uses HTTP to communicate with it.
If either step fails (no daemon.json, stale file, health check timeout), the CLI falls back to in-process mode for commands that support it. Commands that require a daemon (workflows, triggers, channel test/enable/disable, dashboard) will exit with an error and a helpful message.
Daemon lifecycle:
openfang start # Starts daemon, writes daemon.json
# Other CLI instances detect daemon.json
openfang status # Connects to daemon via HTTP
Ctrl+C # Daemon shuts down, daemon.json removed
openfang doctor --repair # Cleans up stale daemon.json from crashesEnvironment File
OpenFang loads ~/.openfang/.env into the process environment on every CLI invocation. System environment variables take priority over .env values.
The .env file stores API keys and secrets:
GROQ_API_KEY=gsk_...
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
TELEGRAM_BOT_TOKEN=123456:ABC-DEF...Manage keys with the config set-key / config delete-key commands rather than editing the file directly, as these commands enforce correct permissions.
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success. |
1 |
General error (invalid arguments, failed operations, missing daemon, parse errors, spawn failures). |
130 |
Interrupted by second Ctrl+C (force exit). |
Examples
First-time setup
# 1. Set your API key
export GROQ_API_KEY="gsk_your_key_here"
# 2. Initialize OpenFang
openfang init --quick
# 3. Start the daemon
openfang startDaily usage
# Quick chat (auto-spawns agent if needed)
openfang chat
# Chat with a specific agent
openfang chat coder
# Check what's running
openfang status
# Open the web dashboard
openfang dashboardAgent management
# Spawn from a template
openfang agent new assistant
# Spawn from a custom manifest
openfang agent spawn ./agents/custom-agent/agent.toml
# List running agents
openfang agent list
# Chat with an agent by UUID
openfang agent chat
# Kill an agent
openfang agent killWorkflow automation
# Create a workflow
openfang workflow create ./review-pipeline.json
# List workflows
openfang workflow list
# Run a workflow
openfang workflow run <WORKFLOW_ID> "Review the latest PR"Event triggers
# Create a trigger that fires on agent spawn
openfang trigger create <AGENT_ID> '{"agent_spawned":{"name_pattern":"*"}}' \
--prompt "New agent spawned: {{event}}" \
--max-fires 100
# List all triggers
openfang trigger list
# List triggers for a specific agent
openfang trigger list --agent-id <AGENT_ID>
# Delete a trigger
openfang trigger deleteSkill management
# Search FangHub
openfang skill search "code review"
# Install a skill
openfang skill install code-reviewer
# List installed skills
openfang skill list
# Create a new skill
openfang skill create
# Remove a skill
openfang skill remove code-reviewerChannel setup
# Interactive channel picker
openfang channel setup
# Direct channel setup
openfang channel setup telegram
# Check channel status
openfang channel list
# Test a channel
openfang channel test telegram
# Enable/disable channels
openfang channel enable discord
openfang channel disable slackConfiguration
# View config
openfang config show
# Get a specific value
openfang config get default_model.provider
# Change provider
openfang config set default_model.provider anthropic
openfang config set default_model.model claude-sonnet-4-20250514
openfang config set default_model.api_key_env ANTHROPIC_API_KEY
# Manage API keys
openfang config set-key anthropic
openfang config test-key anthropic
openfang config delete-key openai
# Open in editor
openfang config editMigration from other frameworks
# Preview migration
openfang migrate --from openclaw --dry-run
# Run migration
openfang migrate --from openclaw
# Migrate from LangChain
openfang migrate --from langchain --source-dir ~/.langchainMCP integration
# Start MCP server for Claude Desktop or other MCP clients
openfang mcpDiagnostics
# Run all diagnostic checks
openfang doctor
# Auto-repair issues
openfang doctor --repair
# Machine-readable diagnostics
openfang doctor --jsonShell completions
# Generate and install completions for your shell
openfang completion bash >> ~/.bashrc
openfang completion zsh > "${fpath[1]}/_openfang"
openfang completion fish > ~/.config/fish/completions/openfang.fishSupported LLM Providers
The following providers are recognized by openfang config set-key and openfang doctor:
| Provider | Environment Variable | Default Model |
|---|---|---|
| Groq | GROQ_API_KEY |
llama-3.3-70b-versatile |
| Gemini | GEMINI_API_KEY or GOOGLE_API_KEY |
gemini-2.5-flash |
| DeepSeek | DEEPSEEK_API_KEY |
deepseek-chat |
| Anthropic | ANTHROPIC_API_KEY |
claude-sonnet-4-20250514 |
| OpenAI | OPENAI_API_KEY |
gpt-4o |
| OpenRouter | OPENROUTER_API_KEY |
openrouter/google/gemini-2.5-flash |
| Together | TOGETHER_API_KEY |
-- |
| Mistral | MISTRAL_API_KEY |
-- |
| Fireworks | FIREWORKS_API_KEY |
-- |
| Perplexity | PERPLEXITY_API_KEY |
-- |
| Cohere | COHERE_API_KEY |
-- |
| xAI | XAI_API_KEY |
-- |
Additional search/fetch provider keys: BRAVE_API_KEY, TAVILY_API_KEY.