Matrix logo

Tool Surface

Package matrix/neo/internal/tools is Neo's tool surface. It reuses the executor's MCP manager, classifies tools as Natural or Escalate, dispatches calls, and manages synthetic tools including core_execute, memory_recall, spawn_subagents, write_skill, todo, and workspace_preview.

Package matrix/neo/internal/tools is Neo's tool surface. It reuses the executor's MCP manager + tool registry (so Neo's tools are byte-identical to the daemon's: fs, web_search, browser, git, shell, fetch, ...), advertises each tool's real JSON schema to the model as a function, and dispatches calls.

Source files: neo/internal/tools/tools.go, neo/internal/tools/surface.go.


Design decisions

Execution-surface split. Reversible actions stay "Natural" (Neo performs them directly, fully permissive). Actions that move or commit the user's on-chain funds, or need a wallet signature, "Escalate" across the wall into the MCL pipeline. Neo holds no signing key, so escalate-class tools are never advertised as directly-callable functions.

Default escalate patterns are empty. With MCL folded into Neo, the interactive agent carries the full tool surface directly. Every manifest tool is Natural and directly callable; nothing is walled behind core_execute. Spend policy is enforced network-side on the embedded wallet (PaxeerSpendPolicy / PAXEER_MAX_SPEND_WEI), not by withholding tools. The autonomous (Automatrix/sub-agent) surface keeps its own explicit money-tool guard.

Six synthetic tools. core_execute (MCL delegation), memory_recall (cortex search), spawn_subagents (concurrent sub-agents), write_skill (conscious pattern authoring), todo (live task checklist), and workspace_preview (workbench preview). None are real MCP servers; they never enter the manifest tool-bijection check.

Graceful degradation. An MCP server that fails to start is recorded as a warning and skipped; Neo degrades rather than refusing to boot.


Surface classification

type Surface int

const (
    Natural  Surface = iota  // reversible, no wallet signature
    Escalate                 // moves/commits funds or needs signature
)
type Classifier struct {
    patterns []string
}

func (c *Classifier) Classify(toolName, sideEffect string) Surface

Default escalate patterns (DefaultEscalatePatterns) are currently empty. When non-empty, classification is a case-insensitive substring match on the tool name. The autonomous surface uses ValueTransferPatterns for its own explicit money-tool guard.


Manager

type Manager struct {
    manifest   *tool.AgentManifest
    mcp        *mcp.Manager
    registry   *tool.Registry
    classifier *Classifier
    delegate   DelegateFunc    // core_execute bridge
    recall     RecallFunc      // memory_recall bridge
    swarm      SwarmFunc       // spawn_subagents bridge
    byFunc     map[string]*boundTool
    order      []string        // natural tool names (advertised)
    escalated  []string        // escalate tool names (hidden)
    warnings   []string        // non-fatal spawn failures
}

Spawn

func Spawn(ctx context.Context, opts Options) (*Manager, error)
  1. Load the agent manifest (agents/default.json)
  2. Start every declared MCP server (with timeout, env resolution)
  3. Build the tool registry from live MCP schemas
  4. Classify each tool as Natural or Escalate
  5. Bind function names

A server that fails to start is logged as a warning and skipped. The remaining tools are still available.

Schemas

func (m *Manager) Schemas() []llm.Tool

Returns the function schemas advertised to the model:

  • Every Natural tool (sorted, deterministic order)
  • The synthetic core_execute tool (when delegate is wired)
  • The synthetic memory_recall tool (when recall is wired)
  • The synthetic spawn_subagents tool (when swarm is wired)
  • The synthetic write_skill tool
  • The synthetic todo tool (when todo emitter is wired)
  • The synthetic workspace_preview tool (when preview launcher is wired)

Escalate-class tools are NOT included; they are reachable only via core_execute.

Dispatch

func (m *Manager) Dispatch(ctx context.Context, funcName string, args map[string]interface{}) (string, bool, error)

Returns (content, isError, err):

  • err != nil then transport/invocation failure (feeds recovery ladder: retry/adapt)
  • isError=true, err=nil then in-band failure the model should see and adapt to
  • Both empty then the tool ran successfully

Special handling:

  • core_execute then delegates to DelegateFunc
  • memory_recall then delegates to RecallFunc
  • spawn_subagents then delegates to SwarmFunc
  • write_skill then validates and writes PatternSpec to cortex
  • todo then records items via TodoFunc
  • workspace_preview then launches sandbox via PreviewFunc
  • Unknown name then "unknown tool %q, it is not available", isError=true
  • Escalate-class tool called directly then "%q moves funds... use core_execute", isError=true

Synthetic tools

core_execute

const CoreExecuteTool = "core_execute"

Delegates a rigorous or money-moving task to Matrix's secure execution pipeline. The intent argument is a prose description passed to the MCL daemon's async API.

{
  "name": "core_execute",
  "description": "Delegate a rigorous or money-moving task to Matrix's secure execution pipeline...",
  "parameters": {
    "type": "object",
    "properties": {
      "intent": {
        "type": "string",
        "description": "A clear, self-contained description of the task..."
      }
    },
    "required": ["intent"]
  }
}

memory_recall

const MemoryRecallTool = "memory_recall"

Searches the durable cortex store. The PRIMARY reasoning-time retrieval verb: the model calls it iteratively with a narrowing query, an optional type filter, a result cap, and an optional bi-temporal as-of instant.

{
  "name": "memory_recall",
  "description": "Search your own durable memory (the cortex) for what you know...",
  "parameters": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "What to look for..." },
      "types": { "type": "array", "items": { "type": "string" }, "description": "Memory type filter..." },
      "k": { "type": "integer", "description": "Max results..." },
      "as_of": { "type": "string", "description": "ISO-8601 instant for bi-temporal lookup..." }
    }
  }
}

spawn_subagents

const SpawnSubagentsTool = "spawn_subagents"

Fans a task out to several task-scoped sub-agents that run concurrently, each in its own isolated context window with the restricted tool surface (full Natural, no money, no recursion). Heavy tool work stays in the sub-agents' windows; only a compact result returns to the parent's. Reachable only from the top-level agent; sub-agents do NOT get this tool (no recursion / fork-bombs).

{
  "name": "spawn_subagents",
  "description": "Run multiple task-scoped sub-agents concurrently...",
  "parameters": {
    "type": "object",
    "properties": {
      "agents": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "persona": { "type": "string" },
            "task": { "type": "string" }
          },
          "required": ["name", "task"]
        }
      }
    },
    "required": ["agents"]
  }
}

write_skill

const WriteSkillTool = "write_skill"

The agent consciously persists a reusable recipe as a cortex Pattern. After a proven task, the agent authors a structured PatternSpec (name, trigger, preconditions, steps, gotchas, success_criteria) and this tool validates it and writes it to the durable procedural store. Coverage starts low and is reinforced on each repeat success.

todo

const TodoTool = "todo"

Maintains a short, ordered task plan with per-item status, surfaced to the user as a live checklist that ticks off in real time. Exactly one item may be in_progress at a time. Advertised only to the top-level agent and only when a todo emitter is wired.

workspace_preview

const PreviewTool = "workspace_preview"

Launches the workbench preview: provisions the active project's on-demand sandbox and the result surfaces in the Preview pane. Advertised only when a preview launcher is wired.


Function naming

Tools are advertised as alias__name (e.g. fs__read_file, paxeer-net__get_balance). The sanitizeFuncName function coerces into the OpenAI function name charset (^[A-Za-z0-9_-]{1,64}$), replacing illegal chars with _ and truncating to 64 chars.


Restricting tools for sub-agents

When Options.RestrictTools is set, the manager advertises the sub-agent tool surface: the full Natural set minus core_execute, memory_recall, and spawn_subagents. An advertised map on the agent enforces the boundary; dispatch rejects any name outside it.


Modifying the tool surface

What to changeWhere
Escalate patternstools/surface.go - DefaultEscalatePatterns
core_execute schematools/tools.go - coreExecuteSchema()
memory_recall schematools/tools.go - memoryRecallSchema()
spawn_subagents schematools/tools.go - spawnSubagentsSchema()
write_skill schematools/tools.go - writeSkillSchema()
todo schematools/tools.go - todoSchema()
Function namingtools/tools.go - funcName(), sanitizeFuncName()
Spawn timeouttools/tools.go - Options.SpawnTimeout
Agent manifest pathconfig/config.go - ManifestPath
Sub-agent tool restrictiontools/tools.go - Options.RestrictTools