This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
scape-agents is a Haskell library and microVM agent for the Scape agentic execution platform. It contains shared protocol types (used by both orchestrator and agent), the agent binary that runs inside Firecracker microVMs, and NixOS modules for building VM templates.
Enter the dev shell first (provides GHC 9.10, cabal, nats-server, HLS):
nix developThen:
cabal build all # Build everything
cabal test all # Run all tests
cabal test scape-agents-test -- --match "Protocol" # Run tests matching a pattern
cabal test scape-agents-test -- --match "Integration" # Integration tests (starts a NATS server)Nix-level commands:
nix build .#scape-agents # Build the package via nix
nix flake check # Full nix evaluation checkShared types serialized as JSON between orchestrator and agent. Two main message directions:
- Command (
Command.hs): Orchestrator -> Agent. Sum type:CmdExec,CmdWriteFile,CmdReadFile,CmdSecrets,CmdCancel,CmdPing. - Observation (
Observation.hs): Agent -> Orchestrator. Sum type:ObsReady,ObsOutput,ObsComplete,ObsError,ObsPong.
Supporting types: Types.hs (newtypes for SessionId, CommandId, etc.), MMDS.hs (Firecracker metadata config), Transport.hs (length-prefixed JSON framing), AISDK.hs (OpenAI/Vercel compatibility).
The agent runs inside a Firecracker microVM. Boot sequence (in app/Agent.hs):
- Fetch config from Firecracker MMDS (
http://169.254.169.254/scape) — provides instance ID, NATS URL, credentials - Connect to NATS for command/observation messaging
- Start HTTP server (health checks on
/healthz, plus WebSocket/SSE streaming) - Publish
ObsReadyand enter command loop
Key subsystems:
- Executor (
Executor.hs): Runs shell commands with streaming output via callbacks. UsesOutputCallback = OutputChannel -> ByteString -> IO (). - State (
State.hs): STM-basedAgentStatewithTVars for secrets, active commands, metrics. All concurrent access goes throughatomically. - Server (
Server.hs): Servant-based HTTP/WS/SSE server. - NATS (
Nats.hs): Subscribes to command subjects, publishes observations. Uses natskell library. - Logging (
Logging.hs): Katip structured logging with namespaced contexts.
If MMDS is unavailable (e.g., running outside Firecracker), the agent falls back to HTTP-only mode unless --nats-url is provided via CLI.
agent.nix: Systemd service definition for scape-agent with security hardening. Options underservices.scape.agent.*.base-vm.nix: Firecracker microVM base config (256MB RAM, 1 vCPU, erofs+lz4, TAP networking, vsock CID 3). All templates import this.template.nix: Schema for template metadata (scape.template.<name>.*) — resources, egress policy, packages, mounts, secrets.
Each template is a NixOS config that imports base-vm and adds packages/services:
- python-sandbox: Python 3 + pip/numpy/pandas/requests, 512MB, deny-all egress
- duckdb-analyst: DuckDB + Python data stack, 1024MB, 2 vCPUs
- debug: SSH + debug logging for troubleshooting
Registered as flake outputs, used via: scape-ctl template add --name <name> --flake-ref github:getmissionctrl/scape-agents#<name>
- GHC 9.10 with
GHC2021language edition. Strict by default (StrictDataextension). -Wall -Werror— all warnings are errors.- Key extensions used everywhere:
OverloadedStrings,OverloadedRecordDot,DuplicateRecordFields,DerivingStrategies,RecordWildCards,LambdaCase. - All modules use explicit export lists with haddock section headers.
- Newtypes for domain identifiers (
CommandId,SessionId,Token, etc.). - Field updates via optics-core:
m & #commandsActive %~ (+ 1). - External dependency natskell is fetched from
github:getmissionctrl/natskellvia the flake.
Tests use hspec with the *Spec.hs naming convention. Test tree in test/Main.hs:
Agent.{StateSpec, ExecutorSpec, NatsSpec}— unit tests for agent subsystemsProtocol.{CommandSpec, ObservationSpec, MMDSSpec}— JSON round-trip property testsIntegration.AgentSpec— full agent + NATS integration (usesTest.Natsharness that auto-starts nats-server on a free port)
Test fixtures (NATS auth configs) live in test/fixtures/.