Files
nanobot-ts/docs/Architecture.md

7.3 KiB

Architecture

Tech Stack

Layer Technology
Runtime Bun (v1.0+)
Language TypeScript (strict mode)
LLM Abstraction Vercel AI SDK v6
Validation Zod v4
CLI Commander
Colors picocolors
Formatting oxfmt (single quotes)
Linting oxlint

Folder Structure

nanobot-ts/
├── index.ts                    # Entry point
├── src/
│   ├── agent/
│   │   ├── loop.ts             # AgentLoop: LLM ↔ tool execution loop
│   │   ├── context.ts          # ContextBuilder: system prompt assembly
│   │   ├── memory.ts           # MemoryConsolidator: token management
│   │   ├── skills.ts           # Skill loader from workspace
│   │   ├── subagent.ts         # SubagentManager: background tasks
│   │   └── tools/
│   │       ├── base.ts         # Tool interface + ToolRegistry
│   │       ├── filesystem.ts   # read_file, write_file, edit_file, list_dir
│   │       ├── shell.ts        # exec
│   │       ├── web.ts          # web_search, web_fetch
│   │       ├── message.ts      # message
│   │       ├── spawn.ts        # spawn
│   │       └── cron.ts         # cron
│   ├── channels/
│   │   ├── base.ts             # BaseChannel abstract class
│   │   ├── mattermost.ts       # Mattermost WebSocket + REST
│   │   └── manager.ts          # ChannelManager lifecycle
│   ├── bus/
│   │   ├── types.ts            # InboundMessage, OutboundMessage schemas
│   │   └── queue.ts            # AsyncQueue, MessageBus
│   ├── provider/
│   │   ├── types.ts            # LLMResponse, ToolCall, ChatOptions
│   │   └── index.ts            # LLMProvider (AI SDK wrapper)
│   ├── session/
│   │   ├── types.ts            # SessionMessage, SessionMeta schemas
│   │   └── manager.ts          # Session persistence (JSONL)
│   ├── cron/
│   │   ├── types.ts            # CronJob, CronSchedule schemas
│   │   └── service.ts          # CronService
│   ├── heartbeat/
│   │   └── service.ts          # HeartbeatService
│   ├── config/
│   │   ├── types.ts            # Zod config schemas
│   │   └── loader.ts           # loadConfig, env overrides
│   └── cli/
│       └── commands.ts         # gateway + agent commands
├── templates/                  # Default workspace files
│   ├── SOUL.md                 # Agent personality
│   ├── USER.md                 # User preferences
│   ├── TOOLS.md                # Tool documentation
│   ├── AGENTS.md               # Agent behavior rules
│   ├── HEARTBEAT.md            # Periodic tasks
│   └── memory/MEMORY.md        # Long-term memory
└── skills/                     # Bundled skills

Data Flow

┌─────────────────────────────────────────────────────────────────┐
│                         Gateway Mode                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Mattermost ──► BaseChannel ──► MessageBus ──► AgentLoop       │
│     ▲                               │                │          │
│     │                               ▼                ▼          │
│     │                         OutboundQueue    LLMProvider      │
│     │                               │                │          │
│     └───────────────────────────────┘                ▼          │
│                                               ToolRegistry      │
│                                                     │          │
│                                                     ▼          │
│                                              Tool.execute()     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                          Agent Mode                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  CLI stdin ──► processDirect() ──► AgentLoop ──► Response      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Key Components

AgentLoop

The core orchestrator. Consumes inbound messages, runs the LLM tool-calling loop, and publishes responses.

  1. Receives InboundMessage from bus
  2. Loads/creates session by key
  3. Builds context (system prompt + history)
  4. Calls LLM with tools
  5. Executes tool calls, appends results
  6. Repeats until no tool calls or max iterations
  7. Saves session, publishes response

MessageBus

An async queue system for decoupling channels from the agent loop.

  • publishInbound() / consumeInbound(): messages from channels to agent
  • publishOutbound() / consumeOutbound(): responses from agent to channels

LLMProvider

Wraps Vercel AI SDK generateText() with:

  • Model string resolution (e.g., openrouter/anthropic/claude-sonnet-4-5)
  • Retry logic (3 attempts, exponential backoff)
  • Malformed JSON repair
  • Normalized LLMResponse type

SessionManager

Persists conversation history to JSONL files in ~/.config/nanobot/sessions/.

  • Key format: {channel}:{chatId} (e.g., mattermost:abc123)
  • Supports history truncation for context window limits

ToolRegistry

Stores tools by name, provides OpenAI-compatible function definitions to the LLM.

MemoryConsolidator

When session history exceeds token limits, summarizes old messages and archives to memory/MEMORY.md.

Configuration

  • File: ~/.config/nanobot/config.json
  • Validation: Zod schemas in src/config/types.ts
  • Env overrides: NANOBOT_MODEL, NANOBOT_WORKSPACE, NANOBOT_CONFIG

Session Key Convention

Channel Key Format Example
Mattermost mattermost:{channelId} mattermost:abc123
Mattermost (thread) mattermost:{channelId}:{rootId} mattermost:abc:def456
CLI cli:{chatId} cli:interactive
System system:{source} system:heartbeat