openfang Documentation

Open-source Agent Operating System

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy openfang on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name openfang -p 4200:4200 --restart always rightnow-ai/openfang:latest
Configured Services & Ports
⚙️ openfang
image: build locally
🔌 Ports: 4200:4200
docker-compose.yml
yaml (docker-compose.yml)
# NOTE: The GHCR image (ghcr.io/rightnow-ai/openfang) is not yet public.
# For now, build from source using `docker compose up --build`.
# See: https://github.com/RightNow-AI/openfang/issues/12

version: "3.8"
services:
  openfang:
    build: .
    # image: ghcr.io/rightnow-ai/openfang:latest  # Uncomment when GHCR is public
    ports:
      - "4200:4200"
    volumes:
      - openfang-data:/data
    # Uncomment to reach host services (Ollama, whisper.cpp, local Postgres)
    # from inside the container. Required on Linux and colima. See
    # docs/troubleshooting.md#connecting-to-host-services-from-docker.
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - GROQ_API_KEY=${GROQ_API_KEY:-}
      - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
      - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN:-}
      - SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN:-}
      - SLACK_APP_TOKEN=${SLACK_APP_TOKEN:-}
    restart: unless-stopped

volumes:
  openfang-data:

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.

bash
curl -fsSL https://openfang.sh/install | sh
openfang init
openfang start
# Dashboard live at http://localhost:4200

Windows

powershell
irm https://openfang.sh/install.ps1 | iex
openfang init
openfang start

Hands: 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.
Twitter 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.
bash
# 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 list

Build 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)

text
ZeroClaw   ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   10 ms
OpenFang   ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  180 ms    ★
LangGraph  █████████████████░░░░░░░░░░░░░░░░░░░░░░░░░  2.5 sec
CrewAI     ████████████████████░░░░░░░░░░░░░░░░░░░░░░  3.0 sec
AutoGen    ██████████████████████████░░░░░░░░░░░░░░░░░  4.0 sec
OpenClaw   █████████████████████████████████████████░░  5.98 sec

Idle Memory Usage (lower is better)

text
ZeroClaw   █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    5 MB
OpenFang   ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   40 MB    ★
LangGraph  ██████████████████░░░░░░░░░░░░░░░░░░░░░░░░░  180 MB
CrewAI     ████████████████████░░░░░░░░░░░░░░░░░░░░░░░  200 MB
AutoGen    █████████████████████████░░░░░░░░░░░░░░░░░░  250 MB
OpenClaw   ████████████████████████████████████████░░░░  394 MB

Install Size (lower is better)

text
ZeroClaw   █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  8.8 MB
OpenFang   ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   32 MB    ★
CrewAI     ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  100 MB
LangGraph  ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  150 MB
AutoGen    ████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░  200 MB
OpenClaw   ████████████████████████████████████████░░░░  500 MB

Security Systems (higher is better)

text
OpenFang   ████████████████████████████████████████████   16      ★
ZeroClaw   ███████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░    6
OpenClaw   ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    3
AutoGen    █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    2
LangGraph  █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    2
CrewAI     ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    1

Channel Adapters (higher is better)

text
OpenFang   ████████████████████████████████████████████   40      ★
ZeroClaw   ███████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░   15
OpenClaw   █████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   13
CrewAI     ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    0
AutoGen    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    0
LangGraph  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    0

LLM Providers (higher is better)

text
ZeroClaw   ████████████████████████████████████████████   28
OpenFang   ██████████████████████████████████████████░░   27      ★
LangGraph  ██████████████████████░░░░░░░░░░░░░░░░░░░░░   15
CrewAI     ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   10
OpenClaw   ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   10
AutoGen    ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    8

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

text
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 automation

40 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:

bash
cd packages/whatsapp-gateway
npm install

2. Configure config.toml:

toml
[channels.whatsapp]
mode = "web"
default_agent = "assistant"

3. Set the gateway URL (choose one):

Add to your shell profile for persistence:

bash
# macOS / Linux
echo 'export WHATSAPP_WEB_GATEWAY_URL="http://127.0.0.1:3009"' >> ~/.zshrc
source ~/.zshrc

Or set it inline when starting the gateway:

bash
export WHATSAPP_WEB_GATEWAY_URL="http://127.0.0.1:3009"

4. Start the gateway:

bash
node packages/whatsapp-gateway/index.js

The gateway listens on port 3009 by default. Override with WHATSAPP_GATEWAY_PORT.

5. Start OpenFang:

bash
openfang start
# Dashboard at http://localhost:4200

6. 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:

bash
# 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-run

The 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:

bash
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

bash
# 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 coder

Windows (PowerShell)

powershell
irm https://openfang.sh/install.ps1 | iex
openfang init
openfang start

Development

bash
# 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 -- --check

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



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:

bash
openfang spawn orchestrator
openfang spawn coder
openfang spawn --template agents/writer/agent.toml

Spawn via the REST API:

bash
# 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:

bash
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 = ["*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
openfang spawn test-engineer
# "Write comprehensive tests for the rate limiter module covering edge cases"

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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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.*"]
bash
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

text
/* 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

  1. Start minimal. Grant only the tools and capabilities the agent actually needs. You can always add more later.
  2. 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.
  3. Set appropriate temperature. Use 0.2 for precise/analytical tasks, 0.5 for balanced tasks, 0.7+ for creative tasks.
  4. Use shell whitelists. Never grant shell = ["*"]. Whitelist specific command patterns like shell = ["python *", "cargo test *"].
  5. Set token budgets. Use max_llm_tokens_per_hour to prevent runaway costs. Start with 100,000 and adjust based on usage.
  6. Add fallback models. If your primary model has rate limits or availability issues, add a [[fallback_models]] entry.
  7. Use memory for continuity. Grant memory_store and memory_recall so the agent can persist context across sessions.

Spawning Agents

CLI

bash
# 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

bash
# 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

bash
# 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/models

Orchestrator Delegation

The orchestrator agent can spawn and delegate to any other agent programmatically:

text
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 report

Environment 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

When an API key is configured in config.toml, all endpoints (except /api/health and /) require a Bearer token:

text
Authorization: Bearer <your-api-key>

Setting the API Key

Add to ~/.openfang/config.toml:

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/health
  • GET / (WebChat UI)

Agent Endpoints

GET /api/agents

List all running agents.

Response 200 OK:

json
[
  {
    "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:

json
{
  "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):

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:

json
{
  "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "my-agent"
}

PUT /api/agents/{id}/update

Update an agent's configuration at runtime.

Request Body:

json
{
  "description": "Updated description",
  "system_prompt": "You are a specialized assistant.",
  "tags": ["updated", "v2"]
}

Response 200 OK:

json
{
  "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:

json
{
  "mode": "Stable"
}

Response 200 OK:

json
{
  "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:

json
{
  "message": "What files are in the current directory?"
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "status": "killed",
  "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Workflow Endpoints

GET /api/workflows

List all registered workflows.

Response 200 OK:

json
[
  {
    "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):

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:

json
{
  "workflow_id": "w1b2c3d4-..."
}

POST /api/workflows/{id}/run

Execute a workflow.

Request Body:

json
{
  "input": "Review this pull request: ..."
}

Response 200 OK:

json
{
  "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:

json
[
  {
    "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:

json
[
  {
    "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:

json
{
  "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:

json
{
  "trigger_id": "t1b2c3d4-...",
  "agent_id": "a1b2c3d4-..."
}

PUT /api/triggers/{id}

Update an existing trigger's configuration.

Request Body:

json
{
  "prompt_template": "Updated template: {{event}}",
  "enabled": false,
  "max_fires": 10
}

Response 200 OK:

json
{
  "status": "updated",
  "trigger_id": "t1b2c3d4-..."
}

DELETE /api/triggers/{id}

Remove a trigger.

Response 200 OK:

json
{
  "status": "removed",
  "trigger_id": "t1b2c3d4-..."
}

Memory Endpoints

GET /api/memory/agents/{id}/kv

List all key-value pairs for an agent.

Response 200 OK:

json
{
  "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:

json
{
  "key": "preferences",
  "value": {"theme": "dark"}
}

Response 404 Not Found (key does not exist):

json
{
  "error": "Key 'preferences' not found"
}

PUT /api/memory/agents/{id}/kv/{key}

Set a key-value pair. Creates or overwrites.

Request Body:

json
{
  "value": {"theme": "dark", "language": "en"}
}

Response 200 OK:

json
{
  "status": "stored",
  "key": "preferences"
}

DELETE /api/memory/agents/{id}/kv/{key}

Delete a key-value pair.

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "status": "shutting_down"
}

GET /api/profiles

List available agent profiles (predefined configurations for common use cases).

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "api_key": "sk-..."
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "status": "ok",
  "provider": "anthropic",
  "latency_ms": 245,
  "model_tested": "claude-sonnet-4-20250514"
}

Response 401 Unauthorized:

json
{
  "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:

json
{
  "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:

json
{
  "source": "/path/to/skill",
  "verify": true
}

Response 201 Created:

json
{
  "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:

json
{
  "name": "my-custom-skill"
}

Response 200 OK:

json
{
  "status": "uninstalled",
  "skill": "my-custom-skill"
}

POST /api/skills/create

Create a new skill from a template.

Request Body:

json
{
  "name": "my-skill",
  "runtime": "python",
  "description": "A custom skill"
}

Response 201 Created:

json
{
  "status": "created",
  "skill": "my-skill",
  "path": "/home/user/.openfang/skills/my-skill"
}

Search the FangHub marketplace for community skills.

Query Parameters:

  • q (required): Search query string
  • page (optional): Page number (default: 1)

Response 200 OK:

json
{
  "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.

Search ClawHub for compatible skills.

Query Parameters:

  • q (required): Search query

Response 200 OK:

json
{
  "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 category
  • page (optional): Page number (default: 1)

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "slug": "data-pipeline"
}

Response 201 Created:

json
{
  "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:

json
{
  "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):

json
{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "id": 1
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "agent_id": "a1b2c3d4-...",
  "message": {
    "role": "user",
    "parts": [
      {"text": "Review this code for security issues"}
    ]
  }
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "status": "valid",
  "chain_length": 1042,
  "first_entry": "2025-01-10T08:00:00Z",
  "last_entry": "2025-01-15T10:30:00Z"
}

Response 200 OK (chain broken):

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "path": "/home/user/.openclaw"
}

Response 200 OK:

json
{
  "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:

json
{
  "source": "/home/user/.openclaw",
  "import_agents": true,
  "import_skills": true,
  "import_sessions": false
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "status": "compacted",
  "message": "Session compacted: 80 messages summarized, 20 kept"
}

Response 200 OK (no compaction needed):

json
{
  "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:

json
{
  "status": "stopped",
  "message": "Agent run cancelled"
}

PUT /api/agents/{id}/model

Switch an agent's LLM model at runtime.

Request Body:

json
{
  "model": "claude-sonnet-4-20250514"
}

Response 200 OK:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "result": "{\"job_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"status\":\"created\"}"
}

DELETE /api/cron/jobs/{id}

Delete a cron job by ID.

Response 200 OK:

json
{ "status": "deleted" }

PUT /api/cron/jobs/{id}/enable

Enable or disable a cron job.

Request Body:

json
{ "enabled": false }

Response 200 OK:

json
{ "status": "updated", "enabled": false }

GET /api/cron/jobs/{id}/status

Get job metadata including last run time, status, and error history.

Response 200 OK:

json
{
  "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 disabled
  • 404 Not Found — Job not found

WebSocket Protocol

Connecting

text
GET /api/agents/{id}/ws

Upgrades 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:

json
{
  "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:

json
{
  "type": "ping"
}

Server to Client

Connection confirmed (sent immediately on connect):

json
{
  "type": "connected",
  "agent_id": "a1b2c3d4-..."
}

Thinking indicator (sent when agent starts processing):

json
{
  "type": "thinking"
}

Text delta (streaming token, sent as the LLM generates output):

json
{
  "type": "text_delta",
  "content": "The weather"
}

Tool use started (sent when the agent invokes a tool):

json
{
  "type": "tool_start",
  "tool": "web_fetch"
}

Complete response (sent when agent finishes, contains final aggregated response):

json
{
  "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:

json
{
  "type": "error",
  "content": "Agent not found"
}

Agent list update (sent every 5 seconds with current agent states):

json
{
  "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):

json
{
  "type": "pong"
}

Connection Lifecycle

  1. Client connects to ws://host:port/api/agents/{id}/ws.
  2. Server sends {"type": "connected"}.
  3. Client sends {"type": "message", "content": "..."}.
  4. Server sends {"type": "thinking"}, then zero or more {"type": "text_delta"} events, then {"type": "response"}.
  5. Server periodically sends {"type": "agents_updated"} every 5 seconds.
  6. 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):

json
{
  "message": "Explain quantum computing"
}

SSE Event Stream:

text
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:

json
{
  "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:

json
{
  "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:

json
{
  "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:

text
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:

json
{
  "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:

json
{
  "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:

text
x-request-id: 550e8400-e29b-41d4-a716-446655440000

Use 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:

text
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

OpenFang is organized as a Cargo workspace with 14 crates (13 code crates + xtask). Dependencies flow downward (lower crates depend on nothing above them).

text
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 config

Crate 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:

text
/* Detailed source-code truncated for AI context efficiency. */

When the daemon wraps the kernel in Arc, additional steps occur:

text
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

text
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

  1. Generate new AgentId (UUID v4) and SessionId.
  2. Create a session in the memory substrate.
  3. Parse the manifest and extract capabilities.
  4. Validate capability inheritance (validate_capability_inheritance() prevents privilege escalation).
  5. Grant capabilities via CapabilityManager.
  6. Register with the AgentScheduler (quota tracking).
  7. Create AgentEntry and register in AgentRegistry.
  8. Persist to SQLite via memory.save_agent().
  9. If agent has a parent, update parent's children list.
  10. Register proactive triggers (if schedule mode is Proactive).
  11. Publish Lifecycle::Spawned event and evaluate triggers.

Message Flow

  1. RBAC check: AuthManager resolves channel identity and checks user role permissions.
  2. Channel policy check: ChannelBridgeHandle.authorize_channel_user() enforces DM/group policy.
  3. Quota check: AgentScheduler verifies the agent has not exceeded its token-per-hour limit.
  4. Entry lookup: Fetch AgentEntry from the registry.
  5. Module dispatch: Based on manifest.module:
    • builtin:chat or unrecognized: LLM agent loop
    • wasm:path/to/module.wasm: WASM sandbox execution
    • python:path/to/script.py: Python subprocess execution (env_clear() + selective vars)
  6. 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.
  7. Cost estimation: MeteringEngine.estimate_cost_with_catalog() computes cost in USD.
  8. Record usage: Update quota tracking with token counts; persist usage event.
  9. Return result: AgentLoopResult with response text, token usage, iteration count, and cost_usd.

Kill Flow

  1. Check caller has AgentKill(target_name) capability.
  2. Remove from AgentRegistry.
  3. Stop background loops via BackgroundExecutor.
  4. Unregister from AgentScheduler.
  5. Revoke all capabilities.
  6. Unsubscribe from EventBus.
  7. Remove triggers.
  8. 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 ToolResult messages (no matching ToolUse).
  • 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.

text
agent_id | key         | value
---------|-------------|------------------
uuid-a   | preferences | {"theme": "dark"}
uuid-b   | state       | {"step": 3}
shared   | project     | {"name": "foo"}

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_events table persists token counts, cost estimates, and model usage per agent. UsageStore provides query and aggregation APIs.
  • Canonical sessions: Cross-channel memory. CanonicalSession tracks a user's conversation context across multiple channels. Compaction produces summaries that are injected into system prompts. Stored in canonical_sessions table (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:

rust
#[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:

  1. AnthropicDriver: Native Anthropic Messages API. Handles Claude-specific features (content blocks including images, tool use blocks, streaming deltas). Supports ContentBlock::Image with media type validation and 5MB cap.

  2. GeminiDriver: Native Google Gemini API (v1beta). Uses x-goog-api-key auth, systemInstruction, functionDeclarations, streamGenerateContent?alt=sse. Maps Gemini function call responses to the unified ToolUse stop reason.

  3. 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:

toml
[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 endpoint

When resolving the driver for an agent:

  1. If the agent uses the same provider as the kernel default (and no custom key/URL), reuse the kernel's shared driver instance.
  2. 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() and resolve_aliases() reference the catalog.
  • API: 4 endpoints (/api/models, /api/models/{id}, /api/models/aliases, /api/providers).
  • Channels: /models and /providers chat commands via ChannelBridgeHandle.

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

rust
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

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

text
Tool invocation request
    |
    v
CapabilityManager.check(agent_id, ToolInvoke("file_read"))
    |
    +-- Granted --> Validate path (traversal check) --> Execute tool
    |
    +-- Denied --> Return "Permission denied" error to LLM

The 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: DmPolicy and GroupPolicy enums enforce who can interact with agents in direct messages vs. group chats.
  • Formatter: formatter.rs converts Markdown to platform-specific formats (TelegramHTML, SlackMrkdwn, PlainText).
  • Rate Limiter: ChannelRateLimiter with 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, /think handled by ChannelBridgeHandle.

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:

  1. SHA256 verification (SkillVerifier): Ensures skill content matches its declared hash.
  2. Prompt injection scan (scan_prompt_content()): Detects malicious patterns in skill prompts and descriptions.
  3. Trust boundary markers: Skill-injected context in system prompts is wrapped with trust boundary markers.
  4. Subprocess env_clear(): Skill code execution uses environment isolation.

Ecosystem Bridges

  • FangHub: Native OpenFang marketplace (FangHubClient).
  • ClawHub: Cross-ecosystem compatibility (ClawHubClient connects 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 as mcp_{server}_{tool} to prevent collisions. Background connection in start_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 of McpServerConfigEntry with name, command, args, env, transport).
  • API: /api/mcp/servers returns 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): Publishes AgentCard at /.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 (optional A2aConfig).

Wire Protocol (OFP)

The OpenFang Protocol (OFP) enables peer-to-peer agent communication across machines.

Architecture

text
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:

  1. Initiator sends {nonce, node_id, hmac_sign(shared_secret, nonce + node_id)}.
  2. Responder verifies HMAC using constant-time comparison (subtle crate).
  3. Responder sends its own {nonce, node_id, hmac} challenge.
  4. Initiator verifies.
  5. 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):

text
WireMessage {
    id: UUID,
    sender: PeerId,
    payload: WireRequest | WireResponse
}

Request types:

  • Discover -- Request peer information and agent list
  • Advertise -- Announce local agents to a peer
  • RouteMessage -- Send a message to a remote agent
  • Ping -- Keepalive

Response types:

  • DiscoverResponse -- Peer info and agent list
  • RouteResponse -- Agent's response to a routed message
  • Pong -- Keepalive response

PeerRegistry

Tracks all known peers and their advertised agents:

rust
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 requests
  • OfpConnect(addr) -- Required to connect to a specific peer
  • OfpAdvertise -- 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

text
+-------------------------------------------+
| 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-instance prevents multiple app instances.
  • Notifications: tauri-plugin-notification for 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

text
/* 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

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
WhatsApp 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
Email 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")
Reddit OAuth2 polling REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USERNAME, REDDIT_PASSWORD Custom("reddit")
LinkedIn 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:

toml
[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 as Zeroizing<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
WhatsApp WA_ACCESS_TOKEN, WA_PHONE_ID, WA_VERIFY_TOKEN
Matrix MATRIX_TOKEN
Email 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:

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

Setup

  1. Open Telegram and message @BotFather.
  2. Send /newbot and follow the prompts to create a new bot.
  3. Copy the bot token.
  4. Set the environment variable:
bash
export TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
  1. Add to config:
toml
[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"
  1. Restart the daemon:
bash
openfang start

How 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:

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

bash
openfang channel setup telegram

This walks you through the setup interactively.


Discord

Prerequisites

Setup

  1. Go to Discord Developer Portal.
  2. Click "New Application" and name it.
  3. Go to the Bot section and click "Add Bot".
  4. Copy the bot token.
  5. Under Privileged Gateway Intents, enable:
    • Message Content Intent (required to read message content)
  6. 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.
  7. Set the environment variable:
bash
export DISCORD_BOT_TOKEN=MTIzNDU2Nzg5.ABCDEF.ghijklmnop
  1. Add to config:
toml
[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
default_agent = "coder"
  1. 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

  1. Go to Slack API and click "Create New App" > "From Scratch".
  2. Enable Socket Mode (Settings > Socket Mode):
    • Generate an App-Level Token with scope connections:write.
    • Copy the token (xapp-...).
  3. Go to OAuth & Permissions and add Bot Token Scopes:
    • chat:write
    • app_mentions:read
    • im:history
    • im:read
    • im:write
  4. Install the app to your workspace.
  5. Copy the Bot User OAuth Token (xoxb-...).
  6. Set the environment variables:
bash
export SLACK_APP_TOKEN=xapp-1-...
export SLACK_BOT_TOKEN=xoxb-...
  1. Add to config:
toml
[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
  1. 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.


WhatsApp

Prerequisites

  • A Meta Business account with WhatsApp Cloud API access

Setup

  1. Go to Meta for Developers.
  2. Create a Business App.
  3. Add the WhatsApp product.
  4. Set up a test phone number (or use a production one).
  5. Copy:
    • Phone Number ID
    • Permanent Access Token
    • Choose a Verify Token (any string you choose)
  6. Set environment variables:
bash
export WA_PHONE_ID=123456789012345
export WA_ACCESS_TOKEN=EAABs...
export WA_VERIFY_TOKEN=my-secret-verify-token
  1. Add to config:
toml
[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"
  1. 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
  2. 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

Setup

  1. Create a custom app in Feishu Open Platform.
  2. Enable the IM message event subscription for your app.
  3. Set environment variable:
bash
export FEISHU_APP_SECRET=cli_xxx_secret
  1. Add to config (default: websocket mode):
toml
[channels.feishu]
app_id = "cli_xxx"
app_secret_env = "FEISHU_APP_SECRET"
mode = "websocket"
default_agent = "assistant"
  1. Restart the daemon.

Webhook Compatibility Mode

If you need the legacy callback flow, switch to webhook and expose a public callback URL:

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

  1. Install signal-cli.
  2. Register or link a phone number.
  3. Add to config:
toml
[channels.signal]
signal_cli_path = "/usr/local/bin/signal-cli"
phone_number = "+1234567890"
default_agent = "assistant"
  1. 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

  1. Create a bot account on your Matrix homeserver.
  2. Generate an access token.
  3. Set the environment variable:
bash
export MATRIX_TOKEN=syt_...
  1. Add to config:
toml
[channels.matrix]
homeserver_url = "https://matrix.org"
access_token_env = "MATRIX_TOKEN"
user_id = "@openfang-bot:matrix.org"
default_agent = "assistant"
  1. Invite the bot to the rooms you want it to monitor.
  2. 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.


Email

Prerequisites

  • An email account with IMAP and SMTP access

Setup

  1. For Gmail, create an App Password.
  2. Set the environment variable:
bash
export EMAIL_PASSWORD=abcd-efgh-ijkl-mnop
  1. Add to config:
toml
[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"
  1. 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:

text
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:

  1. Bindings (most specific first). Declarative [[bindings]] rules in config.toml map 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.
  2. Per-channel default: Each channel config has a default_agent field. Messages from that channel go to that agent.
  3. 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.
  4. Command prefix: Users can switch agents by sending a command like /agent coder in the chat. Subsequent messages will be routed to the "coder" agent.
  5. 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.

toml
# 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_id matches the user (Discord user ID, Slack user ID, etc.).
  • channel_id matches 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

rust
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:

rust
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 named ChannelType variants (Telegram, WhatsApp, Slack, Discord, Signal, Matrix, Email, Teams, Mattermost). All others use Custom(String).
  • Wrap secrets in Zeroizing<String> so they are wiped from memory on drop.
  • Accept a watch::Receiver for 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:

rust
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:

rust
#[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)

bash
cargo install --path crates/openfang-cli

Build from workspace

bash
cargo build --release -p openfang-cli
# Binary: target/release/openfang (or openfang.exe on Windows)

Docker

bash
docker run -it openfang/openfang:latest

Shell installer

bash
curl -fsSL https://get.openfang.ai | sh

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

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

text
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 (0600 for files, 0700 for directories) on Unix.

Example:

bash
# Interactive setup
openfang init

# Non-interactive (CI/scripts)
export GROQ_API_KEY="gsk_..."
openfang init --quick

openfang start

Start the OpenFang daemon (kernel + API server).

text
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.json to ~/.openfang/ so other CLI commands can discover the running daemon.
  • Blocks until interrupted with Ctrl+C.

Output:

text
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 daemon

Example:

bash
# Start with default config
openfang start

# Start with custom config
openfang start --config /path/to/config.toml

openfang status

Show the current kernel/daemon status.

text
openfang status [--json]

Options:

Option Description
--json Output machine-readable JSON for scripting.

Behavior:

  • If a daemon is running: queries GET /api/status and 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:

bash
openfang status

openfang status --json | jq '.agent_count'

openfang doctor

Run diagnostic checks on the OpenFang installation.

text
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:

  1. OpenFang directory -- ~/.openfang/ exists
  2. .env file -- exists and has correct permissions (0600 on Unix)
  3. Config TOML syntax -- config.toml parses without errors
  4. Daemon status -- whether a daemon is running
  5. Port 4200 availability -- if daemon is not running, checks if the port is free
  6. Stale daemon.json -- leftover daemon.json from a crashed daemon
  7. Database file -- SQLite magic bytes validation
  8. Disk space -- warns if less than 100MB available (Unix only)
  9. Agent manifests -- validates all .toml files in ~/.openfang/agents/
  10. 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)
  11. Channel tokens -- format validation for Telegram, Discord, Slack tokens
  12. Config consistency -- checks that api_key_env references in config match actual environment variables
  13. Rust toolchain -- rustc --version

Example:

bash
openfang doctor

openfang doctor --repair

openfang doctor --json

openfang dashboard

Open the web dashboard in the default browser.

text
openfang dashboard

Behavior:

  • 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, pbcopy on macOS, xclip/xsel on Linux).

Example:

bash
openfang dashboard

openfang completion

Generate shell completion scripts.

text
openfang completion <SHELL>

Arguments:

Argument Description
<SHELL> Target shell. One of: bash, zsh, fish, elvish, powershell.

Example:

bash
# 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.ps1

Agent Commands

openfang agent new

Spawn an agent from a built-in template.

text
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), and OPENFANG_AGENTS_DIR (env override).
  • Each template is a directory containing an agent.toml manifest.
  • In daemon mode: sends POST /api/agents with the manifest. Agent is persistent.
  • In standalone mode: boots an in-process kernel. Agent is ephemeral.

Example:

bash
# Interactive picker
openfang agent new

# Spawn by name
openfang agent new coder

# Spawn the assistant template
openfang agent new assistant

openfang agent spawn

Spawn an agent from a custom manifest file.

text
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:

bash
openfang agent spawn ./my-agent/agent.toml

openfang agent list

List all running agents.

text
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:

bash
openfang agent list

openfang agent list --json | jq '.[].name'

openfang agent chat

Start an interactive chat session with a specific agent.

text
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 press Ctrl+C to end the session.

Example:

bash
openfang agent chat a1b2c3d4-e5f6-7890-abcd-ef1234567890

openfang agent kill

Terminate a running agent.

text
openfang agent kill <AGENT_ID>

Arguments:

Argument Description
<AGENT_ID> Agent UUID to terminate.

Example:

bash
openfang agent kill a1b2c3d4-e5f6-7890-abcd-ef1234567890

Workflow Commands

All workflow commands require a running daemon.

openfang workflow list

List all registered workflows.

text
openfang workflow list

Output columns: ID, NAME, STEPS, CREATED.


openfang workflow create

Create a workflow from a JSON definition file.

text
openfang workflow create <FILE>

Arguments:

Argument Description
<FILE> Path to a JSON file describing the workflow steps.

Example:

bash
openfang workflow create ./my-workflow.json

openfang workflow run

Execute a workflow by ID.

text
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:

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

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

text
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:

bash
# 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 10

openfang trigger delete

Delete a trigger by ID.

text
openfang trigger delete

Arguments:

Argument Description
`` UUID of the trigger to delete.

Skill Commands

openfang skill list

List all installed skills.

text
openfang skill list

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

text
openfang skill install

Arguments:

Argument Description
`` Skill name (FangHub), local directory path, or git URL.

Behavior:

  • Local directory: Looks for skill.toml in 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:

bash
# 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.

text
openfang skill remove <NAME>

Arguments:

Argument Description
<NAME> Name of the skill to remove.

Example:

bash
openfang skill remove web-search

Search the FangHub marketplace for skills.

text
openfang skill search <QUERY>

Arguments:

Argument Description
<QUERY> Search query string.

Example:

bash
openfang skill search "docker kubernetes"

openfang skill create

Interactively scaffold a new skill project.

text
openfang skill create

Behavior:

Prompts for:

  • Skill name
  • Description
  • Runtime (python, node, or wasm; defaults to python)

Creates a directory under ~/.openfang/skills/<name>/ with:

  • skill.toml -- manifest file
  • src/main.py (or src/index.js) -- entry point with boilerplate

Example:

bash
openfang skill create
# Skill name: my-tool
# Runtime (python/node/wasm) [python]: python

Channel Commands

openfang channel list

List configured channels and their status.

text
openfang channel list

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

text
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:

  1. Displays step-by-step instructions for obtaining credentials.
  2. Prompts for tokens/credentials.
  3. Saves tokens to ~/.openfang/.env with owner-only permissions.
  4. Appends the channel configuration block to config.toml (prompts for confirmation).
  5. Warns to restart the daemon if one is running.

Example:

bash
# Interactive picker
openfang channel setup

# Direct setup
openfang channel setup telegram
openfang channel setup discord
openfang channel setup slack

openfang channel test

Send a test message through a configured channel.

text
openfang channel test <CHANNEL>

Arguments:

Argument Description
<CHANNEL> Channel name to test.

Requires a running daemon. Sends POST /api/channels/<channel>/test.

Example:

bash
openfang channel test telegram

openfang channel enable

Enable a channel integration.

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

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

text
openfang config show

Prints the contents of ~/.openfang/config.toml with the file path as a header comment.


openfang config edit

Open the configuration file in your editor.

text
openfang config edit

Uses $EDITOR, then $VISUAL, then falls back to notepad (Windows) or vi (Unix).


openfang config get

Get a single configuration value by dotted key path.

text
openfang config get <KEY>

Arguments:

Argument Description
<KEY> Dotted key path into the TOML structure.

Example:

bash
openfang config get default_model.provider
# groq

openfang config get api_listen
# 127.0.0.1:4200

openfang config get memory.decay_rate
# 0.05

openfang config set

Set a configuration value by dotted key path.

text
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:

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

text
openfang config set-key

Arguments:

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/.env as _API_KEY=<value>.
  • Runs a live validation test against the provider's API.
  • File permissions are restricted to owner-only on Unix.

Example:

bash
openfang config set-key groq
# Paste your groq API key: gsk_...
# [ok] Saved GROQ_API_KEY to ~/.openfang/.env
# Testing key... OK

openfang config delete-key

Remove an API key from ~/.openfang/.env.

text
openfang config delete-key

Arguments:

Argument Description
`` Provider name.

Example:

bash
openfang config delete-key openai

openfang config test-key

Test provider connectivity with the stored API key.

text
openfang config test-key

Arguments:

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) or FAILED (401/403) (key rejected).
  • Exits with code 1 on failure.

Example:

bash
openfang config test-key groq
# Testing groq (GROQ_API_KEY)... OK

Quick Chat

openfang chat

Quick alias for starting a chat session.

text
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:

bash
# 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-ef1234567890

Migration

openfang migrate

Migrate configuration and agents from another agent framework.

text
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.md summarizing what was imported.

Example:

bash
# 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 autogpt

MCP Server

openfang mcp

Start an MCP (Model Context Protocol) server over stdio.

text
openfang mcp

Behavior:

  • 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:

json
{
  "mcpServers": {
    "openfang": {
      "command": "openfang",
      "args": ["mcp"]
    }
  }
}

Daemon Auto-Detect

The CLI uses a two-step mechanism to detect a running daemon:

  1. Read daemon.json: On startup, the daemon writes ~/.openfang/daemon.json containing the listen address (e.g. 127.0.0.1:4200). The CLI reads this file to learn where the daemon is.

  2. Health check: The CLI sends GET http://<listen_addr>/api/health with 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:

text
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 crashes

Environment 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:

bash
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

bash
# 1. Set your API key
export GROQ_API_KEY="gsk_your_key_here"

# 2. Initialize OpenFang
openfang init --quick

# 3. Start the daemon
openfang start

Daily usage

bash
# 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 dashboard

Agent management

bash
# 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 kill

Workflow automation

bash
# 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

bash
# 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 delete

Skill management

bash
# 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-reviewer

Channel setup

bash
# 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 slack

Configuration

bash
# 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 edit

Migration from other frameworks

bash
# Preview migration
openfang migrate --from openclaw --dry-run

# Run migration
openfang migrate --from openclaw

# Migrate from LangChain
openfang migrate --from langchain --source-dir ~/.langchain

MCP integration

bash
# Start MCP server for Claude Desktop or other MCP clients
openfang mcp

Diagnostics

bash
# Run all diagnostic checks
openfang doctor

# Auto-repair issues
openfang doctor --repair

# Machine-readable diagnostics
openfang doctor --json

Shell completions

bash
# Generate and install completions for your shell
openfang completion bash >> ~/.bashrc
openfang completion zsh > "${fpath[1]}/_openfang"
openfang completion fish > ~/.config/fish/completions/openfang.fish

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