Budget-Controlled Batch Jobs
Run multiple agent tasks in parallel with per-sandbox budgets, automatic shutdown on overspend, and cost tracking across the batch.
Prerequisites
- Caged CLI installed
- API key configured (
caged login)
- Agent API key in Caged secrets
Single Task with Budget Guard
# Run with a $5 hard limit — sandbox terminates if exceeded
caged run \
--template python-312 \
--cpus 2 \
--memory 1024 \
--repo https://github.com/your-org/data-pipeline \
--budget 5 \
--env "OPENAI_API_KEY=$OPENAI_API_KEY"
If the agent hits the $5 limit, the sandbox is immediately terminated and you’ll see:
WARN: Sandbox cage-a1b2c3d4 terminated — budget limit reached ($5.00/$5.00)
Batch Processing Script
Process multiple repos or tasks with individual budgets:
#!/bin/bash
# batch-agent.sh — Run agent tasks in parallel with budget controls
TASKS=(
"repo1|Fix all type errors|3"
"repo2|Add unit tests for utils/|5"
"repo3|Refactor database layer|8"
"repo4|Update dependencies and fix breaking changes|4"
)
SANDBOX_IDS=()
# Launch all sandboxes
for task in "${TASKS[@]}"; do
IFS='|' read -r repo prompt budget <<< "$task"
SANDBOX_ID=$(caged run \
--template node-20 \
--cpus 2 \
--memory 2048 \
--repo "https://github.com/your-org/$repo" \
--budget "$budget" \
--env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
--json | jq -r '.id')
echo "[$repo] Sandbox: $SANDBOX_ID (budget: \$$budget)"
SANDBOX_IDS+=("$SANDBOX_ID|$repo|$prompt")
done
# Run agent in each sandbox
for entry in "${SANDBOX_IDS[@]}"; do
IFS='|' read -r id repo prompt <<< "$entry"
echo "[$repo] Running: $prompt"
caged exec "$id" "claude '$prompt'" &
done
# Wait for all background jobs
wait
# Report results
echo ""
echo "=== Batch Results ==="
caged list --json | jq -r '.[] | "\(.id)\t\(.status)\t$\(.cost)/\(.budget)"'
# Cleanup
for entry in "${SANDBOX_IDS[@]}"; do
IFS='|' read -r id _ _ <<< "$entry"
caged destroy "$id" --force
done
API-Driven Batch with Webhooks
For production batch processing, use the API with webhook callbacks:
#!/bin/bash
# Create sandbox with completion webhook
curl -X POST https://api.caged.dev/v1/sandboxes \
-H "Authorization: Bearer caged_sk_..." \
-H "Content-Type: application/json" \
-d '{
"template": "node-20",
"resources": {"cpu": 2, "memory": 2048},
"repo": "https://github.com/your-org/project",
"budget": 5.00,
"secrets": ["ANTHROPIC_API_KEY"],
"init_script": "npm install && npm install -g @anthropic-ai/claude-code",
"on_complete": "https://your-server.com/webhook/sandbox-done",
"on_budget_exceeded": "https://your-server.com/webhook/budget-alert"
}'
Cost Tracking
Monitor total batch spend:
# List all running sandboxes with costs
caged list
# Output:
# ID TEMPLATE STATUS COST BUDGET UPTIME
# cage-a1b2c3d4 node-20 running $1.23 $3.00 8m
# cage-e5f6g7h8 node-20 running $2.87 $5.00 12m
# cage-i9j0k1l2 node-20 completed $3.50 $8.00 22m
# cage-m3n4o5p6 node-20 killed $4.00 $4.00 15m ← budget hit
# Total spend across all sandboxes
caged list --json | jq '[.[].cost] | add | "Total: $\(.)"'
Config for Batch Workers
# .caged.yaml for batch processing
template: node-20
resources:
cpu: 2
memory: 2048
disk: 5
timeout: 900 # 15 min idle timeout (aggressive for batch)
budget: 5.00
secrets:
- ANTHROPIC_API_KEY
network_mode: allowlist
allowed_hosts:
- api.anthropic.com
- registry.npmjs.org
- github.com
env:
CI: "true" # Many tools respect this for non-interactive mode
FORCE_COLOR: "0" # Clean output for logs
Tips
Set budget per complexity: Simple tasks (lint fixes) need 2−3.Complexrefactorsneed5-10. Set budgets based on expected token usage.
Use aggressive timeouts: Batch jobs shouldn’t idle. Set timeout: 900 (15 min) so sleeping sandboxes don’t accumulate compute cost.
Monitor with webhooks: For production batch systems, use the on_complete and on_budget_exceeded webhooks instead of polling.