Architecture
ClawHalla is a multi-layered system that connects AI agents to messaging surfaces, management dashboards, and blockchain infrastructure. This document covers the full architecture.
System Diagram
┌──────────────────────────────────────────────┐ │ Channels │ │ Telegram │ Discord │ Web Chat │ API │ └──────────────────┬───────────────────────────┘ │ ┌──────────────────▼───────────────────────────┐ │ OpenClaw Gateway │ │ ws://127.0.0.1:18789 │ │ │ │ ┌─────────┐ ┌──────────┐ ┌───────────┐ │ │ │ Auth │ │ Router │ │ Cron │ │ │ │ Profiles│ │ Bindings │ │ Scheduler│ │ │ └─────────┘ └──────────┘ └───────────┘ │ └──────────────────┬───────────────────────────┘ │ ┌──────────────────▼───────────────────────────┐ │ Agent Layer │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ Claw │ │ Thor │ │ Vidar│ │Frigg │ ... │ │ │Chief │ │ Dev │ │ B/C │ │ PA │ │ │ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │ │ │ │ │ │ │ │ ┌──▼────────▼────────▼────────▼──┐ │ │ │ Workspace (Markdown Files) │ │ │ │ SOUL.md │ AGENTS.md │ memory/ │ │ │ └────────────────────────────────┘ │ └──────────────────┬───────────────────────────┘ │ ┌────────────────────────────┼────────────────────────────┐ │ │ │┌─────────▼──────────┐ ┌─────────────▼───────────┐ ┌────────────▼──────────┐│ Mission Control │ │ File System │ │ Smart Contracts ││ (Next.js @ :3000) │ │ ~/.openclaw/ │ │ (Base L2) ││ │ │ │ │ ││ Dashboard │ │ openclaw.json │ │ AgentRegistry.sol ││ Tasks / Sprints │ │ agents/ │ │ LicenseNFT.sol ││ Approvals │ │ workspace/ │ │ Marketplace.sol ││ Agent Factory │ │ cron/ │ │ ││ Vault │ │ logs/ │ │ ││ Memory │ │ skills/ │ │ │└────────────────────┘ └───────────────────────────┘ └───────────────────────┘ │┌────────▼───────────┐│ SQLite DB ││ 23 tables ││ 11 indexes ││ (Drizzle ORM) │└────────────────────┘Gateway
The OpenClaw Gateway is a single long-lived WebSocket server that owns all messaging surfaces.
Wire protocol
Communication uses a JSON-based request/response protocol over WebSocket:
Client → Gateway: { type: "req", id, method, params }Gateway → Client: { type: "res", id, ok, payload | error }Gateway → Client: { type: "event", event, payload, seq?, stateVersion? }The first frame from any client must be a connect request:
{ "type": "req", "id": "1", "method": "connect", "params": { "auth": { "token": "your-gateway-token" } }}Node roles
Clients can declare role: node with capabilities and commands, enabling them to act as macOS, iOS, Android, or headless execution nodes.
Agent routing
The gateway routes incoming messages to agents based on binding rules:
- Message arrives on a channel (Telegram, Discord, etc.)
- Router checks bindings: which agent handles this channel/chat?
- Agent session is created or resumed
- Bootstrap files are injected into the context
- Model call is made with full context
- Response flows back through the channel
Agent Hierarchy
ClawHalla organizes agents into four tiers:
Tier 0 — Chief Orchestrator
| Agent | Role | Model |
|---|---|---|
| Claw | Chief Orchestrator | Opus 4.6 |
The chief orchestrator manages runtime, configuration, and agent coordination. It delegates work to squad leads and approves outgoing actions.
Personal Squad
| Agent | Role | Model |
|---|---|---|
| Frigg | Personal Assistant / Coordinator | Haiku 4.5 |
| Mimir | Knowledge Curator | Sonnet 4.6 |
Handles scheduling, memory curation, and personal coordination for Daniel.
Dev Squad
| Agent | Role | Model |
|---|---|---|
| Thor | Tech Lead | Sonnet 4.6 |
| Freya | Senior Dev | Sonnet 4.6 |
| Tyr | Security Auditor | Opus 4.6 |
Full-stack development, code review, and security auditing.
Social Squad
| Agent | Role | Model |
|---|---|---|
| Saga | Research Lead | Sonnet 4.6 |
| Bragi | Content Creator | Sonnet 4.6 |
Content research, creation, and publishing across social platforms.
Blockchain
| Agent | Role | Model |
|---|---|---|
| Vidar | Blockchain Architect | Sonnet 4.6 |
Smart contracts, DeFi, and blockchain architecture.
Squads
Agents are grouped into squads with clear domains:
| Squad | Lead | Domain |
|---|---|---|
| personal | Frigg | Scheduling, memory, coordination |
| dev_squad | Thor | Full-stack development, security |
| social | Saga | Content, research, publishing |
| blockchain | Vidar | Smart contracts, DeFi |
Escalation chain
Execution → Management: blocker, conflict, unclear requirementsManagement → Executive: architecture decision, resource conflict, deadline riskExecutive → CEO: budget, strategy, external communication, deploy approvalData Model
Mission Control uses SQLite with Drizzle ORM. The database contains 23 tables with 11 indexes on the most queried columns:
Core tables
agents — Registered agent metadata
CREATE TABLE agents ( id TEXT PRIMARY KEY, name TEXT NOT NULL, role TEXT NOT NULL, tier INTEGER NOT NULL, squad TEXT, model TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'idle', emoji TEXT, reports_to TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);tasks — Work items
CREATE TABLE tasks ( id TEXT PRIMARY KEY, title TEXT NOT NULL, description TEXT, status TEXT NOT NULL DEFAULT 'backlog', -- backlog, in_progress, review, done, blocked priority TEXT NOT NULL DEFAULT 'medium', -- low, medium, high, critical assigned_to TEXT, project_id TEXT, story_id TEXT, sprint_id TEXT, estimated_hours INTEGER, actual_hours INTEGER, tags TEXT, notes TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, completed_at INTEGER);epics — Large feature groupings
CREATE TABLE epics ( id TEXT PRIMARY KEY, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'active', created_by TEXT, approved_by TEXT, priority TEXT DEFAULT 'medium', notes TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, completed_at INTEGER);stories — User stories linked to epics
CREATE TABLE stories ( id TEXT PRIMARY KEY, epic_id TEXT, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'backlog', points INTEGER, assigned_to TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, completed_at INTEGER);sprints — Time-boxed work periods
CREATE TABLE sprints ( id TEXT PRIMARY KEY, name TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'planning', -- planning, active, completed start_date TEXT, end_date TEXT, story_ids TEXT, -- JSON array of story IDs created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);projects — Top-level project containers
CREATE TABLE projects ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, status TEXT NOT NULL DEFAULT 'active', squad TEXT, start_date INTEGER, end_date INTEGER, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);Operational tables
activities — Agent action log
CREATE TABLE activities ( id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, action TEXT NOT NULL, target TEXT, details TEXT, timestamp INTEGER NOT NULL);approvals — Human approval queue
CREATE TABLE approvals ( id TEXT PRIMARY KEY, task_id TEXT NOT NULL, requested_by TEXT NOT NULL, approver TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', -- pending, approved, rejected command TEXT, reason TEXT, created_at INTEGER NOT NULL, resolved_at INTEGER);cost_events — Token usage and cost tracking
CREATE TABLE cost_events ( id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, model TEXT NOT NULL, action TEXT NOT NULL, -- session, task, search, api_call input_tokens INTEGER DEFAULT 0, output_tokens INTEGER DEFAULT 0, estimated_cost_cents INTEGER DEFAULT 0, task_id TEXT, timestamp INTEGER NOT NULL);secrets — Encrypted vault
CREATE TABLE secrets ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, description TEXT, encrypted_value TEXT NOT NULL, -- AES-256-GCM encrypted iv TEXT NOT NULL, -- Initialization vector category TEXT NOT NULL DEFAULT 'api_key', created_by TEXT NOT NULL DEFAULT 'daniel', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, last_accessed_at INTEGER);workspace_files — File metadata index
CREATE TABLE workspace_files ( id TEXT PRIMARY KEY, path TEXT NOT NULL, type TEXT NOT NULL, size INTEGER, last_modified INTEGER NOT NULL, created_at INTEGER NOT NULL);Memory & RAG System
Each agent has its own memory store with two layers:
Agent Memory Directory (.md files) │ ├── FTS5 Index (keyword search) │ └── SQLite with porter stemming │ └── Vector Index (semantic search) └── Embeddings from configurable provider ├── Ollama (local, Docker) ├── Node GGUF (node-llama-cpp) ├── OpenAI / Gemini / Voyage / Mistral └── Per-agent: RAG | .md-only | defaultThe RAG system is configured globally via agents.defaults.memorySearch in openclaw.json, with per-agent overrides on agents.list[n].memorySearch. Mission Control provides a UI for managing both.
Boards Engine (v1.0.1)
boards — Multi-board Kanban with customizable columns
CREATE TABLE boards ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, type TEXT NOT NULL DEFAULT 'kanban', -- kanban | sprint | custom columns TEXT NOT NULL, -- JSON array of { id, name, color, wipLimit } owner TEXT NOT NULL DEFAULT 'user', squad TEXT, settings TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, archived_at INTEGER);cards — Board cards with full metadata
CREATE TABLE cards ( id TEXT PRIMARY KEY, board_id TEXT NOT NULL, title TEXT NOT NULL, description TEXT, column TEXT NOT NULL, position INTEGER DEFAULT 0, assignee TEXT, labels TEXT, priority TEXT DEFAULT 'medium', due_date INTEGER, checklist TEXT, attachments TEXT, parent_card_id TEXT, story_id TEXT, epic_id TEXT, sprint_id TEXT, progress INTEGER DEFAULT 0, created_by TEXT DEFAULT 'user', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, completed_at INTEGER, archived_at INTEGER);-- Indexes: idx_cards_board, idx_cards_board_column, idx_cards_assigneecard_comments / card_history — Comments and change tracking per card.
Chat Engine
chat_sessions — Persistent chat sessions with mode (single/party) chat_messages — Messages with tool calls, thinking content, artifacts
Content & Notifications
content_drafts — Social media content (LinkedIn, Twitter, blog, etc.) content_pipelines — Multi-step content generation workflows notifications — System notifications with priority and read/dismissed state
Autopilot
autopilot_goals — Goal-driven autonomous execution targets autopilot_runs — Run history with status and feedback
Settings
settings — Key-value system configuration
Real-Time Pipeline
Mission Control uses a file-watching pipeline to react to workspace changes in real time.
How it works
Workspace files change │ ▼ Chokidar watcher (watches board/, memory/, org_structure.yaml, knowledge_base/) │ ├──▶ Log activity to DB (activities table) ├──▶ Reindex searchable files (search index) └──▶ Emit SSE event to connected clients │ ▼ Browser dashboard updates in real timeWatched paths
The watcher monitors these paths for changes:
workspace/company/org_structure.yaml— Org changesworkspace/projects/clawhalla/board/— Task board updatesworkspace/memory/— Daily memory logsworkspace/company/knowledge_base/— Knowledge articles
Indexable file types
Only .md, .yaml, and .yml files are indexed for full-text search.
SSE connection
Clients connect to GET /api/sse for real-time updates. The connection sends:
- connected event on first connection
- file_change events when watched files change
- ping events every 30 seconds as keepalive
Security Model
Vault
Secrets are stored encrypted in SQLite using AES-256-GCM:
- A passphrase (
VAULT_KEYorGATEWAY_TOKEN) is derived into a 256-bit key usingscrypt - Each secret gets a random 128-bit IV
- Encryption produces ciphertext + 128-bit authentication tag
- The
GET /api/vaultendpoint never returns decrypted values - Only
POST /api/vault/revealreturns the plaintext (use sparingly)
Gateway authentication
The gateway uses a shared token for all connections. Clients must include the token in their connect frame. Without a valid token, the connection is rejected.
Agent sandboxing
Agents can be sandboxed with restricted tool access:
{ "tools": { "allow": ["exec", "read", "sessions_list"], "deny": ["write", "edit", "browser", "cron"] }}Full Docker sandboxing is also available per agent:
{ "sandbox": { "mode": "all", "scope": "agent", "docker": { "setupCommand": "apt-get update && apt-get install -y git" } }}Mission Control Security (v1.0.1)
- CSP — Content-Security-Policy header on all responses (
unsafe-evalonly in dev) - CORS — Middleware blocks unknown origins on
/api/*routes - Rate limiting — In-memory limiter: dispatch (3 concurrent/10 per min), chat (5/20), council (1/3)
- Auth — Per-process crypto session token on all destructive endpoints (DELETE, reset)
- XSS prevention — HTML escaping + URL sanitization (
javascript:,data:blocked) - Terminal — Regex-based command blocklist + cwd restricted to
$HOMEand/tmp - IDs —
crypto.randomUUID()for all generated identifiers (no collisions)
Approval gates
All external actions require human approval:
- Agent completes work
- Task moves to Review
- Approval request is created
- Human reviews and responds (approve/reject)
- Only on explicit approval does execution proceed
Implicit approval does not exist. Silence is not approval.
Smart Contracts
ClawHalla includes three Solidity contracts deployed on Base L2 for the agent marketplace:
AgentRegistry.sol
On-chain registry of agent templates with creator attribution.
Key functions:
registerTemplate(metadataURI, price, royaltyBps)— Register a new agent templateupdateTemplate(id, metadataURI, price)— Update metadata and pricedeactivateTemplate(id)— Remove from marketplacerecordInstall(id, buyer)— Track installations (marketplace only)getTemplate(id)— Read template detailsgetTemplatesByCreator(address)— List creator’s templates
Template data:
struct AgentTemplate { uint256 id; address creator; string metadataURI; // IPFS or URL to template files uint256 price; // in wei uint16 royaltyBps; // max 1000 (10%) bool active; uint256 installs; uint256 createdAt;}LicenseNFT.sol
ERC-721 compatible license tokens for agent template access.
Key functions:
mint(to, templateId)— Mint a license (marketplace only)holdsValidLicense(user, templateId)— Check if user is licensedlicensesOf(user)— List user’s valid licensesrevokeLicense(tokenId)— Revoke access (owner only)- Standard ERC-721:
transferFrom,approve,balanceOf,ownerOf
License data:
struct License { uint256 templateId; address originalBuyer; uint256 purchasedAt; bool revoked;}Marketplace.sol
Handles purchases, royalty splits, and license minting.
Key functions:
purchase(templateId)— Buy a template (mints license NFT)hasLicense(user, templateId)— Quick license checksetPlatformFee(feeBps)— Adjust platform fee (max 10%)withdrawFees()— Withdraw accumulated platform feespause()/unpause()— Emergency circuit breaker
Purchase flow:
- Buyer calls
purchase(templateId)with ETH payment - Marketplace verifies template is active and buyer is not already licensed
- Payment is split: creator gets
price - platformFee, platform keeps fee - License NFT is minted to the buyer
- Install count is incremented on the registry
Fee structure:
- Platform fee: 2.5% default (max 10%)
- Creator royalty: set by creator at registration (max 10%)
- Duplicate purchase prevention:
holdsValidLicensecheck
Security features:
- Two-step ownership transfer (prevent accidental transfers)
- Pause mechanism for emergencies
- Checks-effects-interactions pattern for reentrancy protection
- Payment based on
template.price, notmsg.value(prevents overpayment exploitation) - Excess ETH is refunded to buyer