Skip to content

toolexec Design Notes

Overview

toolexec provides the execution layer for the ApertureStack tool framework. It handles tool execution, code orchestration, and runtime isolation.

Architecture

┌─────────────────────────────────────────────────────────────┐
│                          exec                                │
│              (Unified Facade - Single Entry Point)          │
│  SearchTools, RunTool, RunChain, GetToolDoc                 │
└─────────────────────────┬───────────────────────────────────┘
                          │
          ┌───────────────┼───────────────┐
          v               v               v
    ┌──────────┐   ┌──────────────┐  ┌──────────┐
    │  index   │   │     run      │  │ tooldoc  │
    │(discover)│   │  (execute)   │  │  (docs)  │
    └──────────┘   └──────┬───────┘  └──────────┘
                          │
                          v
                   ┌──────────────┐
                   │   backend    │
                   │  (registry)  │
                   └──────────────┘
                          │
          ┌───────────────┼───────────────┐
          v               v               v
    ┌──────────┐   ┌──────────────┐  ┌──────────┐
    │  local   │   │     mcp      │  │ provider │
    │ handlers │   │   servers    │  │   APIs   │
    └──────────┘   └──────────────┘  └──────────┘

exec Package (Unified Facade)

Design Decisions

  1. Single Entry Point: The exec.Exec type provides a unified API combining discovery (search, describe) with execution (run, chain). Users don't need to understand multiple packages for basic operations.

  2. Options Pattern: Configuration via exec.Options allows:

  3. Custom index and doc store
  4. Local handler registration via map
  5. MCP and provider executors
  6. Input/output validation toggles
  7. Security profile selection

  8. Result Types: Consistent Result and StepResult types wrap lower-level run.RunResult with additional context (toolID, duration, error).

  9. Handler Function: Simple func(ctx, args) (any, error) signature for local tool handlers, avoiding the need to understand backend interfaces.

run Package

Design Decisions

  1. Execution Pipeline: Every tool call follows a strict pipeline:
  2. Validate tool ID format
  3. Validate input against schema
  4. Resolve tool definition from index
  5. Select and invoke backend
  6. Normalize result
  7. Validate output against schema

  8. Backend Abstraction: The runner doesn't care how tools are executed. It delegates to the backend registry which supports local, provider, and MCP server backends.

  9. Result Normalization: All backends return results in a consistent RunResult format with output, error, duration, and metadata.

Error Handling

  • Input validation errors include the failing field and constraint
  • Backend errors are wrapped with context
  • Output validation errors are warnings (logged but not fatal)

code Package

Design Decisions

  1. DSL for Orchestration: Provides a simple DSL for chaining tool calls with variable binding and conditional logic.

  2. Runner Integration: Delegates actual tool execution to the run package, ensuring consistent validation and error handling.

  3. Runtime Integration: Code execution can be isolated by wiring a runtime.Runtime via the runtime/toolcodeengine adapter.

runtime Package

Design Decisions

  1. Runtime Interface: Abstracts sandbox implementations behind a common interface supporting Execute and Cleanup operations.

  2. Security Profiles:

  3. ProfileDev: Unsafe host execution (development only)
  4. ProfileStandard: Container-based isolation
  5. ProfileHardened: Maximum isolation (seccomp + VM/VM-like backends)

  6. Resource Limits: Configurable CPU, memory, and timeout limits for sandboxed execution.

  7. Gateway Requirement: Every execution request must include a ToolGateway to broker tool discovery/execution for sandboxed code.

Supported Runtimes

Runtime Isolation Performance Use Case
Unsafe host None Fast Trusted/dev
Docker Container Medium Production
WASM Sandbox Varies Edge/browser

Runtime Backend Matrix

Readiness tiers: - prod: production-ready - beta: usable, still evolving - stub: placeholder or incomplete

Concrete runtime clients (Kubernetes, Proxmox, remote HTTP) live in toolexec-integrations and are injected into toolexec core backends via interfaces (PodRunner, APIClient, RemoteClient). This keeps the core dependency-light while integrations remain opt-in.

BackendKind Readiness Isolation Requirements Notes
BackendUnsafeHost prod None Go toolchain (subprocess mode) Dev-only, explicit opt-in supported
BackendDocker prod Container Docker daemon + ContainerRunner Standard isolation
BackendContainerd beta Container containerd client Infrastructure-native
BackendKubernetes beta Pod/Job toolexec-integrations/kubernetes + kubeconfig Cluster execution
BackendGVisor beta Sandbox gVisor/runsc (io.containerd.runsc.v1) Stronger isolation
BackendKata beta VM Kata runtime (io.containerd.kata.v2) VM-level isolation
BackendFirecracker beta MicroVM Firecracker runtime (aws.firecracker) Strongest isolation
BackendWASM beta Sandbox wazero In-process WASM
BackendTemporal stub Workflow Temporal client Orchestrated execution
BackendRemote beta Remote toolexec-integrations/remotehttp External runtime with signed requests
BackendProxmoxLXC beta Container toolexec-integrations/proxmox + runtime client LXC-backed runtime service

Toolcode ↔ Runtime Contract

The code package uses the runtime/toolcodeengine adapter to bridge code execution with runtime backends. The adapter maps code.ExecuteParams to runtime.ExecuteRequest, preserving:

  • Security profile selection
  • Resource limits (timeouts, tool-call/chain limits)
  • ToolGateway injection for tool discovery/execution

backend Package

Design Decisions

  1. Backend Registry: Central registry for all backend implementations, enabling runtime backend selection.

  2. Backend Kinds:

  3. local: In-process Go function
  4. provider: External tool provider via HTTP/gRPC
  5. mcp: Remote MCP server via JSON-RPC

  6. Lazy Resolution: Backends are resolved at execution time, allowing dynamic registration and configuration.

Dependencies

  • github.com/jonwraymond/toolfoundation/model - Tool definitions
  • github.com/jonwraymond/tooldiscovery/index - Tool resolution
  • github.com/tetratelabs/wazero - WASM runtime (optional)