Architecture¶
System Overview¶
MiQi follows a message bus + agent loop + tool system + channel adapters architecture:
- Channels receive external messages and publish them to
MessageBus.inbound(Feishu is wired in the packaged gateway today; other adapter modules are extension points in the repository) - AgentLoop consumes messages, builds context (session + memory + skills), and calls the LLM
- External capabilities are executed through ToolRegistry, either sequentially or concurrently for safe batches
- Responses are published to
MessageBus.outboundand delivered back by channels
┌─────────────────────────────────────────────────────────┐
│ Channel Adapters (Feishu / Telegram / Discord / ...) │
└─────────────────┬───────────────────────────────────────┘
│ InboundMessage
▼
┌─────────────────────────────────────────────────────────┐
│ MessageBus (inbound queue / outbound queue) │
└─────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ AgentLoop │
│ ├── ContextBuilder (session + memory + skills) │
│ ├── LLM Provider (OpenAI / Anthropic / ...) │
│ └── ToolRegistry (filesystem / shell / web / MCP) │
└─────────────────────────────────────────────────────────┘
Core Modules¶
| Module | File | Responsibility |
|---|---|---|
| Agent loop | agent/loop.py |
Main loop, tool-call orchestration, MCP lifecycle |
| Context builder | agent/context.py |
Context assembly: session, memory, skills |
| Runtime controls | agent/context_compressor.py, agent/iteration_budget.py, agent/smart_routing.py |
Optional compression/routing hooks plus iteration-pressure safeguards |
| Command approval helper | agent/command_approval.py |
Interactive dangerous-command approval helper for embedded runtimes |
| Memory store | agent/memory/store.py |
MemoryStore facade over all memory sub-systems |
| Snapshot memory | agent/memory/snapshot.py |
Long-term RAM-first snapshot with disk checkpoints |
| Lessons | agent/memory/lessons.py |
Self-improvement lesson extraction and storage |
| NLP helpers | agent/memory/nlp.py |
Text normalization and relevance scoring |
| LLM providers | providers/ |
Multi-provider adapters unified under a single interface |
| Provider fallback helper | providers/fallback.py |
Retry/fallback chain helper for advanced embeddings |
| Channel adapters | channels/ |
IM and messaging platform adapters |
| Tool registry | agent/tools/registry.py |
Tool registration, discovery, and dispatch |
| Built-in tools | agent/tools/ |
filesystem, shell, web, papers, cron, spawn, message |
| Cron service | cron/service.py |
Scheduled task execution engine |
| Session manager | session/manager.py |
Default JSONL session persistence and compaction |
| SQLite session backend | session/sqlite_store.py |
Optional SQLite+FTS5 backend module shipped in the repository |
| CLI | cli/ |
Entry point and subcommand modules |
Data Flow¶
Input: Channel adapter → InboundMessage (with sender identity, channel metadata)
↓
Process: AgentLoop.process_*
├── ContextBuilder assembles: session history + memory items + lessons + skill files
├── LLM Provider generates response (streaming or blocking)
└── If tool calls: ToolRegistry dispatches (sequentially or concurrently) → tool executes → result fed back
↓
Output: OutboundMessage → Channel adapter delivers to user
↓
Memory: MemoryStore.record_turn updates short-term ring buffer and long-term snapshot
Key Design Principles¶
- Workspace-local runtime data: memory and session files live under
agents.defaults.workspaceby default (~/.miqi/workspace/), not the config root itself. - RAM-first memory: runtime operates entirely from in-memory structures; disk writes happen only at checkpoint events. See Memory System.
- Tool registry: decouples tool definitions (schema), validation, and execution; MCP tools and built-in tools share the same dispatch interface.
- Safe concurrency:
ToolRegistryparallelizes read-only or path-disjoint batches to reduce round-trip latency without reordering stateful tools. - Provider abstraction: all LLM providers implement a unified
BaseProviderinterface; the agent loop callsprovider.chat(messages, tools)without knowing which backend is in use. - Iteration pressure control:
IterationBudgetinjects hints as the loop nearsmaxToolIterations, reducing runaway tool cycles. - Session storage:
SessionManagerrewrites JSONL session files periodically to keep context size bounded while preserving readable history. The repository also ships an optional SQLite+FTS5 backend module, but the packaged CLI/gateway path still instantiates JSONL sessions. - Embedded advanced helpers: smart model routing, provider fallback, command approval, and context compression are present as runtime modules; only the always-safe pieces are active in the packaged CLI/gateway defaults today.
Group Chat Message Filtering¶
Feishu (and other group-capable channels) supports @mention filtering:
- When
channels.feishu.requireMentionInGroupsistrue(default), group chat messages are only forwarded to the agent if the bot is explicitly @mentioned. - Private (p2p) chats always pass through.
- The @mention placeholder is stripped from the message text before it reaches the agent.
Task Queue and User Notifications¶
AgentLoop processes messages serially. When busy, new messages enter a pending queue managed by TaskTracker:
- Senders receive a queue position notification (e.g. "You are #2 in queue").
- When a task starts, the sender is notified.
- CLI and system messages bypass the queue.
- Controlled by
channels.sendQueueNotificationsconfig (defaulttrue).
MCP Tool Progress Reporting¶
Long-running MCP tool calls support two kinds of progress feedback:
- SDK progress — if the MCP server sends progress events, they are forwarded to the user as percentage updates.
- Heartbeat —
MCPToolWrapperstarts a background timer that sends elapsed-time messages everyprogressIntervalSeconds(default 15s), independent of the MCP server. The heartbeat is cancelled when the tool returns.
CLI Architecture¶
| File | Role |
|---|---|
cli/commands.py |
Entry point and compatibility exports |
cli/onboard.py |
Onboarding command |
cli/agent_cmd.py |
miqi agent command |
cli/gateway_cmd.py |
miqi gateway command |
cli/management.py |
channels / memory / session / cron / status / provider commands |
cli/config_cmd.py |
miqi config subcommands |