goClaw/Documentation

Architecture

Permission System

Group-level isolation, sandbox execution, mount allowlists, and container mode.

goClaw's permission system lets you control exactly what each agent sees, touches, and does. It's built on two concepts: groups (logical isolation) and sandbox (technical enforcement).

Groups

A group is a named configuration set that scopes an agent context. Every agent execution runs within a group. Groups control:

  • Which knowledge files the agent can read
  • Which MCP tools the agent can call
  • Which CRM contacts the agent can see (filtered by group tag)
  • The technical sandbox level (process vs. container)

Group configuration

Groups are defined in config/permissions.yaml:

groups:
  outbound_sales:
    description: "SDR agent — outbound prospecting"
    knowledge_mounts:
      - ./knowledge/public         # Company-wide knowledge
      - ./knowledge/products       # Product knowledge
      - ./knowledge/objections     # Objection handling
    tool_allowlist:
      - crm_search
      - crm_get_contact
      - crm_create_contact
      - crm_add_note
      - crm_schedule_followup
      - knowledge_search
      - knowledge_file_curiosity
      - web_search
      - send_email
      - send_sms
    sandbox:
      filesystem: read_only
      network: allow
      container: false

  customer_support:
    description: "Support agent — inbound only"
    knowledge_mounts:
      - ./knowledge/public
      - ./knowledge/products
      - ./knowledge/support        # Support-specific guides
    tool_allowlist:
      - crm_search
      - crm_get_contact
      - crm_update_contact
      - crm_add_note
      - knowledge_search
      - knowledge_file_curiosity
      - send_email
      - send_telegram
    sandbox:
      filesystem: read_only
      network: allow
      container: false

  admin:
    description: "Human admin access — full permissions"
    knowledge_mounts:
      - ./knowledge                # All knowledge
    tool_allowlist: "*"           # All tools
    sandbox:
      filesystem: read_write
      network: allow
      container: false

Group assignment

Messages are assigned to groups based on channel routing rules:

routing:
  email:
    domain_rules:
      - pattern: "*@yourcompany.com"
        group: admin
      - pattern: "*"
        group: outbound_sales
  telegram:
    group: customer_support
  sms:
    group: outbound_sales

You can also assign a group directly when triggering agent execution via the API or admin dashboard.

Knowledge mounts

Knowledge mounts are directory paths the agent is allowed to read. Paths outside the mount list are inaccessible — the knowledge_search and knowledge_get tools enforce this at query time.

knowledge_mounts:
  - ./knowledge/public       # Readable
  - ./knowledge/products     # Readable
  # ./knowledge/internal     # Not listed → inaccessible

Relative paths are resolved from the project root. Absolute paths are supported.

Tool allowlist

The tool_allowlist is an array of MCP tool names the agent can call. Any call to a tool not in the allowlist is rejected with an error logged to the audit trail.

tool_allowlist:
  - crm_search
  - crm_get_contact
  - send_email

Use "*" to allow all tools (human admin only — not recommended for agent groups).

CRM scoping

Contacts are tagged with their originating group. The CRM tools automatically filter results to the current group context:

// Agent in "outbound_sales" group
await mcp.tool("crm_search", { query: "acme" });
// → Returns only contacts with group_id: "outbound_sales"

This means your outbound sales agent and customer support agent see different contact sets, even though they share the same CRM database. Contacts can be transferred between groups via the admin dashboard.

Sandbox modes

Process isolation (default)

Each agent execution runs in a Node.js worker thread with:

  • Read-only access to allowed knowledge paths (enforced by knowledge module)
  • Tool allowlist enforcement (enforced by MCP router)
  • No direct database access (all CRM operations go through MCP tools)
  • Shared process memory (not fully isolated from the main process)

This mode is appropriate for trusted agent configurations with minimal risk.

Container isolation

When sandbox.container: true is set, agent execution moves into a Docker container:

groups:
  untrusted_agent:
    sandbox:
      filesystem: read_only
      network:
        allow:
          - "api.anthropic.com"
          - "api.openai.com"
          - "api.resend.com"
        deny: "*"
      container: true
      container_config:
        image: "goclaw/agent-sandbox:latest"
        memory_limit: "512m"
        cpu_limit: 1.0
        user: "1000:1000"   # Non-root

Container mode enforces:

  • Strict filesystem isolation — only mounted knowledge directories visible
  • Network allowlist via iptables rules in the container
  • Non-root execution (UID 1000)
  • Memory and CPU limits
  • No access to host credentials (only required tokens passed via environment at launch time)

Container mode is recommended for:

  • Multi-tenant deployments where different tenants run different agents
  • Agents with access to sensitive external APIs
  • Deployments where agent code changes frequently

Audit logging

All agent actions are logged to the audit trail regardless of group:

interface AuditEntry {
  id: string;
  timestamp: number;
  group_id: string;
  agent_id: string;
  action: string;           // "tool_call" | "message_sent" | "contact_created" | etc.
  tool_name: string | null;
  tool_input: unknown;
  tool_result: unknown;
  contact_id: string | null;
  duration_ms: number;
  success: boolean;
  error: string | null;
}

The admin dashboard shows the audit log per group with filtering by tool, contact, and time range. Audit entries are retained for 90 days.