Architecture

At runtime, Loopy is one engine process plus a fresh sandbox for each step's agent. This page walks through both, and the outside services they depend on.

Loopy engine

The running system has two halves. The engine (loopy run) is one ordinary process: it receives webhooks, turns them into events, and decides which steps run next. The agents do the actual work, each in its own sandbox, away from the engine. When something happens outside (a Sentry alert, a push to GitHub) it arrives as a webhook and a sensor turns the payload into an event. A cron trigger skips that path: on schedule, the engine builds the tick event itself. Either way, the engine finds the steps that listen for the event, and each of those steps gets an agent in a fresh sandbox.

External sources your signals

Sentry Linear Datadog GitHub
HTTPS POST /hooks/…

The engine

SensorRunner
Runs your @sensor code: a raw payload becomes a registered event.
EventReceiver
Re-validates the event against the registry, then publishes it.
EventBus
Routes events to every on: subscriber. The one piece you can swap out.
WorkflowRunner
Runs steps in after: order, fills in their templates, records history.

On one machine the bus lives inside the process; point it at redis to receive webhooks on one machine and run steps on another. Run history is written to SQLite. For each step, the AgentHarness fills in the step's instructions, then starts the agent in the sandbox below.

per step, the AgentHarness launches the agent

Sandbox

The agent CLI runs here, isolated from the engine. The agent's model calls and tool side effects (git push, open a PR) all originate here. Egress is open unless the sandbox sets a network: allowlist.

How it runs today: one machine, plus sandboxes

Today Loopy is built to run on a single machine. Everything in the diagram except the sandboxes lives inside the one loopy run process: the SensorRunner, EventReceiver, EventBus, Scheduler, Runtime, and the per-step AgentHarness are all part of it, and the StateStore (run history) is a SQLite file next to it. There is one process to start, one to watch, and one file of history.

The agents are the only part that runs somewhere else. Each step gets its own fresh sandbox (Daytona by default), so the model calls and the git work happen away from the engine, with egress open unless the sandbox sets a network: allowlist. Secrets are injected into the sandbox, never into the engine or the compiled manifest. The engine decides what runs; the sandboxes do the running. Two services sit outside both and are reached from inside the sandbox: the model API (Anthropic or OpenAI) and GitHub.

Growing past one machine is a swap, not a rewrite. Point the EventBus at Redis, and webhooks can land on one machine while workers on other machines pick up steps from the stream. The sandboxes were already elsewhere, so nothing else moves, and no workflow .md changes.

The services Loopy relies on.

Loopy itself is the engine that compiles your project and drives runs. It leans on a few external services for the parts it doesn't run.

Daytona

The default sandbox: a container cloud where each step's agent runs, isolated and built from the image: spec in registry.yml. You reach it with DAYTONA_API_KEY in loopy.env (DAYTONA_API_URL is optional and defaults to prod). To run agents locally instead, switch a sandbox's provider: to docker (hermetic, same image spec) or local (a bare subprocess).

Anthropic

The model behind the default claude-code harness. Set ANTHROPIC_API_KEY in the sandbox's env_file (secrets/base.env); it is injected into the sandbox at runtime, not held by the engine. The scaffold's default model for the claude-code harness is claude-opus-4-8, set per agent in registry.yml (every agent names its model and harness explicitly) (for example on an agent named Claude).

OpenAI

The model behind the codex harness, an alternative to claude-code. A codex agent (say Codex) sets a gpt-* model such as gpt-5.5; put OPENAI_API_KEY in the same sandbox env_file. An agent names exactly one harness, so a project can mix both by referencing a claude-code agent (Claude) on some steps and a codex agent (Codex) on others.

GitHub

Where agents clone, push, and open PRs. The recommended path is a GitHub App you create with the manifest flow: the engine mints a short-lived, repo-scoped token per step and injects only that token into the sandbox. A plain GITHUB_TOKEN (a PAT) in the sandbox env_file also works if you skip the App.

Where each credential lives is the whole point of the split: loopy.env holds the engine's infrastructure creds (Daytona, the GitHub App key), and the sandbox env_file holds the agents' creds (the model key). See Secrets.