Outcall
SpecificationsS005 · Agent Shim

S005 · Agent Shim

Specification module 005-agent-shim

S005: Agent Shim

FieldValue
SpecS005
FeatureAgent Shim
Date2026-04-21
StatusDraft
Author@marktopper

Overview

The agent shim (outcall-agent) is a small, statically linked binary that is bind-mounted read-only into every agent container at /usr/local/bin/outcall. It is the only interface between the agent process running inside the container and outcalld's agent API socket (/run/outcall/agent.sock).

The shim's job is to intercept every action the agent wants to take — tool invocations, outbound network requests, file operations — submit them to outcalld for policy evaluation, and enforce the verdict. If outcalld says allow, the shim executes the action. If outcalld says block, the shim refuses. If outcalld is unreachable at any point, the shim exits immediately with code 5 (fail closed).

The shim talks only to agent.sock. It has no access to host.sock or any other outcalld surface. The container cannot modify the shim binary because it is bind-mounted read-only.

CONTAINER (agent)
  └── outcall-agent (shim)     — bind-mounted read-only at /usr/local/bin/outcall
      └── talks to agent.sock only — no other outcalld access

User Scenarios

S005-US-001 [P1] As an agent process, I want the shim to verify that outcalld is reachable on startup so that I fail immediately if the security layer is missing.

S005-US-002 [P1] As an agent process, I want to submit tool invocations through the shim so that outcalld can approve or deny them against policy.

S005-US-003 [P1] As an agent process, I want outbound network requests to be checked against policy so that I cannot exfiltrate data to unauthorized destinations.

S005-US-004 [P1] As a host operator, I want the shim to fail closed (exit 5) whenever outcalld is unreachable so that an unmonitored agent cannot run unsupervised.

S005-US-005 [P2] As a host operator, I want the shim to log diagnostic information to stderr so that I can troubleshoot container issues without polluting the agent API channel.

Requirements Summary

IDTypePriorityTitleStatus
S005-FR-001FunctionalP1Socket path constantDraft
S005-FR-002FunctionalP1Startup socket checkDraft
S005-FR-003FunctionalP1Startup registrationDraft
S005-FR-004FunctionalP1Fail-closed exit codeDraft
S005-FR-005FunctionalP1Socket-only communicationDraft
S005-FR-006FunctionalP1Static binary, read-only mountDraft
S005-FR-007FunctionalP1Tool invocation interceptionDraft
S005-FR-008FunctionalP1Verdict enforcement (allow)Draft
S005-FR-009FunctionalP1Verdict enforcement (block)Draft
S005-FR-010FunctionalP1Network request gatingDraft
S005-FR-011FunctionalP1Default-block on no verdictDraft
S005-FR-012FunctionalP1Mid-session unreachable handlingDraft
S005-FR-013FunctionalP1Request timeoutDraft
S005-FR-014FunctionalP2Configurable timeoutDraft
S005-FR-015FunctionalP1Exit code semanticsDraft
S005-FR-016FunctionalP1Logging to stderrDraft
S005-FR-017FunctionalP1No stdout protocol pollutionDraft
S005-FR-018FunctionalP2Structured log formatDraft
S005-FR-019FunctionalP1Heartbeat loopDraft
S005-FR-020FunctionalP1Graceful shutdown on SIGTERMDraft
S005-FR-021FunctionalP2Agent identity propagationDraft
S005-FR-022FunctionalP1Verdict response passthroughDraft
S005-AS-001AcceptanceP1Startup happy pathDraft
S005-AS-002AcceptanceP1Startup socket missingDraft
S005-AS-003AcceptanceP1Tool allow verdictDraft
S005-AS-004AcceptanceP1Tool block verdictDraft
S005-AS-005AcceptanceP1Network request allowedDraft
S005-AS-006AcceptanceP1Network request blockedDraft
S005-AS-007AcceptanceP1Mid-session outcalld crashDraft
S005-AS-008AcceptanceP1Request timeoutDraft
S005-AS-009AcceptanceP2Graceful shutdownDraft
S005-AS-010AcceptanceP1Binary immutabilityDraft
S005-EC-001Edge CaseP1Socket missing at startupDraft
S005-EC-002Edge CaseP1Socket disappears mid-sessionDraft
S005-EC-003Edge CaseP1outcalld crashes mid-requestDraft
S005-EC-004Edge CaseP1Verdict timeoutDraft
S005-EC-005Edge CaseP2Malformed verdict responseDraft
S005-EC-006Edge CaseP2Concurrent requestsDraft
S005-EC-007Edge CaseP1Registration rejectedDraft
S005-EC-008Edge CaseP2Socket exists but not listeningDraft
S005-EC-009Edge CaseP2Container tries to overwrite shimDraft
S005-EC-010Edge CaseP1Rapid reconnect after socket flapDraft
S005-SC-001SuccessP1Startup and registration verifiedDraft
S005-SC-002SuccessP1Tool allow/block cycleDraft
S005-SC-003SuccessP1Network gating verifiedDraft
S005-SC-004SuccessP1Fail-closed on unreachableDraft
S005-SC-005SuccessP1No leaked actions after blockDraft
S005-SC-006SuccessP1Exit codes correctDraft
S005-SC-007SuccessP1Stderr-only loggingDraft
S005-SC-008SuccessP1Binary cannot be modifiedDraft

Out of Scope

  • Host API surface — the shim is a consumer of the agent API (S004), not a provider
  • Rule authoring — rules are defined via the host API; the shim only receives verdicts
  • Container lifecycle — starting/stopping containers is not the shim's concern
  • TLS on agent.sock — the socket is local and bind-mounted; no TLS needed
  • Agent process management — the shim wraps actions, it does not supervise the agent process
  • Direct nftables manipulation — network enforcement at the packet level is handled by the bridge (S001)
  • Multi-socket communication — the shim talks only to agent.sock, never host.sock

Cross-Spec Dependencies

  • Depends on: S004 (Agent API — the shim is its primary client)
  • Depends on: S003 (Rule Engine — verdicts come from rule evaluation)
  • Required by: Container management (future spec)

On this page