Documentation
¶
Overview ¶
Package container provides container lifecycle management for agents.
Index ¶
- Constants
- type AgentOpts
- type AgentRuntimeSpec
- type ConnectorBuildOpts
- type Container
- type ContainerManager
- type DirectRuntimeNetworkPolicy
- type DockerManager
- func (m *DockerManager) BuildConnectorBinary(ctx context.Context, opts ConnectorBuildOpts) error
- func (m *DockerManager) CaptureToolserverDiagnostics(ctx context.Context, name, reason string) error
- func (m *DockerManager) Close()
- func (m *DockerManager) GetRunning(ctx context.Context, agentID uuid.UUID) (*Container, error)
- func (m *DockerManager) InspectConnectorManifest(ctx context.Context, binaryPath string) ([]byte, error)
- func (m *DockerManager) InspectManifest(ctx context.Context, imageRef string) (manifest []byte, retErr error)
- func (m *DockerManager) KillToolserver(ctx context.Context, name string) error
- func (m *DockerManager) LockSwap(agentID uuid.UUID) func()
- func (m *DockerManager) MarkBusy(agentID uuid.UUID)
- func (m *DockerManager) MarkIdle(agentID uuid.UUID)
- func (m *DockerManager) PruneAgentResources(ctx context.Context, validAgents map[string]AgentRuntimeSpec) []uuid.UUID
- func (m *DockerManager) ReapJSExecutors(ctx context.Context) error
- func (m *DockerManager) RemoveImage(ctx context.Context, imageRef string) error
- func (m *DockerManager) RunningAgents(ctx context.Context, agentIDs []uuid.UUID) (map[uuid.UUID]bool, error)
- func (m *DockerManager) StartAgent(ctx context.Context, opts AgentOpts) (*Container, error)
- func (m *DockerManager) StartJSExecutor(ctx context.Context, runID, token uuid.UUID) (io.ReadWriteCloser, error)
- func (m *DockerManager) StartTestJSExecutor(ctx context.Context, buildID uuid.UUID) (io.ReadWriteCloser, error)
- func (m *DockerManager) StartToolserver(ctx context.Context, opts ToolserverOpts) (*Container, error)
- func (m *DockerManager) StopAgent(ctx context.Context, agentID uuid.UUID) error
- func (m *DockerManager) StopToolserver(ctx context.Context, name string) error
- type JSExecutorManager
- type RuntimeNetworkPolicy
- type TestJSExecutorManager
- type ToolserverOpts
Constants ¶
const AgentStartupHealthTimeout = 2 * time.Minute
AgentStartupHealthTimeout bounds cold runtime initialization, including migrations and process-local startup hooks that complete before readiness.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AgentOpts ¶
type AgentOpts struct {
AgentID uuid.UUID
Image string // Docker image to run (e.g., "my-agent:abc123")
Token string // Versioned agent JWT issued from the live agent row
Env map[string]string // Additional environment variables
}
AgentOpts configures an agent container.
type AgentRuntimeSpec ¶ added in v0.4.0
PruneAgentResources removes Docker containers and images for agents that no longer exist in the database, and removes stale image tags for active agents (keeping only the current image_ref).
AgentRuntimeSpec is the persisted identity a reusable agent container must match.
type ConnectorBuildOpts ¶ added in v0.6.1
type ConnectorBuildOpts struct {
SourceDir string
OutputDir string
Package string
Filename string
Platform string
GoProxyDir string
}
ConnectorBuildOpts describes one pure-Go connector compilation in the untrusted build sandbox. Platform is empty for the Linux-native manifest binary, which every connector package must compile regardless of its targets.
type Container ¶
type Container struct {
ID string // Docker container ID
Name string // Human-readable name
Endpoint string // HTTP endpoint (e.g., "http://172.17.0.2:8080")
Token string // Bearer token for authenticating requests to this container
AgentID uuid.UUID
// Image is the tag the container was started with, copied from
// Docker's Config.Image at inspect time. StartAgent compares this
// against opts.Image to detect a stale running container after a
// build/rollback swap — adopting one with the wrong image would
// silently keep the agent on the old code.
Image string
// Network is the Docker network selected when the runtime was created.
// Managed isolation uses it to reject containers left on a shared network.
Network string
}
Container represents a running container.
type ContainerManager ¶
type ContainerManager interface {
// StartAgent ensures an agent container is running.
// Returns the existing container if already running and healthy.
StartAgent(ctx context.Context, opts AgentOpts) (*Container, error)
// GetRunning returns the running container for an agent without starting
// one if absent. Returns (nil, nil) when no container is up. Used by
// out-of-band signals (e.g. /refresh push) where booting a container
// just to notify it would defeat the purpose.
GetRunning(ctx context.Context, agentID uuid.UUID) (*Container, error)
// RunningAgents reports, per requested agent ID, whether a running
// container currently exists for it. One Docker query regardless of
// how many agents are asked about — for list/grid views that would
// otherwise fan out into one inspect per agent.
RunningAgents(ctx context.Context, agentIDs []uuid.UUID) (map[uuid.UUID]bool, error)
// StopAgent stops a specific agent's container (resolved from the agent
// ID via the instance-scoped name scheme).
StopAgent(ctx context.Context, agentID uuid.UUID) error
// MarkBusy / MarkIdle bracket an in-flight request to an agent
// container. While the in-flight count is above zero the idle
// reaper leaves the container alone, even past the idle timeout —
// so a run that runs longer than the timeout is not killed
// mid-execution. MarkIdle also refreshes the idle clock, so the
// timeout is measured from the end of the last request. Pair every
// MarkBusy with exactly one MarkIdle.
MarkBusy(agentID uuid.UUID)
MarkIdle(agentID uuid.UUID)
// StartToolserver starts an ephemeral toolserver container for build operations.
// Returns the container with a WebSocket endpoint for tool execution.
StartToolserver(ctx context.Context, opts ToolserverOpts) (*Container, error)
// StopToolserver stops and removes an ephemeral toolserver container.
StopToolserver(ctx context.Context, name string) error
// KillToolserver force-kills (SIGKILL) and removes an ephemeral
// toolserver container without waiting for graceful shutdown. Used
// on the build-cancel path so an in-flight tool stops emitting logs
// the moment cancel hits, instead of after the 5s graceful timeout.
KillToolserver(ctx context.Context, name string) error
// CaptureToolserverDiagnostics snapshots abnormal runtime state/logs
// before the ephemeral toolserver container is removed.
CaptureToolserverDiagnostics(ctx context.Context, name, reason string) error
// InspectManifest runs a candidate image in manifest mode and returns the
// manifest written to stdout.
InspectManifest(ctx context.Context, imageRef string) ([]byte, error)
// BuildConnectorBinary compiles one connector with CGO disabled in a
// read-only, capability-free build container.
BuildConnectorBinary(ctx context.Context, opts ConnectorBuildOpts) error
// InspectConnectorManifest runs a native connector binary in the same
// no-network manifest envelope used for candidate agent manifests.
InspectConnectorManifest(ctx context.Context, binaryPath string) ([]byte, error)
// RemoveImage removes a Docker image by reference (e.g., "agentID:hash").
RemoveImage(ctx context.Context, imageRef string) error
// LockSwap serializes the agent's container-swap window. Held by the
// builder around Phase F (StopAgent → StartAgent → UpdateAgentRefs)
// and by EnsureRunning around its GetAgent → StartAgent critical
// section, so a concurrent trigger can't start the old image while a
// build is mid-swap (and vice versa). Returns a release function
// callers must defer. Scope is just the swap — codegen, image build,
// and migration validation all run outside the lock.
LockSwap(agentID uuid.UUID) func()
}
ContainerManager manages the lifecycle of agent containers.
type DirectRuntimeNetworkPolicy ¶ added in v0.4.1
type DirectRuntimeNetworkPolicy struct{}
DirectRuntimeNetworkPolicy keeps managed per-agent networks internet-capable. Per-agent networks still separate runtimes from one another.
type DockerManager ¶
type DockerManager struct {
// contains filtered or unexported fields
}
DockerManager implements ContainerManager using the Docker API.
func NewDockerManager ¶
func NewDockerManager(cfg *config.Config, pool *pgxpool.Pool, networkPolicy RuntimeNetworkPolicy, logger *zap.Logger) *DockerManager
NewDockerManager creates a Docker-based ContainerManager.
func (*DockerManager) BuildConnectorBinary ¶ added in v0.6.1
func (m *DockerManager) BuildConnectorBinary(ctx context.Context, opts ConnectorBuildOpts) error
BuildConnectorBinary compiles untrusted connector source without exposing the Docker socket, runtime credentials, or a writable source tree.
func (*DockerManager) CaptureToolserverDiagnostics ¶ added in v0.4.0
func (m *DockerManager) CaptureToolserverDiagnostics(ctx context.Context, name, reason string) error
CaptureToolserverDiagnostics snapshots abnormal tool runtime state/logs.
func (*DockerManager) Close ¶
func (m *DockerManager) Close()
Close stops the idle reaper and closes the Docker client.
func (*DockerManager) GetRunning ¶
GetRunning implements ContainerManager. Returns (nil, nil) when no container exists for the agent — caller is expected to treat that as "nothing to do" rather than an error. Repopulates the in-memory cache when it finds a running container Airlock didn't previously know about (typical after an Airlock restart).
func (*DockerManager) InspectConnectorManifest ¶ added in v0.6.1
func (m *DockerManager) InspectConnectorManifest(ctx context.Context, binaryPath string) ([]byte, error)
InspectConnectorManifest executes only the mounted native binary. The read-only root, absent network, and empty environment keep source-controlled code away from build and runtime credentials while it declares its contract.
func (*DockerManager) InspectManifest ¶ added in v0.5.0
func (m *DockerManager) InspectManifest(ctx context.Context, imageRef string) (manifest []byte, retErr error)
InspectManifest runs a candidate image without runtime credentials or network access and returns its bounded stdout. The image entrypoint selects the one-shot behavior from AIRLOCK_AGENT_MODE.
func (*DockerManager) KillToolserver ¶ added in v0.1.6
func (m *DockerManager) KillToolserver(ctx context.Context, name string) error
KillToolserver force-removes an ephemeral toolserver container without waiting for graceful shutdown. RemoveOptions{Force: true} sends SIGKILL and removes in one call, so any in-flight tool execution dies immediately. Used by the build-cancellation path: graceful shutdown is 5+ seconds of dead air during which the toolserver keeps running its in-flight tool (e.g. a long `bash go build`) and emitting log lines — which makes the cancel feel like it didn't take. Idempotent: returns nil/NotFound if the container is already gone.
func (*DockerManager) LockSwap ¶ added in v0.4.0
func (m *DockerManager) LockSwap(agentID uuid.UUID) func()
LockSwap acquires the per-agent container-swap mutex. See the ContainerManager interface comment for the design rationale.
func (*DockerManager) MarkBusy ¶ added in v0.4.0
func (m *DockerManager) MarkBusy(agentID uuid.UUID)
MarkBusy records the start of an in-flight request to an agent container. While the in-flight count is above zero the idle reaper skips the container, so a run that outlasts idleTimeout is not stopped mid-execution. Pair every MarkBusy with exactly one MarkIdle.
func (*DockerManager) MarkIdle ¶ added in v0.4.0
func (m *DockerManager) MarkIdle(agentID uuid.UUID)
MarkIdle records the end of an in-flight request. It also refreshes the idle clock so the timeout is measured from the end of the last request rather than its start.
func (*DockerManager) PruneAgentResources ¶
func (m *DockerManager) PruneAgentResources(ctx context.Context, validAgents map[string]AgentRuntimeSpec) []uuid.UUID
validAgents maps agent UUID string to its current runtime identity. Any container or UUID-tagged image owned by this instance (run.airlock.instance label) not matching this set is removed. Other instances' resources carry a different label value and are never listed here.
func (*DockerManager) ReapJSExecutors ¶
func (m *DockerManager) ReapJSExecutors(ctx context.Context) error
ReapJSExecutors only removes this instance's containers whose exact owner lease is no longer live. Another replica's live execution is never reclaimed.
func (*DockerManager) RemoveImage ¶
func (m *DockerManager) RemoveImage(ctx context.Context, imageRef string) error
RemoveImage removes a Docker image by reference.
func (*DockerManager) RunningAgents ¶ added in v0.4.0
func (m *DockerManager) RunningAgents(ctx context.Context, agentIDs []uuid.UUID) (map[uuid.UUID]bool, error)
RunningAgents implements ContainerManager. One ContainerList call, scoped to this instance via the ownership label, then matched back to the requested IDs via agentName. Builder/toolserver containers ("<instance>-agent-builder-*") also carry the label but never equal an agentName(id), so they fall out of the lookup harmlessly.
func (*DockerManager) StartAgent ¶
StartAgent implements ContainerManager.
func (*DockerManager) StartJSExecutor ¶
func (m *DockerManager) StartJSExecutor(ctx context.Context, runID, token uuid.UUID) (io.ReadWriteCloser, error)
func (*DockerManager) StartTestJSExecutor ¶
func (m *DockerManager) StartTestJSExecutor(ctx context.Context, buildID uuid.UUID) (io.ReadWriteCloser, error)
func (*DockerManager) StartToolserver ¶
func (m *DockerManager) StartToolserver(ctx context.Context, opts ToolserverOpts) (*Container, error)
StartToolserver starts an ephemeral toolserver container for build operations. The container runs the toolserver binary with the workspace mounted. Returns the container with a WebSocket endpoint for remote tool execution.
func (*DockerManager) StopAgent ¶
StopAgent implements ContainerManager. Idempotent: if Docker stopped or removed the container out-of-band (crash, OOM, daemon restart, the idle reaper), the desired post-condition — container not running — is already met, so a not-found error is success. Without this a dead-but-status='active' agent could never be stopped and so never restarted (the UI only offers Stop while active).
func (*DockerManager) StopToolserver ¶
func (m *DockerManager) StopToolserver(ctx context.Context, name string) error
StopToolserver stops and removes an ephemeral toolserver container.
type JSExecutorManager ¶
type JSExecutorManager interface {
StartJSExecutor(context.Context, uuid.UUID, uuid.UUID) (io.ReadWriteCloser, error)
}
JSExecutorManager is intentionally separate from reusable app containers. The stream is non-TTY stdin/stdout; Close must unblock both directions and destroy the realm. No endpoint, credentials, workspace, or network is exposed.
type RuntimeNetworkPolicy ¶ added in v0.4.1
RuntimeNetworkPolicy selects the Docker network boundary for an agent runtime. The OSS server supplies DirectRuntimeNetworkPolicy; distributions that require stricter containment can inject their own policy.
type TestJSExecutorManager ¶
type TestJSExecutorManager interface {
StartTestJSExecutor(context.Context, uuid.UUID) (io.ReadWriteCloser, error)
}
TestJSExecutorManager allocates only build-scoped test realms, using the same isolated image and resource recipe as chat execution.
type ToolserverOpts ¶
type ToolserverOpts struct {
Image string // toolserver image (e.g., "agent-builder:v1.0.0")
Mounts []mount.Mount // workspace bind mounts
WorkDir string // -space-dir value inside the container
Env []string // additional environment variables
LogCallback func(line string)
}
ToolserverOpts configures an ephemeral toolserver container for build operations.