Signature
← Back to Overview

MAXIM

Communication & Safety

Reaching the Outside World and Handling Interrupts

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.

Communication Bridge

The CommunicationBridge connects external messaging to the reward system, enabling Maxim to learn from communication outcomes:

Communication → Learning Loop Agent sends message → User responds positively → Inbound Percept │ │ ↓ ↓ CommunicationBridge NAc reward attribution │ │ ↓ ↓ Record outcome: "messaging user about X → positive" Learn: future similar situations → communicate

The bridge subscribes to the AgentBus and watches for communication-related ToolResults and subsequent user responses. Over time, the NAc learns which communication patterns lead to positive outcomes, making the agent progressively better at deciding when and how to reach out.

As a PromotionSource, the bridge can also contribute candidates to the SemanticPromoter — communication patterns that repeat enough become ATL concepts ("user prefers brief updates" or "morning messages get faster responses").