Skip to main content

Documentation Index

Fetch the complete documentation index at: https://qwibitai-nanoclaw-8-mintlify-container-config-db-1778347658.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

In v2, NanoClaw uses a new entity model that separates agent groups (workspaces) from messaging groups (platform chats). These are connected through wirings — many-to-many relationships stored in messaging_group_agents.

Entity model

Agent groups

Agent groups are workspaces where agents run:
interface AgentGroup {
  id: string;             // Unique identifier
  name: string;           // Display name
  folder: string;         // Filesystem folder name
  agent_provider?: string; // Optional provider override
  created_at: string;     // ISO timestamp
}
  • Each agent group has a folder under groups/{folder}/
  • Container runtime configuration lives in the container_configs table; groups/{folder}/container.json is a read-only materialized view written at spawn time
  • Each gets its own OneCLI agent identifier for credential scoping

Messaging groups

Messaging groups represent platform chats and channels:
interface MessagingGroup {
  id: string;                    // Unique identifier
  channel_type: string;          // e.g., 'whatsapp', 'telegram', 'discord'
  platform_id: string;           // Platform-specific chat ID
  name?: string;                 // Display name
  unknown_sender_policy: UnknownSenderPolicy; // 'strict' | 'request_approval' | 'public'
  denied_at?: string;            // ISO timestamp if denied
}
  • Unique on (channel_type, platform_id)
  • Auto-created on first mention or DM
  • denied_at silently drops future mentions

Wirings (messaging_group_agents)

Wirings connect messaging groups to agent groups:
interface MessagingGroupAgent {
  messaging_group_id: string;
  agent_group_id: string;
  engage_mode: EngageMode;           // 'pattern' | 'mention' | 'mention-sticky'
  engage_pattern: string;            // Regex (e.g., '.' = always match)
  sender_scope: SenderScope;         // 'all' | 'known'
  ignored_message_policy: IgnoredMessagePolicy; // 'drop' | 'accumulate'
  session_mode: SessionMode;         // 'shared' | 'per-thread' | 'agent-shared'
  priority: number;                  // Evaluation order
}

Users and roles

Users

interface User {
  id: string;          // Namespaced: 'channelType:handle'
  kind: string;        // phone, email, discord, telegram, matrix, etc.
  created_at: string;
}

User roles

interface UserRole {
  user_id: string;
  role: 'owner' | 'admin';
  agent_group_id?: string;  // null = global scope
}
  • Owner — always global, full system access
  • Admin — global or scoped to a specific agent group

Agent group members

interface AgentGroupMember {
  user_id: string;
  agent_group_id: string;
}
Members can interact with agents in their assigned group when sender_scope='known' is set on a wiring.

Sessions

interface Session {
  id: string;
  agent_group_id: string;
  messaging_group_id?: string;
  thread_id?: string;
  status: 'active' | 'closed';
  container_status: 'running' | 'idle' | 'stopped';
  last_active: string;
  created_at: string;
}
Session resolution depends on the wiring’s session_mode:
ModeResolution
sharedOne session per messaging group (ignores thread)
per-threadOne session per (messaging group, thread) pair
agent-sharedOne session per agent group (all messaging groups share)

Database schema

Central database (data/v2.db)

TablePurpose
agent_groupsAgent workspaces
container_configsPer-agent-group container runtime config (provider, model, packages, MCP servers, mounts, cli_scope)
messaging_groupsPlatform chats/channels
messaging_group_agentsWirings with engage/scope/session config
usersNamespaced platform identifiers
user_rolesOwner and admin roles
agent_group_membersUnprivileged membership
user_dmsCached DM channel mapping
sessionsSession status and container tracking
pending_questionsInteractive question cards
pending_sender_approvalsUnknown sender approval flow

Session databases

Each session has two databases in data/v2-sessions/{agent_group_id}/{session_id}/: inbound.db (host writes):
TablePurpose
messages_inInbound messages, tasks, system notifications
deliveredDelivery tracking
destinationsLive destination map
session_routingDefault reply routing
outbound.db (container writes):
TablePurpose
messages_outOutbound messages
processing_ackProcessing acknowledgments
session_statePersistent key/value store
container_stateTool-in-flight tracking

Channel approval flow

When a message arrives on an unwired channel:
  1. Router detects no wirings exist for this messaging group
  2. Channel-request gate sends approval card to the owner
  3. Approve — creates wiring with defaults:
    • Groups: mention-sticky engage mode
    • DMs: pattern='.' (always respond)
    • Triggering sender is auto-admitted as a member
    • Original event is replayed
  4. Deny — sets denied_at on the messaging group

Sender approval flow

When an unknown sender messages on a request_approval channel:
  1. Approval card sent to the designated approver
  2. Approve — adds sender to agent_group_members, replays original message
  3. Deny — deletes pending row (future messages re-trigger)

Container config operations

In addition to the standard CRUD verbs, the groups resource exposes custom operations for managing the per-group container config and lifecycle:
OperationPurpose
ncl groups restartKill and respawn containers for the group. Accepts --rebuild to rebuild the per-group image and --message <text> to write a wake message that is delivered only to the fresh container’s first poll iteration.
ncl groups config getRead the materialized container config for a group.
ncl groups config updatePatch scalar fields on the container_configs row (e.g., --model, --effort, --cli-scope).
ncl groups config add-mcp-server / remove-mcp-serverWire or remove an MCP server entry.
ncl groups config add-package / remove-packageAdd or remove an apt or npm package.
Config writes do not restart the container — call ncl groups restart (with --rebuild if package lists changed) to apply changes. From inside a container, --id is auto-filled to the calling group, and restart only kills the calling session. The host enforces the cli_scope field on every cli_request: under group scope (the default) only groups, sessions, destinations, and members are reachable, group-related arguments are auto-filled, and changing cli_scope itself is blocked.
Last modified on May 9, 2026