How to Set Up Tilde.run Agent Sandbox with S3 and GitHub on macOS
How to Set Up Tilde.run Agent Sandbox with S3 and GitHub on macOS
Running AI agents against production data has always felt like playing with fire. You want autonomous code that can read from your S3 buckets, modify files in GitHub, and output results—but without risking data exfiltration, credential leaks, or accidental destructive changes. Tilde.run solves this by wrapping every agent execution in a transactional, versioned filesystem with network isolation and rollback capabilities.
This guide walks you through setting up Tilde.run on macOS with mounted S3 data, GitHub code repositories, and strict egress policies.
Prerequisites
Before starting, you'll need:
- macOS 11+ (Intel or Apple Silicon)
- AWS credentials configured locally (for S3 access)
- GitHub token with repo read permissions
- Docker installed (Tilde.run runs agents in isolated containers)
- curl or Homebrew to install the Tilde CLI
Verify your setup:
aws --version
gh --version
docker --version
Step 1: Install Tilde.run CLI
The quickest way to install Tilde on macOS is via the official installer:
curl -fsSL https://tilde.run/install | sh
This script downloads the binary and adds it to your $PATH. Verify the installation:
tilde --version
If you prefer Homebrew:
brew install tilderun/tap/tilde
Step 2: Configure AWS S3 Mount
Tilde allows you to mount S3 buckets as a read-only filesystem layer. Create a project directory and initialize it:
mkdir my-agent-project
cd my-agent-project
tilde init
This generates a tilde.yaml configuration file. Edit it to mount your S3 bucket:
# tilde.yaml
project: my-ml-pipeline
mounts:
- source: s3://acme-data/training
path: /sandbox/data
access: read-only
credentials: aws-default
- source: github://acme/ml-pipeline
path: /sandbox/code
access: read-only
branch: main
- source: local
path: /sandbox/output
access: read-write
sandbox:
runtime: python:3.12
memory: 512Mi
cpus: 2
timeout: 3600
network:
policy: default-deny
allow:
- api.openai.com
- api.anthropic.com
- pypi.org
Key configuration points:
- read-only mounts prevent accidental modification of source data
- credentials: aws-default uses your local
~/.aws/credentialsfile - network.policy: default-deny blocks all outbound calls except explicitly allowed hosts
- memory and cpus limit resource consumption per run
Step 3: Configure AWS Credentials
Tilde reads AWS credentials from your standard ~/.aws/credentials file:
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region = us-east-1
For security, use an IAM user with minimal S3 permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::acme-data",
"arn:aws:s3:::acme-data/*"
]
}
]
}
Step 4: Set Up GitHub Repository Access
For Tilde to mount your GitHub repository, generate a personal access token (PAT):
- Go to GitHub Settings → Developer settings → Personal access tokens
- Click Generate new token (classic)
- Give it
reposcope (read-only for your purposes) - Copy the token
Store it in your environment or Tilde's credential store:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# Or register it with Tilde
tilde credentials add github acme-org ghp_xxxxxxxxxxxxx
Update your tilde.yaml to reference it:
mounts:
- source: github://acme/ml-pipeline
path: /sandbox/code
access: read-only
credentials: github
branch: main
Step 5: Create Your Agent Script
Now write the agent code. Tilde mounts everything as a standard POSIX filesystem, so any language works without SDK bindings:
#!/usr/bin/env python3
# agent.py
import os
import json
from pathlib import Path
# Read training data from mounted S3
data_dir = Path("/sandbox/data")
training_files = list(data_dir.glob("*.csv"))
print(f"Found {len(training_files)} training files")
# Read code from mounted GitHub repo
code_dir = Path("/sandbox/code")
readme = (code_dir / "README.md").read_text()
print(f"Project: {readme.split(chr(10))[0]}")
# Process data and write results (only to /sandbox/output)
output_dir = Path("/sandbox/output")
results = {
"files_processed": len(training_files),
"status": "success"
}
(output_dir / "results.json").write_text(json.dumps(results, indent=2))
print("✓ Results written to /sandbox/output/results.json")
Step 6: Run the Agent in a Transaction
Execute your agent inside a sandboxed transaction:
tilde run python agent.py
Tilde will:
- Spin up an isolated container with your mounts attached
- Execute the script with network isolation active
- Log all outbound requests (blocked by default)
- Commit changes atomically to
/sandbox/outputon success - Rollback everything on failure (no partial writes)
You'll see output like:
Sandbox: sb-7f3a9c01
Runtime: python:3.12
Found 847 training files
Project: ML Pipeline v2.1
✓ Results written to /sandbox/output/results.json
Transaction: COMMITTED
Changeset: a1b2c3d4 (HEAD)
Network egress: 0 allowed, 0 blocked
Step 7: Review Network Policy Violations
If your agent tries to make unauthorized API calls, Tilde blocks them and logs them:
tilde logs sb-7f3a9c01 --filter=network
Output:
12:04:07 POST evil-exfil.io /upload DENY (not in allow list)
12:04:08 GET 169.254.169.254 /metadata/latest DENY (cloud metadata blocked)
12:04:09 PUT registry.npmjs.org /my-pkg DENY (not in allow list)
Update your tilde.yaml if the blocked call was legitimate, re-run, and audit the change.
Step 8: Rollback a Failed Run
If something went wrong, roll back with one command:
tilde rollback sb-7f3a9c01
All writes to mounts are reversed instantly. Since everything is versioned from the first commit, you can also inspect what changed:
tilde diff a1b2c3d4 HEAD
Common Configuration Patterns
| Use Case | Config |
|----------|--------|
| Read-only data pipeline | access: read-only on data mounts |
| CI/CD approval gates | Add approval_required: true to agent config |
| Multi-region S3 data | Use ARNs in multiple mount sources |
| GPU workloads | Set runtime: pytorch:2.1-cuda |
| Credential rotation | Use credentials: aws-assume-role |
Best Practices
- Always use read-only mounts for source data. Reserve read-write access only for
/sandbox/output. - Whitelist outbound hosts explicitly. Start with
default-denyand add only required endpoints. - Set strict timeouts. Runaway agents will auto-kill after the timeout expires.
- Version your tilde.yaml. Treat it like code; changes are auditable.
- Test agent behavior locally first. Use
tilde run --dry-runto preview without committing. - Monitor egress logs regularly. Unexpected API calls often signal prompt injection or credential leaks.
Troubleshooting
Problem: S3 mount fails with "AccessDenied"
Verify your IAM policy includes s3:ListBucket and s3:GetObject on the target bucket.
Problem: GitHub mount shows "Repository not found"
Check that your PAT has repo scope and hasn't expired. Regenerate if needed.
Problem: Agent times out frequently
Increase timeout in tilde.yaml or optimize your script to avoid I/O bottlenecks on mounted filesystems.
Next Steps
With Tilde.run configured, you can now:
- Chain multiple agents by using output from one run as input to the next
- Add human approval gates before writes commit
- Integrate with LangGraph for agentic workflows
- Deploy to production knowing every run is safely reversible
Read the full Tilde documentation for advanced features like custom network policies, multi-region failover, and integration with Anthropic's Claude for more intelligent agent behavior.