sandbox
Sandbox configuration, protocols, and implementations for agent isolation.
This package defines tunable agent isolation infrastructure — sandbox types, token permission tiers, isolation configuration, and the protocols that sandbox and framework adapter implementations must satisfy.
Subpackages
core: Enums, config dataclasses, context, AgentSandbox, AgentFrameworkAdapter, and CredentialProvider protocols. implementations: Concrete implementations (NullSandbox, ClaudeCodeAdapter, NullCredentialProvider, FileCredentialProvider, etc.).
AgentFrameworkAdapter
Bases: Protocol
Protocol for building framework-specific agent CLI commands.
Implementations construct the raw CLI invocation string for a specific
AI framework (Claude Code, Codex, etc.). The resulting command is then
wrapped by an :class:AgentSandbox before execution.
Methods:
| Name | Description |
|---|---|
build_command |
Build the CLI command string for launching an agent. |
Source code in src/agentrelay/sandbox/core/adapters.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | |
build_command(config, signal_dir)
Build the framework-specific CLI command string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgentConfig
|
Agent configuration with framework, model, and settings. |
required |
signal_dir
|
Path
|
Path to the signal directory for this task. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The raw CLI command string ready for sandbox wrapping. |
Source code in src/agentrelay/sandbox/core/adapters.py
32 33 34 35 36 37 38 39 40 41 42 | |
AnthropicCredential
dataclass
Resolved Anthropic credential for agent authentication.
Holds a named credential entry from the credentials YAML
anthropic section, with type-specific fields populated.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Key from the YAML |
credential_type |
CredentialType
|
Whether this is an API key or OAuth credential. |
api_key |
Optional[str]
|
The API key string. Set when |
oauth_path |
Optional[Path]
|
Path to the |
Source code in src/agentrelay/sandbox/core/config.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
ContainerRuntime
Bases: str, Enum
Container runtime binary for OCI sandbox execution.
Attributes:
| Name | Type | Description |
|---|---|---|
DOCKER |
Docker container runtime. |
|
PODMAN |
Podman container runtime. |
Source code in src/agentrelay/sandbox/core/config.py
51 52 53 54 55 56 57 58 59 60 | |
CredentialType
Bases: str, Enum
Type of Anthropic credential for agent authentication.
Attributes:
| Name | Type | Description |
|---|---|---|
API_KEY |
Pay-per-token API key (injected as env var). |
|
OAUTH |
Max plan OAuth token file ( |
Source code in src/agentrelay/sandbox/core/config.py
63 64 65 66 67 68 69 70 71 72 | |
IsolationConfig
dataclass
Fully-resolved sandbox configuration for an agent or task.
All fields are required — partial/inherited configs are resolved during YAML parsing before constructing this type.
Attributes:
| Name | Type | Description |
|---|---|---|
sandbox_type |
SandboxType
|
Type of sandbox boundary (none or OCI container). |
token_tier |
TokenTier
|
Permission tier for credential injection. |
image |
Optional[str]
|
Container image name, or None for default. |
runtime |
Optional[ContainerRuntime]
|
Container runtime, or None for default (Docker). |
Source code in src/agentrelay/sandbox/core/config.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
SandboxContext
dataclass
Execution context passed to sandbox operations.
Provides the sandbox implementation with the paths, identifiers, and environment variables it needs to set up and wrap agent commands.
Attributes:
| Name | Type | Description |
|---|---|---|
worktree_path |
Path
|
Absolute path to the git worktree for this task. |
signal_dir |
Path
|
Absolute path to the signal directory for this task. |
repo_path |
Path
|
Absolute path to the main repository. |
task_id |
str
|
Unique identifier of the task being sandboxed. |
graph_name |
str
|
Name of the task graph being executed. |
attempt_num |
int
|
Current attempt number (0-indexed). Used to generate unique container and tmux window names across retries. |
env_vars |
dict[str, str]
|
Environment variables to inject into the sandbox. |
Source code in src/agentrelay/sandbox/core/config.py
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
SandboxType
Bases: str, Enum
Type of sandbox execution boundary.
Attributes:
| Name | Type | Description |
|---|---|---|
NONE |
No sandbox — agent runs directly on the host. |
|
OCI |
Agent runs inside an OCI container (Docker/Podman). |
Source code in src/agentrelay/sandbox/core/config.py
25 26 27 28 29 30 31 32 33 34 | |
TokenTier
Bases: str, Enum
Permission tier for credential injection into sandboxed agents.
Attributes:
| Name | Type | Description |
|---|---|---|
READ_ONLY |
Read-only access (e.g., repo clone, PR read). |
|
STANDARD |
Standard access (e.g., push branches, create PRs). |
|
ELEVATED |
Elevated access (e.g., merge PRs, admin operations). |
Source code in src/agentrelay/sandbox/core/config.py
37 38 39 40 41 42 43 44 45 46 47 48 | |
CredentialProvider
Bases: Protocol
Protocol for resolving a token tier into credential environment variables.
Implementations map a :class:TokenTier to a dictionary of environment
variable names and values that should be injected into the agent's
execution environment.
Methods:
| Name | Description |
|---|---|
resolve |
Resolve a token tier into credential environment variables. |
Source code in src/agentrelay/sandbox/core/credentials.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
resolve(tier)
Resolve a token tier into credential environment variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tier
|
TokenTier
|
Permission tier to resolve credentials for. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dictionary of environment variable names to values. |
Source code in src/agentrelay/sandbox/core/credentials.py
28 29 30 31 32 33 34 35 36 37 | |
SandboxInfrastructureManager
Bases: Protocol
Protocol for managing graph-level sandbox infrastructure.
Implementations handle the setup and teardown of infrastructure required by sandboxed agents — for example, creating and removing Docker networks for OCI-isolated tasks.
The graph name (needed for network naming) is captured at construction time by the factory, keeping the protocol methods argument-free.
Methods:
| Name | Description |
|---|---|
setup |
Provision infrastructure before orchestrator execution. |
teardown |
Clean up infrastructure after orchestrator execution. |
Source code in src/agentrelay/sandbox/core/infrastructure.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
setup()
Provision sandbox infrastructure.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If required infrastructure cannot be created. |
Source code in src/agentrelay/sandbox/core/infrastructure.py
32 33 34 35 36 37 38 | |
teardown()
Clean up sandbox infrastructure.
Best-effort: implementations should swallow errors when resources are already removed.
Source code in src/agentrelay/sandbox/core/infrastructure.py
40 41 42 43 44 45 46 | |
AgentSandbox
Bases: Protocol
Protocol for wrapping agent commands with sandbox isolation.
Implementations control how an agent command is executed — directly on the host (NullSandbox), inside a container (OciSandbox), etc.
Methods:
| Name | Description |
|---|---|
wrap_command |
Transform a raw agent command into a sandboxed command. |
setup |
Perform any pre-launch setup (e.g., create Docker network). |
teardown |
Clean up sandbox resources after agent completion. |
Source code in src/agentrelay/sandbox/core/sandbox.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
wrap_command(cmd, context)
Wrap an agent command string with sandbox isolation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cmd
|
str
|
The raw agent command to execute. |
required |
context
|
SandboxContext
|
Execution context with paths and environment. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The wrapped command string ready for execution. |
Source code in src/agentrelay/sandbox/core/sandbox.py
29 30 31 32 33 34 35 36 37 38 39 | |
setup(context)
Perform pre-launch sandbox setup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context with paths and environment. |
required |
Source code in src/agentrelay/sandbox/core/sandbox.py
41 42 43 44 45 46 47 | |
teardown(context)
Clean up sandbox resources after agent completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context with paths and environment. |
required |
Source code in src/agentrelay/sandbox/core/sandbox.py
49 50 51 52 53 54 55 | |
ClaudeCodeAdapter
Build the CLI command string for launching a Claude Code agent.
Constructs the claude CLI invocation with the signal directory
environment variable, optional model flag, and permission skip flag.
Source code in src/agentrelay/sandbox/implementations/claude_code_adapter.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
build_command(config, signal_dir)
Build the Claude Code CLI command string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgentConfig
|
Agent configuration. Uses |
required |
signal_dir
|
Path
|
Path to the signal directory, injected as the
|
required |
Returns:
| Type | Description |
|---|---|
str
|
The raw CLI command string, e.g.:: AGENTRELAY_SIGNAL_DIR="/path" claude --model X --dangerously-skip-permissions |
Source code in src/agentrelay/sandbox/implementations/claude_code_adapter.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
FileCredentialProvider
Resolve credential environment variables from a YAML file.
The YAML file contains a token_tiers mapping keyed by tier value
and an optional anthropic mapping of named Anthropic credentials.
On :meth:resolve, the requested tier's entries are returned.
The file is read once at construction time and cached.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path to the YAML credential file. |
Source code in src/agentrelay/sandbox/implementations/file_credentials.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | |
anthropic_names
property
Sorted list of available Anthropic credential names.
__init__(path)
Load and parse the credential YAML file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the YAML credential file. |
required |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file does not exist. |
ValueError
|
If the file is not valid YAML or has an unexpected structure. |
Source code in src/agentrelay/sandbox/implementations/file_credentials.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
resolve(tier)
Resolve credentials for the given token tier.
Returns the tier-specific credential environment variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tier
|
TokenTier
|
Permission tier to resolve credentials for. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dictionary of environment variable names to values. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the requested tier is not defined in the credential file. |
Source code in src/agentrelay/sandbox/implementations/file_credentials.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
resolve_anthropic(name=None)
Resolve a named Anthropic credential.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
Optional[str]
|
Credential name from the YAML |
None
|
Returns:
| Type | Description |
|---|---|
Optional[AnthropicCredential]
|
The resolved credential, or |
Optional[AnthropicCredential]
|
section is defined. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/agentrelay/sandbox/implementations/file_credentials.py
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
NullCredentialProvider
Credential provider that returns empty credentials for any tier.
Always returns an empty dictionary regardless of the requested token
tier. This is the default credential provider for SandboxType.NONE.
Source code in src/agentrelay/sandbox/implementations/null_credentials.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
resolve(tier)
Return an empty credential dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tier
|
TokenTier
|
Permission tier (unused). |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
An empty dictionary. |
Source code in src/agentrelay/sandbox/implementations/null_credentials.py
22 23 24 25 26 27 28 29 30 31 | |
NullSandboxInfrastructureManager
No-op infrastructure manager for graphs without OCI tasks.
Both :meth:setup and :meth:teardown are no-ops.
Source code in src/agentrelay/sandbox/implementations/null_infrastructure.py
11 12 13 14 15 16 17 18 19 20 21 | |
setup()
No-op setup.
Source code in src/agentrelay/sandbox/implementations/null_infrastructure.py
17 18 | |
teardown()
No-op teardown.
Source code in src/agentrelay/sandbox/implementations/null_infrastructure.py
20 21 | |
NullSandbox
Pass-through sandbox that applies no isolation.
All methods are no-ops: wrap_command returns the command unchanged,
and setup/teardown do nothing. This is the default sandbox for
SandboxType.NONE.
Source code in src/agentrelay/sandbox/implementations/null_sandbox.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
wrap_command(cmd, context)
Return the command unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cmd
|
str
|
The raw agent command. |
required |
context
|
SandboxContext
|
Execution context (unused). |
required |
Returns:
| Type | Description |
|---|---|
str
|
The original command string, unmodified. |
Source code in src/agentrelay/sandbox/implementations/null_sandbox.py
22 23 24 25 26 27 28 29 30 31 32 | |
setup(context)
No-op setup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context (unused). |
required |
Source code in src/agentrelay/sandbox/implementations/null_sandbox.py
34 35 36 37 38 39 | |
teardown(context)
No-op teardown.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context (unused). |
required |
Source code in src/agentrelay/sandbox/implementations/null_sandbox.py
41 42 43 44 45 46 | |
OciSandboxInfrastructureManager
Docker network lifecycle manager for OCI-sandboxed graphs.
Creates a Docker network named agentrelay-<graph_name> on
setup() and removes it on teardown().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph_name
|
str
|
Name of the graph (used for network naming). |
required |
Source code in src/agentrelay/sandbox/implementations/oci_infrastructure.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
setup()
Create the Docker network if it does not already exist.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If Docker is not available. |
Source code in src/agentrelay/sandbox/implementations/oci_infrastructure.py
27 28 29 30 31 32 33 34 35 36 37 38 | |
teardown()
Remove the Docker network (best-effort).
Source code in src/agentrelay/sandbox/implementations/oci_infrastructure.py
40 41 42 43 44 45 | |
OciSandbox
OCI container sandbox — wraps agent commands in docker run.
Mounts the git worktree, signal directory, and main .git/
directory into the container at their original absolute paths so
that internal git references resolve without modification.
Attributes:
| Name | Type | Description |
|---|---|---|
_image |
Container image to use. |
|
_runtime |
Container runtime binary name ( |
|
_anthropic_credential |
Resolved Anthropic credential for
agent authentication, or |
Source code in src/agentrelay/sandbox/implementations/oci_sandbox.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
setup(context)
Validate runtime and network are available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context with graph name for network naming. |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the container runtime is not available or the Docker network does not exist. |
Source code in src/agentrelay/sandbox/implementations/oci_sandbox.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
wrap_command(cmd, context)
Wrap an agent command in docker run with bind mounts and env vars.
Mounts
- worktree_path → worktree_path (read-write)
- signal_dir → signal_dir (read-write)
- main .git/ dir → same path (read-write, needed for commits)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cmd
|
str
|
The raw agent command to execute inside the container. |
required |
context
|
SandboxContext
|
Execution context with paths and environment. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The full |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/agentrelay/sandbox/implementations/oci_sandbox.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | |
teardown(context)
Stop and remove the container, swallowing errors if already gone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
SandboxContext
|
Execution context with task ID for container naming. |
required |
Source code in src/agentrelay/sandbox/implementations/oci_sandbox.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |