{% extends "base.html" %} {% block title %}Communication & Safety — Maxim Docs | Agentic Robotics{% endblock %} {% block meta_description %}How Maxim reaches the outside world and handles interrupts. Communication Gateway, Preemption Circuit, and mode-based filesystem containment.{% endblock %} {% block meta_keywords %}Maxim communication, communication gateway, preemption circuit, execution tracking, agent safety, mode containment, filesystem policy, Twilio integration, interrupt handling{% endblock %} {% block meta_author %}Maxim Project{% endblock %} {% block og_site_name %}Maxim{% endblock %} {% block og_type %}article{% endblock %} {% block structured_data %}
{% endblock %} {% block content %}
← Back to Overview

An agent that can only talk to itself isn't very useful. Maxim's agentic upgrade adds three critical capabilities: external communication channels, interrupt handling for when humans need to override decisions, and mode-based containment that scales access with trust.

## Communication Gateway

The gateway is a pure transport layer. It delivers messages when the agent tells it to and receives inbound messages into the bus. It has no opinion about when to notify or what to notify about — that's the agent's job.

Message Flow Outbound (agent → user) Agent decides to send → send_message tool → Gateway → Channel → User Inbound (user → agent) User texts/calls in → Channel → Gateway → Percept on bus → Agent The gateway is a dumb pipe. The agent is the brain.

### Channel Architecture

Channels are pluggable transport adapters. Each channel handles a specific communication medium:

#### Twilio Channel

SMS + Voice via REST API. Outbound messages are immediate API calls. Inbound messages arrive via webhook.

- send(recipient, body) → Twilio Messages API
- call(recipient, message) → TwiML voice synthesis
- Inbound webhook → gateway.receive_inbound()

#### Future Channels

The channel interface is intentionally minimal. Adding new channels requires implementing just send() and optionally call().

- Email (SMTP/IMAP)
- Slack / Discord webhooks
- WebSocket for web interfaces

### Security: Hardened Inbound Path

External messages are untrusted input. The gateway enforces strict separation between external data and internal control fields:

Inbound Percept Construction percept = Percept( source = "comms:twilio" # Set by gateway (not external) content = text # External text (only user data) salience = 0.9 # FIXED — not from external data hard_override = None # Only set if text matches HARD_STOP whitelist metadata = {channel, sender} # Informational only ) External data NEVER controls: salience, hard_override, novelty, interests hard_override is only str|None from HARD_STOP_TRIGGERS whitelist

### Agent Tools

Two tools give the agent control over outbound communication:

Tool | Parameters | Effect
--- | --- | ---
send_message | channel, recipient, body | Calls gateway.send() → delivers via channel adapter
call_user | recipient, message | Calls gateway.call() → initiates voice call with TTS

Both tools are registered in the tool registry during bootstrap and are subject to mode-based access gating. The agent decides when and what to communicate based on its reasoning — the gateway just delivers.

## Preemption Circuit

### Biological Inspiration

Biological agents can be interrupted. When something more urgent appears (a loud noise, a sudden threat), the current action is suspended and attention shifts. The prefrontal cortex mediates this via inhibitory control — the ability to stop an ongoing behavior. Maxim's preemption circuit provides the same capability: external signals (voice commands, inbound messages, hard stops) can interrupt the current goal.

The PreemptionCircuit evaluates incoming Percepts for urgency and can pause, redirect, or abort the current goal. It operates on a priority system:

#### HARD_STOP (immediate)

Unconditional halt. Triggered by voice commands ("Maxim stop"), inbound messages matching the hard-stop whitelist, or safety circuit triggers. Cancels current goal, freezes motor output.

#### REDIRECT (high priority)

Suspend current goal and switch to a higher-priority one. Triggered by urgent user input or significant environmental changes. Current goal is preserved for potential resumption.

#### HOLD (tonic inhibition)

Pause goal execution for a duration. The agentic loop continues cycling but skips goal proposals while the hold is active. Used during mode transitions or when waiting for external input.

### Integration with the Agent Loop

The preemption check happens early in each agent loop cycle, before goal proposals:

Agent Loop (simplified) while running: # 0. Stop checks (max steps, stop event) # 0.5 Preemption hold check — skip cycle if holding if agent.goal.check_hold(): continue # 1. Perception / observation # 2. LLM proposals (if needed) # 3. Intent path (propose_intent → tool execution) # 4. LLM action execution (autonomy-gated)

## Execution Tracking

When the preemption circuit interrupts an action mid-execution, the system needs to know what was happening so it can either reverse it or resume it later. The ExecutionTracker captures pre-execution snapshots:

Execution Snapshot capture_before( goal_description = "Navigate to kitchen" tool_name = "move" tool_params = {yaw: 30, pitch: -10, duration: 1.0} robot = <RobotController reference> ) # If preemption occurs, the snapshot enables: # - Reversal: undo the motor command (move back) # - Logging: what was interrupted and why # - Resumption: retry the same action after hold expires

Execution tracking is wired into the agent loop's LLM action execution path (Section 4). Before each tool call, a snapshot is captured. If the preemption circuit fires mid-execution, the snapshot provides the context needed for graceful handling.

## Mode-Based Containment

Trust scales with experience. A new agent shouldn't have filesystem root access. Maxim's tool registry enforces mode-based containment that limits capabilities based on the current operational mode:

Mode | Filesystem Access | Directory Change | Tool Gating
--- | --- | --- | ---
passive | Restricted to .maxim_sandbox/ within CWD | Blocked | Read-only + network
active | Read/write within CWD | Can request | Full sandbox, execution requires approval
singularity | Full filesystem access | Unrestricted | All tools, constitution still applies

Every filesystem tool (ReadFileTool, WriteFileTool, ExecuteFileTool, GlobTool, BashTool) receives an allowed_dirs parameter at construction time, enforced on every call. The sandbox is created automatically in passive/active modes.

## Conversation Memory

Communication isn't just delivered — it's remembered. The ConversationManager tracks per-channel, per-participant exchanges and, when a conversation expires, archives it into Maxim's memory systems so the agent can learn from how it talks to people:

Conversation → Memory Loop Inbound / outbound messages → ConversationManager (per channel + participant) │ ↓ on expiry / cleanup _archive(conversation) ┌───────────┴───────────┐ ↓ ↓ Hippocampus (episodic) NAc conversation event summary Percept on bus (3+ messages → record_event) │ │ ↓ ↓ ATL via SemanticPromoter at session-end consolidation

Each archived conversation publishes a summary Percept onto the agent bus (captured by the Hippocampus as an episodic memory) and, once it has at least three messages, records a conversation-level event in the NAc. Over time the NAc accumulates which channels and patterns matter.

Patterns that repeat enough are promoted to the SemanticPromoter during session-end consolidation, becoming ATL concepts ("user prefers brief updates" or "morning messages get faster responses").

Note: a dedicated `CommunicationBridge` abstraction described in earlier drafts is not part of the 1.0 surface — conversation learning flows through the `ConversationManager` archival path above.

← Previous Body Awareness Next → Usage Guide

### All Chapters

Overview The Agent Brain Memory Systems Math & Statistics Attention & Salience Body Awareness Communication Usage Guide Technical Deep Dive Operating Modes Networking & Mesh Roadmap
{% include "_maxim_footer.html" %}
{% endblock %}