Autonomous Agent Sandboxes
Diverge includes a Kubernetes-native execution engine for autonomous coding agents (AgentTask). Each task runs inside a network-isolated sandbox pod (kubernetes-sigs/agent-sandbox), authenticates with an attenuated Macaroon capability token, optionally provisions an automatic linked preview Environment, and enforces strict iteration, USD cost, token, and wall-clock timeout guardrails via live LLM metering (POST /api/v1/agenttask/meter).
1. Architecture Overview
Section titled “1. Architecture Overview”flowchart LR
IDE["IDE / Agent / PR Comment"] -->|ConnectRPC / Webhook| Srv["diverge-server / controller"]
Srv -->|Creates / Updates| AT["AgentTask CR"]
Ctrl["diverge-controller"] -->|Watches| AT
Ctrl -->|1. Mints Macaroon| Sec["Secret: task-token + diverge-agenttask-tokens"]
Ctrl -->|2. Linked Preview| Env["Environment: agent-task"]
Ctrl -->|3. Provisions| Claim["SandboxClaim (agent-sandbox)"]
Claim -->|Spawns Pod| Pod["Agent Sandbox Pod (gvisor / kata)"]
Sec -->|Mounted Read-Only| Pod
Pod -->|Bearer Macaroon + Metering| Srv
NP["NetworkPolicy: diverge-sandbox-isolation"] -.->|Blocks Metadata & K8s API| Pod
Key Security Properties
Section titled “Key Security Properties”- Attenuated Macaroon Capability Tokens:
- Minted by
diverge-controllerusing HMAC-SHA256 chained caveats (task_id,namespace,repo,branch,tools,models,max_cost_usd,max_tokens,expires). - Mounted read-only into the sandbox pod at
/etc/diverge/token/token. - Verified by
diverge-serveragainst the namespace-scoped index Secret (diverge-agenttask-tokens) and liveAgentTaskphase (Active).
- Minted by
- Automatic Linked Preview Environments (
divergedev.com/preview-enabled: "true"):- When
spec.repository.urlis set (anddivergedev.com/preview-enabledis not"false"),AgentTaskReconcilerautomatically provisions and owns a linkedEnvironmentCR (agent-preview-<task-name>) tracking the agent’s working branch, populatesdivergedev.com/preview-environmentanddivergedev.com/preview-urlannotations, and injectsDIVERGE_PREVIEW_URL,DIVERGE_PREVIEW_HEADER_KEY, andDIVERGE_PREVIEW_HEADER_VALUEinto the sandbox pod.
- When
- Idempotent Live LLM Cost & Token Metering (
POST /api/v1/agenttask/meter):- Sandbox pods report incremental
tokensUsedandcostUSDrequest deltas (with an idempotentrequestIdand aniterationcounter) toPOST /api/v1/agenttask/meterondiverge-server(requestIdis the sole deduplication key). - Every metering heartbeat returns the latest
guidance,previewUrl,iteration, andmaxIterations. - Budget checks compare cumulative
status.costUSDandstatus.tokensConsumedagainst the effectiveAgentTaskbudgets: a positivespec.budgetUSDorspec.budgetTokensreplaces the Macaroon’smax_cost_usdormax_tokenscaveat (for example, a$1.00max_cost_usdcaveat withspec.budgetUSD: "5.00"enforces$5.00; the Macaroon caveat is used only when the correspondingspecfield is unset or zero).iterationis checked only againstspec.maxIterations(it is not a Macaroon caveat). When cumulative spend/tokens oriterationexceeds its limit,diverge-serveratomically transitions the task toPaused(Reason: BudgetExceeded), marks the token"revoked"indiverge-agenttask-tokens, and returns429 Too Many Requests({"suspended": true}).
- Sandbox pods report incremental
- Sandbox Suspension, Linked Preview Hibernation & Token Rotation:
- Setting
spec.suspended: true(viadiverge task pauseor/diverge pauseon a PR/MR) transitions the task throughPausingtoPaused, revokes the Macaroon token, suspends the sandbox (spec.operatingMode: Suspended), and hibernates the linked previewEnvironment(divergedev.com/hibernated: "true"). - Resuming a paused task (
diverge task resume --budget +15.00 --tokens 2000000or/diverge resume) un-hibernates the linked preview, wakes the sandbox, and mints a fresh capability token projected automatically into/etc/diverge/token/token.
- Setting
- Defense-in-Depth Network Isolation:
- The default
NetworkPolicy(<release>-sandbox-isolation) denies all ingress to sandbox pods, restricts egress to DNS (53) and HTTPS/SSH (443/22), and blocks cloud metadata (169.254.169.254/32,169.254.0.0/16) and the in-cluster Kubernetes API (10.96.0.1/32). - Pod specs set
AutomountServiceAccountToken: false,ReadOnlyRootFilesystem: true,RunAsNonRoot: true, and dropALLLinux capabilities.
- The default
2. Enabling Agent Sandboxes in Helm
Section titled “2. Enabling Agent Sandboxes in Helm”- Create a 32-byte Macaroon root key Secret in the controller namespace:
kubectl create secret generic diverge-macaroon-root-key \ -n diverge-system \ --from-literal=root-key="$(openssl rand -hex 32)"- Install or upgrade the Diverge Helm chart with
sandbox.enabled=trueandserver.enabled=true:
kubectl apply -f charts/diverge/crds/helm upgrade --install diverge charts/diverge \ --namespace diverge-system --create-namespace \ --set server.enabled=true \ --set sandbox.enabled=true \ --set sandbox.provider=agent-sandbox \ --set sandbox.macaroonSecretRef.name=diverge-macaroon-root-key \ --set sandbox.networkPolicy.enabled=true3. Repository Configuration (.diverge/agent.yaml) & Creating an AgentTask
Section titled “3. Repository Configuration (.diverge/agent.yaml) & Creating an AgentTask”Scaffold .diverge/agent.yaml with diverge task init
Section titled “Scaffold .diverge/agent.yaml with diverge task init”Run diverge task init inside your repository to generate .diverge/agent.yaml with default model capabilities, allowed tools, budget caps, and sandbox settings:
diverge task initversion: "1"agent: capabilities: - claude-3-7-sonnet - gemini-2.5-pro allowedTools: - git - go - npm - pytest - diverge_* budgetUSD: "5.00" maxIterations: 5 baseBranch: main sandbox: provider: agent-sandbox timeoutSeconds: 3600Create & Manage Tasks from the CLI (diverge task)
Section titled “Create & Manage Tasks from the CLI (diverge task)”# Submit an autonomous task from your terminaldiverge task create "Diagnose and fix N+1 query in /api/v1/checkout" --name fix-checkout-latency --budget 5.00 --base-branch main
# List tasks, inspect status, or stream live sandbox logsdiverge task listdiverge task status fix-checkout-latencydiverge task logs fix-checkout-latency -f
# Send real-time steering guidance (delivered on the next metering heartbeat)diverge task guide fix-checkout-latency "Ensure backward compatibility with API v1 clients"
# Pause and resume with an additive budget bump (+$15.00 USD and +2,000,000 tokens)diverge task pause fix-checkout-latencydiverge task resume fix-checkout-latency --budget +15.00 --tokens 2000000Declarative AgentTask Custom Resource
Section titled “Declarative AgentTask Custom Resource”You can also apply an AgentTask Custom Resource directly with kubectl, via diverge mcp, or from a GitHub/GitLab PR comment (/diverge fix <objective>):
apiVersion: divergedev.com/v1alpha1kind: AgentTaskmetadata: name: fix-checkout-latency namespace: default annotations: divergedev.com/preview-enabled: "true" divergedev.com/preview-service: "checkout-api" divergedev.com/preview-image: "ghcr.io/myorg/checkout-service:latest" divergedev.com/preview-port: "8080"spec: objective: "Diagnose and fix N+1 query in /api/v1/checkout and verify in a preview environment" draftPR: true repository: url: https://github.com/myorg/checkout-service baseBranch: main workingBranch: fix/checkout-n-plus-1 maxIterations: 8 budgetUSD: "5.00" budgetTokens: 200000 capabilities: - claude-3-7-sonnet - gemini-2.5-pro sandbox: provider: agent-sandbox timeoutSeconds: 18004. Live LLM Metering (POST /api/v1/agenttask/meter)
Section titled “4. Live LLM Metering (POST /api/v1/agenttask/meter)”Inside the sandbox pod, the agent harness reports token usage, USD cost, iteration, and an idempotent requestId after each LLM invocation:
curl -X POST "$DIVERGE_METER_URL" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(cat /etc/diverge/token/token)" \ -d '{ "requestId": "fix-checkout-iter-1", "iteration": 1, "model": "claude-3-7-sonnet", "tokensUsed": 1500, "costUSD": 0.0225 }'Node.js & Python SDK Metering Helpers
Section titled “Node.js & Python SDK Metering Helpers”Both @divergedev/sdk (Node.js) and diverge-sdk (Python) include built-in metering helpers that automatically read DIVERGE_MACAROON_TOKEN or /etc/diverge/token/token and surface live steering guidance and previewUrl:
// Node.js (@divergedev/sdk)import { meterLLMUsage, LLMMeterError } from '@divergedev/sdk';
try { const res = await meterLLMUsage({ requestId: 'fix-checkout-iter-1', iteration: 1, model: 'claude-3-7-sonnet', tokensUsed: 1500, costUSD: 0.0225, }); if (res.guidance) { console.log('Live steering guidance:', res.guidance); }} catch (err) { if (err instanceof LLMMeterError && err.isBudgetExceeded) { process.exit(0); // Task auto-paused by diverge-server } throw err;}# Python (diverge-sdk)from diverge_sdk import meter_llm_usage, LLMMeterError
try: res = meter_llm_usage( model="claude-3-7-sonnet", tokens_used=1500, cost_usd=0.0225, request_id="fix-checkout-iter-1", iteration=1, ) if res.guidance: print("Live steering guidance:", res.guidance)except LLMMeterError as err: if err.is_budget_exceeded: raise SystemExit(0) raise200 OK: Returns{"allowed": true, "suspended": false, "totalTokensUsed": 1500, "totalCostUSD": 0.0225, "iteration": 1, "maxIterations": 8, "guidance": "...", "previewUrl": "https://..."}. Each distinct metered LLM call must use a uniquerequestId(even within the same iteration); retried calls whoserequestIdremains in the bounded 32-entry ring buffer (status.lastMeterRequestIds) are idempotent and do not double-charge.403 Forbidden: Returned whenallowed_models(spec.capabilities) is configured on the token/task andmodelis omitted or not permitted (supporting exact or prefix wildcards likeclaude-*).429 Too Many Requests: Returned when cumulativestatus.costUSDorstatus.tokensConsumedexceeds the effective budget (spec.budgetUSD/spec.budgetTokenswhen positive, replacing the Macaroon’smax_cost_usd/max_tokenscaveat—e.g. a$1.00caveat withspec.budgetUSD: "5.00"stops at$5.00; the caveat applies only when thespecfield is unset or zero) with"reason": "budget exceeded", or wheniteration > spec.maxIterations(and the effective USD/token budgets have not already been exceeded) with"reason": "max iterations exceeded". If a single request crosses both a budget limit andspec.maxIterations,"reason": "budget exceeded"takes precedence. The task is automatically suspended (status.phase = Paused,spec.suspended = true) and the Macaroon token is revoked indiverge-agenttask-tokens.
5. Steering & Pausing Tasks (Paused / Active)
Section titled “5. Steering & Pausing Tasks (Paused / Active)”Pause Execution (spec.suspended: true or /diverge pause)
Section titled “Pause Execution (spec.suspended: true or /diverge pause)”Once the controller reconciles spec.suspended: true, it transitions the AgentTask to Paused and revokes its Macaroon token so subsequent tool calls to diverge-server are rejected with 401 Unauthenticated:
kubectl patch agenttask fix-checkout-latency --type=merge -p '{"spec":{"suspended":true}}'Guide & Resume Execution (spec.suspended: false or /diverge resume)
Section titled “Guide & Resume Execution (spec.suspended: false or /diverge resume)”Use the diverge_guide_task / diverge_resume_task MCP tools, comment /diverge resume on the PR/MR, or patch spec.suspended: false with an updated budget:
kubectl patch agenttask fix-checkout-latency --type=merge -p '{ "spec": { "suspended": false, "budgetUSD": "10.00", "maxIterations": 12 }}'When resumed, diverge-controller mints a new Macaroon capability token reflecting the updated budgetUSD and maxIterations limits and clears the revocation marker in diverge-agenttask-tokens.
6. Linked Preview Annotations & Automatic PR / MR Status Comments (SCMTaskNotifier)
Section titled “6. Linked Preview Annotations & Automatic PR / MR Status Comments (SCMTaskNotifier)”Linked Preview Annotations
Section titled “Linked Preview Annotations”- Input Annotations (on
AgentTask):divergedev.com/preview-enabled:"true"or"false"divergedev.com/preview-service: Target Kubernetes service name (defaults to<task.name>)divergedev.com/preview-image: Container image for the linked previewEnvironmentdivergedev.com/preview-port: Container/service port exposed on the linked previewEnvironment(defaults to80or8080)
- Output Annotations:
divergedev.com/preview-environmentanddivergedev.com/preview-urlon theAgentTaskdivergedev.com/sandbox-ipon the linkedEnvironment(propagating the live sandbox pod IP)
Automatic PR / MR Status Comments (SCMTaskNotifier)
Section titled “Automatic PR / MR Status Comments (SCMTaskNotifier)”When notifierProvider (github or gitlab) is configured on diverge-controller (along with the corresponding SCM credentials via DIVERGE_NOTIFIER_TOKEN, GITHUB_TOKEN, DIVERGE_GITLAB_TOKEN, or GITLAB_TOKEN), AgentTaskReconciler automatically initializes an SCMTaskNotifier (internal/notifier/task_notifier.go) that posts and idempotently updates a sticky comment (<!-- diverge-agent-task -->) on the associated Pull Request or Merge Request whenever the AgentTask transitions across Provisioning, Active, Paused, Completed, or Failed phases. /diverge fix webhook handlers automatically attach divergedev.com/provider, divergedev.com/project, and divergedev.com/pr-number (or divergedev.com/mr-iid) annotations onto created AgentTask resources. The comment includes:
- Current phase badge (
🚀 RunningforProvisioningandActive,⏸️ Paused,✅ Completed,❌ Failed) - Task objective and working branch
- One-click Magic Link (
?_diverge_env=) to open the agent’s linked preview environment and an Exit Preview (?_diverge_env=clear) link - Live cumulative LLM token and USD spend (
status.tokensConsumed/status.costUSD)
7. Bidirectional SCM Bot Interaction & PR/MR Slash Commands
Section titled “7. Bidirectional SCM Bot Interaction & PR/MR Slash Commands”Developers and reviewers can steer, pause, resume, and inspect AgentTask sandboxes directly from GitHub PR or GitLab MR comments:
| Slash Command | Action |
|---|---|
/diverge fix <objective> |
Spawns or updates an AgentTask (fix-pr-<num> / fix-mr-<iid>) for the branch with the specified objective |
/diverge guide <hint> |
Sends live steering guidance (divergedev.com/guidance) delivered to the running agent on its next metering heartbeat |
/diverge budget [+$budget] [tokens] |
Bumps the task’s USD and/or token budget without changing its suspension state |
/diverge pause |
Suspends the active AgentTask (spec.suspended: true), revokes its Macaroon token, and hibernates its linked preview environment |
/diverge resume [+$budget] [tokens] |
Resumes a paused AgentTask (spec.suspended: false) with optional additive budget bumps and mints a fresh Macaroon token |
/diverge status |
Posts an immediate Markdown summary of active AgentTasks and linked preview environments |
/diverge help |
Displays the interactive slash command reference table |
8. Reference Autonomous Agent Runner (cmd/agent-runner) & Admission Guardrails
Section titled “8. Reference Autonomous Agent Runner (cmd/agent-runner) & Admission Guardrails”Diverge ships a reference sandbox entrypoint binary (cmd/agent-runner, packaged via Dockerfile.agent-runner as ghcr.io/divergedev/agent-runner) that executes inside PodSandboxProvider and AgentSandboxProvider pods:
- Capability Token Resolution: Checks
DIVERGE_MACAROON_TOKENfirst and reads the mounted token file atDIVERGE_TOKEN_FILE(/etc/diverge/token/token) only whenDIVERGE_MACAROON_TOKENis empty. - Shallow Workspace Clone: Clones
DIVERGE_REPO_URL(--depth=50 --branch $DIVERGE_BASE_BRANCH) intoDIVERGE_WORKSPACE_DIR(/workspace) and checks outDIVERGE_WORKING_BRANCH(agent/<task-name>). - Metered Build-Verify-Fix Loop (
1..DIVERGE_MAX_ITERATIONS):- Reports token and USD consumption to
POST $DIVERGE_METER_URLbefore each iteration, halting immediately on429 Too Many Requests(ErrBudgetExceeded) or403 Forbidden(ErrModelDisallowed). - Runs
DIVERGE_AGENT_CMD(receivingDIVERGE_LAST_FAILUREon retry iterations) and validates the fix usingDIVERGE_VERIFY_CMDplus optional live HTTP health checks againstDIVERGE_PREVIEW_URLwith thex-diverge-envrouting header. - Stages, commits (
fix(<task>): <objective>), and pushesDIVERGE_WORKING_BRANCHonce verification passes.
- Reports token and USD consumption to
Admission Webhooks & CEL ValidatingAdmissionPolicy
Section titled “Admission Webhooks & CEL ValidatingAdmissionPolicy”Enable admission-time validation for Environment, PreviewGroup, and AgentTask Custom Resources in the Helm chart:
helm upgrade --install diverge charts/diverge \ --namespace diverge-system \ --set certManager.enabled=true \ --set webhook.validatingWebhook.enabled=true \ --set webhook.admissionPolicy.enabled=true