sandbox
It lets an agent request privileged, human-approved actions executed outside its own context.
Run arbitrary shell commands through
run_privilegedwhen a human approves.Request file reads/writes outside the sandbox folder via
request_path_access.Fetch URLs through the sandbox with
fetch_url, with human approval.Check the outcome of pending or previously requested escalations using
check_request.View sandbox status, including the sandbox root, active triggers, and pending escalations via
sandbox_status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sandboxRunsudo apt-get updateand show the output."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agent Governance Gateway
An AI agent having a capability is not the same as it having authority. This system separates the two.
Authorization & governance infrastructure for autonomous AI agents. Drop it into any folder where an agent already runs — Claude Code, ChatGPT Enterprise/Codex, Cursor, Windsurf — and every tool call is answered, and recorded: who is the agent · what is it trying to do · to what resource · what authority does it have · what policy applies · does it need a human · who approved · what happened · can an examiner prove it. Privileged actions are escalated to a named human approver, executed outside the agent's context, and the output is fed back so the agent continues.
A private, in-tenant model (e.g. ChatGPT Enterprise on Entra) fixes data residency. It does not govern what the agent does — reading files outside its remit, writing to prod, or being prompt-injected into exfiltrating to an attacker host. That is an authorization problem, and it is what this governs.
For the banking/MUFG framing, start with docs/MUFG_BRIEF.md; to see it run, docs/DEMO.md.
Architecture
The Folder Connector bridges the sandbox into your project:
Claude Code hooks intercept tool calls, escalate privileged operations to a human approver, and return captured output inside a
denydecision so the tool never runs with agent privilegesMCP server (
run_privileged,check_request,sandbox_status) provides the same loop over the Model Context Protocol — works with Claude Code, Codex, Cursor, WindsurfFolder queue (
.sandbox/escalations/) is the bus: atomic file operations (os.replace,os.rename) coordinate approval across four unrelated processes (hook subprocess, MCP server, approver terminal, dashboard)Policy engine classifies shell commands, file writes, network requests, and reads — four escalation triggers with human-in-the-loop as the top tier
Related MCP server: Approval Gate
Quick Start
# Install the connector
python -m pip install -e ".[dev]"
# Initialize a folder
sandbox init . --claude --mcp
# In one terminal: watch for escalations
sandbox watch .
# In another: use Claude Code or the MCP tools as normal
# Privileged commands will appear in the `watch` terminal for approvalHow It Works
Agent tries to run a command — Claude Code's PreToolUse hook intercepts it
Hook classifies and escalates — shell commands not in the allowlist go to the folder queue
Human approves in
sandbox watch— the approver executes the command outside the agentOutput returns to the model — wrapped in
permissionDecision:"deny"with stdout in the reason stringAgent continues — it received the result, never had privilege itself
The MCP channel works identically: run_privileged returns a tool result with captured output.
Milestones
✅ Milestone 0 — Foundations (bug fixes, path containment, audit rehydration)
✅ Milestone 1 — The loop (PreToolUse hook, folder queue, CLI approval)
✅ Milestone 2 — MCP channel (run_privileged, check_request, sandbox_status)
✅ Milestone 3 — Folder record (restorable originals, chained audit, PostToolUse)
✅ Milestone 4 — Other triggers (full classifier, remembered decisions, SessionStart context)
✅ Milestone 5 — Surfaces (REST routes, uninstall, docs)
All milestones complete. See docs/CONNECTOR.md for the full technical reference.
Testing
# Run all tests (117 passing)
python -m pytest -q
# Test the loop with a real hook subprocess and background approver
python -m pytest tests/integration/test_connector_loop.py -v
# Test the MCP channel
python -m pytest tests/integration/test_mcp_tools.py -vProject Structure
src/sandbox/
├── connector/ # Folder connector (queue, hooks, policy, MCP)
├── launcher/ # M1 jailed launcher (job objects, jail, shims)
├── audit/ # Chained audit log with tamper detection
├── broker/ # Non-AI privilege executor
├── fs/ # Path containment and validation
├── agents/ # Multi-agent sandbox orchestrator
├── api/ # FastAPI routes and WebSocket
└── ...Key Design Decisions
The folder is the bus: Atomic file operations on NTFS coordinate four independent processes (no in-memory state, no open ports, survives restarts)
denycarries the output: Tool never executes in the agent; output is pasted back in the reason stringCLI-first approval: Headless, works over SSH, no browser dependency
Fail-closed: Internal errors block rather than silently allow
Non-removable self-protection:
.sandbox/**in write denials and\.sandboxin shell denials are re-injected on every policy load — agent cannot remove its own constraints
License
[To be determined]
Available Tools
5 toolscheck_requestA
Retrieve the outcome of an escalation (from MCP OR the hook).
Use this after run_privileged returns 'pending', or to pick up a request the Claude Code hook raised.
| Name | Required | Description | Default |
|---|---|---|---|
| request_id | Yes | ||
| wait_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. Yet it never explains the polling semantics implied by wait_seconds — what happens on timeout, whether it blocks, what states the outcome can be in, or the return shape. For a polling-type tool this is a notable gap given there is no annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the purpose front-loaded ahead of the usage trigger. No filler. It only loses a point because the second clause ('or to pick up a request the Claude Code hook raised') could arguably have been folded into the first, though it does add the sibling/hook context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given it has an output schema and only two parameters (one with a meaningful default), the description covers the core purpose and when to call it competently. But it leaves out the wait_seconds timeout/blocking behavior and the possible outcome states — information an agent polling after a pending escalation would reasonably need before calling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, but it adds no parameter meaning at all. request_id and wait_seconds are never explained beyond their raw schema definition (an ID string and a defaulted integer). The description's mention of 'the request' hints at request_id but provides no semantics like what a valid ID looks like or what wait_seconds controls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource — 'Retrieve the outcome of an escalation' — with an explicit scope qualifier ('from MCP OR the hook'). It differentiates itself from its sibling run_privileged by the triggering mechanism it responds to, so an agent can tell exactly what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use context: 'after run_privileged returns pending, or to pick up a request the Claude Code hook raised.' This is clear and actionable, though it stops short of stating when-not-to-use or naming an alternative for older/unresolved requests.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_urlA
Fetch a URL through the sandbox. A human approves; you get the body.
Network access is gated — the sandbox performs the fetch outside your context so you never make the request directly.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| reason | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that a human approves each request and that the sandbox performs the fetch outside the agent's context, providing key behavioral context. However, it does not cover all potential behaviors like failure scenarios or rejection handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with two short paragraphs that front-load the primary purpose and add key behavioral context without unnecessary words. Every sentence contributes value, making it well-structured and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with only two parameters, and the description covers the main flow (fetch, approval, body). However, it omits the purpose of the 'reason' parameter, which is significant given zero schema descriptions. The output schema likely covers return format, but the missing parameter explanation creates a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, but it fails to explain the 'reason' parameter or any URL constraints. It implicitly mentions the URL but adds no meaningful detail beyond what the schema already shows (just types). The optional reason parameter is left unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches a URL through the sandbox, specifying both the verb and resource. It is distinct from siblings like run_privileged and request_path_access, making its purpose unambiguous and easy to differentiate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when needing to fetch a URL and mentions human approval, but it does not explicitly state when to use this tool versus alternatives or specify exclusions. The guidance is implied rather than explicit, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
request_path_accessA
Request a file operation OUTSIDE the sandbox folder.
A human approves; the sandbox performs the read or write on your behalf
(you never receive the capability). mode is "read" or "write"; for
"write", pass the file content in content.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | read | |
| path | Yes | ||
| reason | No | ||
| content | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses critical behavioral traits: a human must approve, the sandbox performs the read/write on the agent's behalf, and the agent never receives the capability. This covers the most important asynchronous and security implications. It does not mention whether the operation is blocking or how to check approval status, but the core behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no redundancy. The first sentence states the purpose upfront, and the second explains the approval process and parameter usage. Every word earns its place, and the structure is optimized for quick comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the description is fairly complete for a tool that requires human approval. It covers the main flow (request, approval, sandbox performs) and key parameters (mode, content). It does not mention that the operation is asynchronous or that the agent should poll check_request for status, but given the sibling tools and the output schema, this is a moderate gap. Overall, it's adequate but not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for parameter meaning. It does explain 'mode' (valid values 'read' or 'write') and 'content' (used with write mode), which adds value. However, it does not clarify 'path' (though it's implied as the target file) or 'reason' (its purpose), leaving those parameters ambiguous. While partial compensation, the coverage gaps prevent a higher score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: requesting a file operation outside the sandbox folder. It specifies the verb 'Request' and the resource 'a file operation', and the scope 'OUTSIDE the sandbox folder' differentiates it from siblings like run_privileged, fetch_url, check_request, and sandbox_status, which have distinct purposes. The distinction is explicit and leaves no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: this tool is for file operations that need to happen outside the sandbox. It implies that for operations inside the sandbox, this tool is not needed. However, it does not explicitly name alternatives or state when not to use it; rather, it relies on the reader to infer that other tools like run_privileged or fetch_url are for different resource types. This is clear context but no exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_privilegedA
Request a privileged shell command. A human approves; you get the output.
The command runs OUTSIDE the sandbox on your behalf — you never receive root yourself. Returns the captured stdout/stderr on approval.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | ||
| command | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full responsibility. It discloses critical behaviors: human approval is required, the command runs outside the sandbox, the agent never receives root, and output is captured on approval. This is substantial transparency, though it omits what happens on rejection, timeouts, or any safety caveats—more than enough to earn a 4 but not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The core action is front-loaded ('Request a privileged shell command'), and the second sentence adds essential behavioral context. Every clause earns its place; it is a model of conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the description misses critical operational details an agent needs: what happens if approval is denied, is the request asynchronous (the term 'Request' implies a wait, but it is not stated), what is the expected latency, and how does the 'reason' parameter factor into approval. It also does not mention safety or restrictions on the command. These gaps are significant for a privileged, human-in-the-loop tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description does not shed any light on the parameters. It never mentions 'command' or 'reason' by name, nor explains expected syntax, purpose of reason, or any parameter-specific guidance. With zero schema coverage, the description must compensate but fails entirely.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Request') and resource ('a privileged shell command'), and the second sentence adds the key differentiator: it runs outside the sandbox. This distinguishes it from siblings like fetch_url (network) and request_path_access (file access), so an agent can tell it apart without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It is clear the tool is for running privileged shell commands that require human approval, but it does not explicitly state when to prefer it over alternatives or when not to use it. There is no mention of 'use this when sandbox is insufficient' or 'instead of sandbox_status'. The context is implied but not made explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sandbox_statusA
Show the sandbox root, triggers, and any pending escalations.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. The verb 'Show' implies a non-mutating, read-only operation, which is useful implicit disclosure. However, it doesn't explicitly state that it has no side effects, requires no auth, or how escalations are represented. For a status tool this is acceptable but leaves room for more explicit guarantees.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with zero waste. The verb leads, and each listed item (root, triggers, pending escalations) earns its place by describing distinct output facets. Nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool with an output schema present, the description is largely complete — it states exactly what the status covers. Minor gaps exist (e.g., no mention of when status is current or whether it reflects a snapshot), but these are not material for an agent deciding to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and an empty input schema with 100% coverage, so there is nothing for the description to add. Per the baseline for a 0-param tool, a 4 is appropriate — no parameter documentation burden exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource — 'Show the sandbox root, triggers, and any pending escalations.' The verb 'Show' signals a read-only status operation, and the listed content (root, triggers, escalations) is concrete. It does not explicitly contrast with siblings, but the domain is distinct enough from run_privileged, request_path_access, fetch_url, and check_request that an agent can infer the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus the siblings. It does not state prerequisites, conditions, or exclusions. For example, it doesn't clarify that this should be called before requesting access or that it's the safe inspection entry point. The agent must infer usage purely from the name and the sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.0.0- First observed
check_request - First observed
fetch_url - First observed
request_path_access - First observed
run_privileged - First observed
sandbox_status
TDQS
Scored across 5 tools
Each tool targets a distinct capability: shell execution, file access, network fetch, request status, and sandbox overview. There is no overlap in purpose, and descriptions clearly delineate boundaries.
Most tools follow a verb_noun pattern (run_privileged, request_path_access, fetch_url, check_request), but sandbox_status breaks the pattern by being noun_noun. The deviation is minor and the intent remains clear.
With 5 tools, the server is well-scoped for its purpose of gated external operations. Each tool earns its place without redundancy or excess.
The surface covers all core operations (run, file, fetch) and provides status retrieval via check_request and sandbox_status. No obvious dead ends or missing lifecycle steps for the stated escalation workflow.
Maintenance
Related MCP Connectors
Preventive human-approval write-gate for AI agents: writes commit only after a human approves.
Human-in-the-loop approval for agent actions, with verifiable action-bound receipts.
Runtime permission, approval, and audit layer for AI agent tool execution.
Supervised API-write gateway for AI agents with policy, human approval and execution receipts.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceHuman-in-the-Loop authorization gateway for AI Agents. Securely pause MCP workflows and route high-risk actions to human approvers via Slack or Email.64 npm1MIT
- AlicenseNot gradedqualityDmaintenanceProvides a human approval gate for AI agents, enabling interactive inline cards for approving, editing, or rejecting actions before they are executed.MIT
- AlicenseNot gradedqualityCmaintenancePauses AI agent execution and routes approval requests to humans via Slack or email, with cryptographically signed proof of the human's decision.18 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to securely use real secrets (API keys, database passwords) by requiring human approval for each release, ensuring secrets never enter the model's context.2Apache 2.0