Skip to main content
Stripe’s Minions are unattended coding agents that one-shot tasks end to end: a developer kicks one off, and it produces a complete pull request with no human in the loop. Over 1,300 PRs merge at Stripe each week this way. This guide shows you how to build the same thing with isol8 — the architecture, each pipeline stage, and the patterns that make one-shot agents reliable.

Architecture

A one-shot coding agent system has three layers: a client that submits tasks, an orchestrator that sequences steps, and an isol8 container where all code and agent work happens. The client can be anything — a GitHub bot reacting to issue labels, a Slack bot responding to commands, a web UI with a task form, or a CLI script. It simply sends a task description to the orchestrator and optionally consumes progress events. The orchestrator is the core of the system. It creates a single persistent isol8 container and runs a pipeline of steps inside it: Every step runs inside the same container. The filesystem state built up during setup (/sandbox/repo) persists through implement, verify, fix, and ship.

The container: one persistent session per task

Each task gets a single DockerIsol8 instance in mode: "persistent". All steps share the container’s filesystem.
network: "host" is used here because the agent needs to reach GitHub, the LLM provider API, and package registries simultaneously. If you know your exact set of hostnames, network: "filtered" with an explicit whitelist is more secure. See Security considerations.

Step 1: Setup — clone before the agent starts

Before the agent receives any prompt, a setupScript clones the repo and checks out a branch. Setup scripts run as bash inside the container and complete before the main execution begins.
git checkout -b on retry: With set -e, git checkout -b exits non-zero if the branch already exists (e.g. on a retry). The || git checkout ${branch} fallback is load-bearing — always include it.

Step 2: Implement — the agent gets the task

The implement step passes a prompt to the agent runtime. The agent reads files, writes code, and runs tools — all inside the sandbox. A naive approach passes the raw task description directly:
This works for simple tasks but is fragile. The isol8 agent has no way to ask follow-up questions — the prompt is the complete specification.
In practice, the orchestrator should act as a master agent. Gather context before handing off: read relevant files, pull issue details, summarize related PRs, fetch coding guidelines. Construct a self-sufficient prompt that gives the agent everything it needs without clarification.
A better implement step looks like this:

Step 3: Verify — lint and build

After the agent implements, deterministic shell steps verify the result. Lint and build are the only steps allowed to fail — their output is collected and fed into a fix loop, not treated as a hard error.

Step 4: Fix loop — automated retry

If lint or build fails, the fix loop runs the agent again with the error output, then re-verifies. Two rounds is the practical ceiling — after that, hand off to humans.
Diminishing returns set in quickly. Two fix rounds is the practical ceiling — after that, hand off to humans rather than burning more tokens.

Step 5: Ship — commit and open a PR

The commit and PR steps are also delegated to the agent. Two shell patterns matter:

Full pipeline

Putting it all together, the orchestrator function:

Streaming progress to clients

Every step can use executeStream() to emit progress in real-time. The phase field on each StreamEvent distinguishes setup output from agent output:
How you relay these events to the client depends on your architecture — SSE, WebSockets, a message queue, or writing to a database that the client polls. The orchestrator produces StreamEvents; what the client does with them is up to you.
If the setupScript exits non-zero, the stream yields a { type: "error", phase: "setup" } event followed by an exit event, and the agent never starts. Filter on phase to surface setup failures separately from agent failures.

Concurrency and cancellation

When running multiple tasks concurrently, use a job queue with bounded concurrency. Each task should get its own AbortController for cancellation — aborting triggers engine.stop() to destroy the container immediately.
Inside the orchestrator, wire the abort signal to engine.stop():

Security considerations

For production deployments — especially multi-tenant or untrusted-task workloads — use network: "filtered" with an explicit allowlist instead of network: "host":
All other isol8 isolation guarantees apply regardless of network mode: read-only root filesystem, non-root sandbox user, seccomp syscall filtering, /sandbox tmpfs, and automatic secret masking in output.

Agent in a Box

Full reference for the agent runtime: flags, networking, file injection, and streaming.

Setup scripts

Image-level vs request-level setup, execution order, streaming output, and error handling.

AI agent code execution

Foundational patterns for LLM tool-call loops with isol8.

Security model

Network controls, seccomp, secret masking, and isolation boundaries.

Remote server

Deploy isol8 as a centralized execution server for agent fleets.