Skip to main content
  1. Documentation/

Platform Architecture

3 mins
Table of Contents

Core vs Platform
#

Carpenter separates platform-agnostic logic from platform-specific implementations:

  • Core (carpenter-ai) — Arc management, review pipeline, trust system, agent loop, model selection, skills, memory
  • Platform packages (carpenter-linux, carpenter-android, etc.) — Executors, sandbox backends, network egress enforcement, platform-specific tools

Platform packages are thin. They register their implementations at startup, then hand off to the core:

from carpenter import (
    set_platform, register_executor,
    set_sandbox_provider, add_tool_dir
)

set_platform(LinuxPlatform())
register_executor("subprocess", SubprocessExecutor())
set_sandbox_provider(LinuxSandboxProvider())
add_tool_dir("/path/to/platform/tools")

This means the core never imports platform-specific code. New platforms (Android, Windows, macOS) are independent packages that plug into the same core.

Executor Backends
#

Code execution is handled by pluggable executor backends:

TypeIsolation level
Subprocess (basic)Same-user, env isolation, close_fds, RLIMIT_AS
Subprocess (standard)Different-UID, RLIMIT_AS, optional Landlock
Docker (single)Platform + executor in one container
Docker (orchestrator)Separate containers

The platform detects available sandbox methods and falls back gracefully. All subprocess executors enforce a configurable virtual memory limit (default 300MB) via RLIMIT_AS.

Tool System
#

Tools are partitioned by safety:

carpenter_tools/
  read/   — safe, direct agentic access
  act/    — requires reviewed code

The @tool() decorator declares safety properties: local, readonly, side_effects, trusted_output. A validation function enforces that read/ tools are all safe and act/ tools have at least one unsafe property.

The trusted_output=False declaration (currently only on the web tool) feeds into the taint tracking system — output from untrusted tools is never returned directly to the chat agent.

Model Selection
#

A YAML models manifest declares available models with metadata:

  • provider — Anthropic, Ollama
  • model_id — full model identifier
  • cost_tier — low / medium / high
  • context_window — token limit
  • roles — which task types the model suits

Arc creation accepts a short name (e.g., "opus") that resolves to the full provider:model_id. Templates can specify model_min_tier per step — security review steps require high tier, preventing cost optimization from undermining review quality.

Presets
#

Four built-in presets route requests to appropriate models:

PresetUse case
fast-chatQuick conversational responses
careful-codingThorough code generation and review
background-batchCost-optimized batch processing
caretakerSystem monitoring and maintenance

Resilience
#

Both AI clients use exponential backoff with jitter for transient failures and a per-provider circuit breaker that fast-fails after consecutive errors. The circuit breaker transitions through CLOSED → OPEN → HALF_OPEN states. HTTP 429 responses are handled by the rate limiter (natural cooldown via sliding window) rather than the circuit breaker.

Configuration
#

All settings via config.yaml or environment variables. Three-layer precedence:

env vars > credential files > YAML > built-in defaults

No hardcoded credentials in the package. The platform process holds all secrets and exposes them to executors only through the callback RPC layer.