Skip to content

Architecture

Molf Assistant is a monorepo with 10 packages under packages/, managed by pnpm workspaces. A central tRPC WebSocket server orchestrates LLM interactions while workers execute tool calls locally. Clients connect over WebSocket to drive conversations.

Package Overview

PackageDescription
protocolShared types, Zod schemas, tRPC router type definition, plugin system, credentials, TLS trust, tool definitions, truncation, WebSocket helpers
agent-coreAgent class (manual step loop with streamText), Session, context pruner, provider registry/catalog, system prompts
serverWebSocket server (tRPC v11), SessionManager, AgentRunner, EventBus, ToolDispatch, ApprovalGate, ConnectionRegistry, WorkspaceStore, PluginLoader, SubagentRunner
workerToolExecutor, skill/agent loading, server connection with auto-reconnect, StateWatcher, SyncCoordinator, worker plugin loader
client-tuiInk 5 + React 18 terminal client
client-telegramTelegram bot client via grammY framework
plugin-cronDefault server plugin: cron job scheduling with routes and session tool
plugin-mcpDefault worker plugin: MCP client integration (stdio + HTTP transport)
test-utilsShared test helpers: mockStreamText, createTmpDir, createEnvGuard, getFreePort
e2eIntegration and live test suites with server/worker test helpers

Dependency Graph

protocol
  ├──▲── agent-core
  │        ▲
  │        │
  │      server

  ├──▲── worker
  ├──▲── client-tui
  ├──▲── client-telegram
  ├──▲── plugin-cron
  └──▲── plugin-mcp

protocol sits at the base. agent-core builds on protocol to provide the Agent class and provider system. server depends on both protocol and agent-core. All other packages (worker, clients, plugins) depend only on protocol.

Communication

All communication uses tRPC v11 over WebSocket with TLS enabled by default. The server exposes 9 sub-routers:

RouterDomain
sessionSession lifecycle (create, list, load, delete, rename)
agentLLM interaction (prompt, abort, events subscription)
toolTool approval (approve, deny, list)
workerWorker registration, state sync, tool call dispatch
fsFile system reads (tool output retrieval)
providerLLM provider and model listing
workspaceWorkspace management and config
authPairing codes, API key management
pluginPlugin route dispatch

See Protocol for the full tRPC API reference.

Message Flow

Prompt Flow

Client                    Server                     Worker
  │                         │                          │
  ├─ agent.prompt ─────────►│                          │
  │                         ├─ AgentRunner.run()       │
  │                         ├─ streamText (LLM) ──►    │
  │                         │  ◄── tool_call           │
  │                         ├─ ToolDispatch ──────────►│
  │                         │                          ├─ ToolExecutor
  │                         │  ◄── toolResult ─────────┤
  │                         ├─ continue loop           │
  │                         │  ...                     │
  │  ◄── turn_complete ─────┤                          │
  1. Client sends agent.prompt with session ID and text.
  2. AgentRunner resolves the model (prompt-level > workspace config > server default), builds the system prompt, and calls streamText from Vercel AI SDK.
  3. When the LLM emits tool calls, ToolDispatch routes them to the bound worker via promise queuing (120s timeout).
  4. The worker executes the tool via ToolExecutor and returns the result.
  5. The agent loop continues until the LLM produces a final response or maxSteps is reached.

Event Flow

AgentRunner ──► EventBus ──► agent.onEvents subscription ──► Client

The AgentRunner emits events per session through the EventBus. Clients subscribe via agent.onEvents to receive streaming updates. Nine event types are emitted: status_change, content_delta, tool_call_start, tool_call_end, turn_complete, error, tool_approval_required, context_compacted, and subagent_event.

Key Abstractions

AgentRunner

Orchestrates LLM interactions. Maintains a cache of Agent instances per session (evicted after 30 minutes idle). Builds system prompts from default instructions, skill hints, task hints, workdir context, media references, and runtime context. Dispatches hooks at turn_start, before_prompt, after_prompt, and turn_end.

ToolDispatch

Routes tool calls from the server to the connected worker. Uses promise queuing with a 120-second timeout. If a worker disconnects, all pending dispatches are rejected immediately.

EventBus

Per-session event channels. AgentRunner publishes events; clients consume them via tRPC subscriptions.

ConnectionRegistry

Tracks all connected WebSocket clients (workers and clients). Worker state persists across disconnects -- workers are marked offline rather than removed. Dispatches worker_connect and worker_disconnect hooks.

ApprovalGate

Three-layer tool approval evaluation: agent permissions (subagent sessions only), static rules from permissions.jsonc, and runtime "always approve" patterns. See Tool Approval.

PluginLoader

Loads server plugins from config, validates config against plugin schemas, and manages the plugin lifecycle. Tracks worker plugin specifiers to send to workers on connect. See Plugins.

SessionManager

In-memory session cache with JSON file persistence at {dataDir}/sessions/{id}.json. Uses atomic writes (tmp file + rename). Dispatches session_create, session_delete, and session_save hooks.

WorkspaceStore

Groups sessions into workspaces. Each workspace carries a per-workspace model config override. Persisted at {dataDir}/workers/{workerId}/workspaces/{workspaceId}/workspace.json.

Server Module Table

ModuleDescription
main.tsEntry point: CLI parsing, config resolution, LogTape setup, server start
config.tsConfig resolution (YAML + CLI + env), defaults
server.tsWebSocket server initialization, TLS, component wiring
router.tstRPC router composition (9 sub-routers)
context.tstRPC context and middleware (auth)
agent-runner.tsLLM orchestration, system prompt building, model resolution
session-mgr.tsSession persistence and caching
event-bus.tsPer-session event channels
auth.tsToken verification, API key management
tls.tsSelf-signed certificate generation
connection-registry.tsWebSocket client tracking
worker-store.tsWorker state persistence
worker-dispatch.tsTool call, upload, and FS read dispatch to workers
workspace-store.tsWorkspace config and session grouping
workspace-notifier.tsWorkspace event subscriptions
plugin-loader.tsServer plugin loading and lifecycle
plugin-api.tsServerPluginApi implementation
plugin-routes.tsPlugin route tRPC integration
summarization.tsContext summarization
subagent-runner.tsSubagent session lifecycle
subagent-types.tsBuilt-in agent definitions (explore, general)
pairing.tsPairing code store
approval/approval-gate.tsThree-layer tool approval
approval/evaluate.tsPattern matching and rule evaluation
approval/ruleset-storage.tspermissions.jsonc persistence
approval/shell-parser.tsShell command parsing for approval

Worker Module Table

ModuleDescription
index.tsEntry point: CLI, identity, TLS, connection, plugin loading
cli.tsCLI argument parsing
identity.tsPersistent worker UUID
connection.tsServer connection with auto-reconnect
tool-executor.tsTool registration and execution
skills.tsSkill and AGENTS.md loading
agents.tsAgent definition loading
state-watcher.tsFile system watching for skills/agents changes
sync-coordinator.tsSerialized state sync to server
plugin-loader.tsWorker plugin loading
plugin-api.tsWorkerPluginApi implementation
pair.tsTOFU + pairing code exchange
truncation.tsTool output truncation and storage

See also

  • Protocol -- full tRPC API reference
  • Plugins -- plugin and hook system
  • Logging -- structured logging configuration