Sandbox Execution Model
For each execute_skill and run_code call, the Skills Runtime creates an ephemeral sandbox with isolated execution environment, mounted resources, and enforced resource limits.
Sandbox creation
Each execution creates a new sandbox with strict isolation:
Isolation mechanism
The runtime creates one of:
- Separate process — Non-root user with restricted environment
- Container — Isolated container runtime (Docker, etc.)
- Virtual machine — Full VM isolation for maximum security
Non-root execution
Runtimes MUST run skill code as a non-root user to prevent privilege escalation attacks.
Resource limits
Enforce limits on:
- CPU — CPU time or core limits
- Memory — RAM usage ceiling (e.g., 512MB, 4GB)
- Wall-clock time — Execution timeout
- Disk I/O — Optional, to prevent abuse
- Network — Restricted to allowlisted domains
Resource mounting
For each execution, the runtime mounts:
Skills
For each skill in mount_skills (and the target skill for execute_skill):
/skills/<skill_name>/ (read-only)
skill.toml
SKILL.md
code/
resources/
Skills are mounted read-only. Code can import them as Python modules:
from skills.salesforce.leads.sync import main
result = main({"env": "prod"})
Workspace
Create a writable /workspace/ directory for temporary files:
/workspace/
(ephemeral, writable, cleaned up after execution)
Blobs
Make input blobs available either:
- Mount as files:
/blobs/<blob_id>(read-only) - Via helper functions:
runtime.blobs.read_text(blob_id)
The second approach is preferred and more efficient.
Environment setup
Environment variables
By default, sanitize the environment. Only inject:
- Secrets — Only those listed in
permissions.secretsof the executing skill - Runtime variables — Minimal set (e.g.,
PATH,HOME) - Custom variables — Any passed by the LLM in
args(serialized as JSON, not env vars)
Example: Salesforce skill with secrets
# skill.toml declares:
[permissions]
secrets = ["SALESFORCE_API_KEY", "SALESFORCE_ORG_ID"]
# Runtime injects these env vars
os.environ["SALESFORCE_API_KEY"] # From runtime secure storage
os.environ["SALESFORCE_ORG_ID"]
Working directory
Set working directory to /workspace/.
Code execution
For execute_skill
- Import the skill's entrypoint module
- Call the
exportfunction with providedargs:
from skills.salesforce.leads.sync import main
result = main(args) # args from execute_skill params
For run_code
- Save the provided code as a temporary module
- Import and call the entrypoint function:
# Code provided by LLM
def main(args):
from skills.salesforce.leads.sync import main as sync_main
result = sync_main(args)
return result
result = main(args) # args from run_code params
Return value requirements
The entrypoint function must return a JSON-serializable object:
return {
"status": "completed",
"synced": 142,
"errors": []
}
Result collection
After execution completes or times out:
Output
Capture the return value from the entrypoint function:
output = result # Must be JSON-serializable, ≤ 4KB
Logs
Capture stdout and stderr, truncate to preview (≤ 2KB):
logs_preview = stdout + stderr # Truncated
Output blobs
Collect any blobs created via runtime.blobs.write_*():
output_blobs = [blob_ids_created_during_execution]
Cleanup
Destroy the sandbox and all temporary files in /workspace/.
Runtime helpers
Sandboxes provide a runtime module with helper functions. MVP requires:
runtime.blobs
read_text
Read a blob's full content as text.
content = blobs.read_text(blob_id)
write_text
Store text content as a new blob.
blob_id = blobs.write_text(content)
write_json
Serialize and store JSON data as a blob.
blob_id = blobs.write_json(obj)
runtime.log
info
Log an info message.
log.info("Processing 142 records...")
error
Log an error message.
log.error("Failed to authenticate")
Example usage
from runtime import blobs, log
def main(args):
log.info("Starting sync...")
# Read input blob
csv_data = blobs.read_text(args['input_blob'])
# Process data...
results = process(csv_data)
# Write large results to blob
output_blob = blobs.write_json(results)
log.info(f"Created output blob: {output_blob}")
return {
"status": "completed",
"output_blob": output_blob
}
Execution flow diagram
┌─────────────────────────────────────────┐
│ execute_skill / run_code call │
│ (with args, mount_skills, blobs) │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 1. Create sandbox │
│ - Process/Container with limits │
│ - Non-root user │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 2. Mount resources │
│ - /skills/<name>/ directories │
│ - /workspace/ (writable) │
│ - Blobs via runtime.blobs │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 3. Set environment │
│ - Inject only required secrets │
│ - Sanitize environment │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 4. Execute code │
│ - Call entrypoint function │
│ - Capture output & logs │
│ - Enforce timeout │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 5. Collect results │
│ - Return value → output │
│ - Logs → logs_preview │
│ - Created blobs → output_blobs │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ 6. Tear down │
│ - Destroy sandbox │
│ - Clean /workspace/ │
│ - Return result to LLM │
└──────────────────────────────────────────┘