KithKit Architecture — BMO Instance

Three-tier agent framework: Human ↔ Comms ↔ Daemon ↔ Orchestrator ↔ Workers

System Overview

graph TB
    Human["👤 Human\nTelegram · Email · Voice · Browser"]

    subgraph CommsAgent["Comms Agent"]
        ClaudeComms["Claude Code\n(persistent session + personality)"]
    end

    subgraph Daemon["Daemon"]
        HTTP["HTTP API"]
        DB["SQLite + Memory"]
        Routing["Message & Channel Router"]
        AgentMgr["Agent Lifecycle"]
        Scheduler["Scheduler"]
    end

    subgraph Orchestrator["Orchestrator"]
        ClaudeOrch["Claude Code\n(on-demand session)"]
    end

    Workers["Workers\nresearch · coding · testing"]
    Peers["Peer Agents\nLAN direct · P2P relay"]

    Human <-->|"channels"| Routing
    CommsAgent <-->|"HTTP API"| HTTP
    CommsAgent -->|"escalate"| HTTP
    HTTP --- DB
    HTTP --- Routing
    HTTP --- AgentMgr
    HTTP --- Scheduler
    Routing -->|"inject"| CommsAgent
    Routing -->|"inject"| Orchestrator
    Orchestrator -->|"spawn"| AgentMgr
    AgentMgr -->|"SDK"| Workers
    Workers -->|"results"| Routing
    CommsAgent <-->|"agent-comms"| Peers

Comms Agent

Persistent tmux session "bmo". Full BMO personality from identity.md. Talks to human, delegates complex tasks to orchestrator. Never does multi-step implementation work.

Daemon

Node.js HTTP server on localhost:3847. Owns SQLite DB (WAL). Routes messages, manages agent lifecycle, runs scheduler, handles channel delivery. Extension-based architecture.

Orchestrator

On-demand tmux session "bmo-orch". Spawned via POST /api/orchestrator/escalate. Decomposes tasks, spawns workers, synthesizes results. Auto-kills after 15min idle.

Workers

Ephemeral Claude Code agents. Profiles: research (read-only), coding (implementation), testing (test runner). Spawned by orchestrator via SDK adapter. Results sent via message router.

Daemon Internal Architecture

graph TB
    subgraph Server["HTTP Server (localhost:3847)"]
        Router["Route Registry\n(registerRoute)"]
    end

    subgraph CoreAPI["Core API Routes"]
        Health["/health, /status"]
        AgentsAPI["/api/agents/*\n(spawn, list, kill)"]
        OrchAPI["/api/orchestrator/*\n(escalate, status, shutdown)"]
        MsgsAPI["/api/messages\n(inter-agent)"]
        SendAPI["/api/send\n(channel delivery)"]
        TodosAPI["/api/todos"]
        CalendarAPI["/api/calendar"]
        MemoryAPI["/api/memory/*\n(store, search)"]
        TasksAPI["/api/tasks\n(scheduler control)"]
        TimerAPI["/api/timer\n(self-timer alarms)"]
        ConfigAPI["/api/config/reload"]
        UsageAPI["/api/usage"]
        ActivityAPI["/api/agents/:id/activity"]
    end

    subgraph ExtRoutes["Extension Routes (BMO)"]
        TelegramWH["/telegram\n(webhook)"]
        ShortcutRT["/shortcut"]
        AgentP2P["/agent/p2p\n(A2A envelope)"]
        AgentMsg["/agent/message"]
        AgentSend["/agent/send"]
        AgentStatus["/agent/status"]
        ExtStatus["/agent/extended-status"]
        CoworkAPI["/api/cowork/*\n(tabs, cdp, psk)"]
        ContextAPI["/api/context"]
    end

    subgraph CoreModules["Core Modules"]
        DB["SQLite\n(kithkit.db, WAL)"]
        Logger["Logger\n(winston-style)"]
        Config["Config Loader\n(YAML deep-merge)"]
        Keychain["Keychain Reader\n(macOS security)"]
        RouteReg["Route Registry"]
        ExtReg["Extension Registry"]
    end

    subgraph AgentSys["Agent System"]
        Lifecycle["lifecycle.ts\n(spawn/monitor/kill/queue)"]
        SDKAdapter["sdk-adapter.ts\n(Claude SDK wrapper)"]
        Profiles["profiles.ts\n(YAML frontmatter)"]
        TmuxMgr["tmux.ts\n(session management)"]
        MsgRouterMod["message-router.ts\n(dedup, inject, store)"]
    end

    subgraph MemSys["Memory System"]
        KeywordSearch["Keyword Search\n(AND matching, relevance)"]
        VectorSearch["Vector Search\n(MiniLM-L6-v2 ONNX)"]
        HybridSearch["Hybrid Search\n(keyword + vector)"]
        SQLiteVec["sqlite-vec\n(native extension)"]
    end

    Router --> CoreAPI
    Router --> ExtRoutes
    AgentsAPI --> Lifecycle
    OrchAPI --> TmuxMgr
    MsgsAPI --> MsgRouterMod
    SendAPI --> ChanRouterMod["channel-router.ts"]
    MemoryAPI --> KeywordSearch
    MemoryAPI --> HybridSearch
    Lifecycle --> SDKAdapter
    Lifecycle --> Profiles
    Lifecycle --> DB
    MsgRouterMod --> TmuxMgr
    MsgRouterMod --> DB
    HybridSearch --> KeywordSearch
    HybridSearch --> VectorSearch
    VectorSearch --> SQLiteVec

Route Registry

Core routes handle agents, messages, todos, memory, scheduler. Extension routes (BMO) add Telegram webhook, agent-comms, cowork bridge, and more. Routes registered via registerRoute().

Agent Lifecycle

Workers: queued -> running -> completed/failed/timeout. Persistent agents: idle / busy. Max concurrent enforcement with FIFO queue. SDK adapter wraps Claude Code SDK for spawning.

Memory System

Three search modes: keyword (AND matching, always available), vector (MiniLM-L6-v2 ONNX via sqlite-vec, requires enableVectorSearch()), hybrid (combines both scores).

SQLite Database

Tables: agents, worker_jobs, memories, todos, todo_actions, calendar, messages, config, feature_state, task_results, migrations. WAL mode for concurrent reads.

All

Use the scrubber to step through the message flow one interaction at a time.

Message Flow Paths

sequenceDiagram
    participant H as Human (Dave)
    participant TG as Telegram
    participant D as Daemon
    participant C as Comms Agent
    participant O as Orchestrator
    participant W as Worker

    Note over H,W: Inbound: Human to Agent
    H->>TG: Send message
    TG->>D: POST /telegram (webhook)
    D->>D: Access control check (5-tier)
    D->>C: tmux send-keys (inject message)
    C->>C: Process and respond

    Note over H,W: Outbound: Agent to Human
    C->>D: POST /api/send (message, channels: telegram)
    D->>D: Channel router selects adapter
    D->>TG: Telegram Bot API (sendMessage)
    TG->>H: Deliver message

    Note over H,W: Task Escalation Flow
    C->>D: POST /api/orchestrator/escalate (task)
    D->>D: Check if orchestrator alive
    alt Orchestrator not running
        D->>D: buildOrchestratorPrompt + memory injection
        D->>O: spawnOrchestratorSession (tmux: bmo-orch)
    end
    D->>D: sendMessage(comms to orch, type task)
    D->>O: tmux send-keys (inject task)
    O->>O: Decompose task

    Note over H,W: Worker Spawning
    O->>D: POST /api/agents/spawn (profile, prompt)
    D->>D: Load profile (.claude/agents/*.md)
    D->>W: SDK spawn (Claude Code)
    W->>W: Execute task
    W->>D: POST /api/messages (type result)
    D->>D: Store in SQLite and notify
    D->>O: tmux send-keys (result notification)

    Note over H,W: Result Delivery
    O->>D: POST /api/messages (from orch, to comms, type result)
    D->>C: tmux send-keys (inject result)
    C->>D: POST /api/send (message, channels: telegram)
    D->>TG: Telegram Bot API
    TG->>H: Final result
All

Inter-Agent Communication

sequenceDiagram
    participant BMO as Agent A (localhost)
    participant R2 as Peer Agent (LAN)
    participant Relay as Relay (relay.bmobot.ai)
    participant Remote as Remote Agent

    Note over BMO,Remote: LAN: Direct Agent-to-Agent
    BMO->>R2: POST /agent/message (Bearer token auth)
    R2->>R2: Validate HMAC and process
    R2->>BMO: POST /agent/message (response)

    Note over BMO,Remote: Peer Heartbeat (interval)
    BMO->>R2: POST /agent/status (agent, status)
    R2->>BMO: 200 (agent, status, latencyMs)

    Note over BMO,Remote: P2P: Via Network SDK
    BMO->>Relay: WebSocket (register, heartbeat)
    Remote->>Relay: Route envelope to BMO
    Relay->>BMO: POST /agent/p2p (WireEnvelope)
    BMO->>BMO: handleIncomingP2P()

Scheduler Tasks

graph LR
    subgraph Core["Core Tasks (kithkit framework)"]
        CW["context-watchdog\ninterval: 3m\nMonitors comms context usage"]
        TR["todo-reminder\ninterval: 30m\nNudges on open todos"]
        AA["approval-audit\ncron: biannual\nApproval review"]
        BK["backup\ncron: Sun 03:00\nWeekly backup"]
        OI["orchestrator-idle\ninterval: 2m\nKills idle orch (15min timeout)"]
        MD["message-delivery\ninterval: 5s\nDelivers pending messages"]
        CH["comms-heartbeat\ninterval: 60s\nChecks unacked workers/msgs"]
    end

    subgraph BMO["BMO Extension Tasks"]
        EC["email-check\ninterval: 15m\nIMAP/Graph inbox scan"]
        NT["nightly-todo\ncron: 22:00\nEnd-of-day todo review"]
        HC["health-check\ncron: Mon 08:00\nWeekly system health"]
        MC["memory-consolidation\ncron: 05:00\nDaily memory cleanup"]
        MB["morning-briefing\ncron: 07:00\nDaily briefing"]
        PH["peer-heartbeat\ninterval: 5m\nLAN peer status exchange"]
        AD["a2a-digest\ncron: Mon 09:00\nWeekly A2A network digest"]
        MS["memory-sync\ninterval: 30m\nCross-agent memory sync"]
        LI["lindee-inbox-watch\ninterval: 15m\nEmail monitoring"]
        SK["supabase-keep-alive\ncron: every 3 days\nPrevent free tier pause"]
        BR["blog-reminder\ncron: Mon,Thu 14:00\nBlog writing nudge"]
        WP["weekly-progress-report\ncron: Fri 16:00\nSend progress report"]
    end

    subgraph Engine["Scheduler Engine"]
        Tick["Tick Loop (1s)"]
        Cron["Cron Parser"]
        Interval["Interval Tracker"]
        Runner["Task Runner\n(in-process handlers\nor subprocess)"]
    end

    Tick --> Cron
    Tick --> Interval
    Cron --> Runner
    Interval --> Runner
    Runner --> Core
    Runner --> BMO

Communication Channels and BMO Extension

graph TB
    subgraph Extension["BMO Extension (extensions/index.ts)"]
        onInit["onInit()"]
        onShutdown["onShutdown()"]
    end

    subgraph Channels["Communication Channels"]
        subgraph TGChan["Telegram"]
            TGBot["Bot API\n(webhook: /telegram)"]
            TGOwner["Owner Auth\n(chat ID allowlist)"]
            TGAccess["5-tier Access Control"]
        end
        subgraph EmailChan["Email"]
            Graph["Microsoft Graph"]
            JMAP["Fastmail JMAP"]
            Himalaya["Himalaya CLI (Gmail)"]
            OutlookIMAP["Outlook IMAP"]
            Triage["Email Triage\n(VIP, junk, newsletters,\nreceipts, auto-read)"]
        end
        subgraph VoiceChan["Voice"]
            STT["Whisper-cpp (small.en)"]
            TTS["Kokoro (am_adam)"]
            Wake["OpenWakeWord\n(Hey BMO)"]
        end
    end

    subgraph AgentNet["Agent Networking"]
        subgraph LAN["LAN Comms"]
            HB["Peer Heartbeat\n(5min interval)"]
            HMAC["HMAC Auth\n(keychain secret)"]
            R2Peer["Peer Agent\n(LAN discovery)"]
        end
        subgraph P2P["P2P Network"]
            SDK["A2A SDK"]
            RelayWS["Relay: relay.bmobot.ai"]
            Endpoint["Endpoint: bmo.bmobot.ai/agent/p2p"]
        end
    end

    subgraph Cowork["Cowork Bridge"]
        WS["WebSocket Server\n(ws library, /cowork)"]
        Auth["Token Auth\n(5s timeout)"]
        KeyEx["ECDH Key Exchange\n(X25519 + PSK)"]
        E2E["E2E Encryption\n(AES-256-GCM + seq numbers)"]
        CDP["Chrome DevTools Protocol\n(tab control, JS eval)"]
    end

    onInit --> TGChan
    onInit --> EmailChan
    onInit --> VoiceChan
    onInit --> LAN
    onInit --> P2P
    onInit --> Cowork

KithKit Architecture Visualization | Three-tier agent framework
Daemon: HTTP API server | Comms: persistent session | Orchestrator: on-demand session
Database: SQLite (WAL mode) | Peers: LAN agents
Last updated: