July 13, 202611 min

Loopy and the case for compiling your agent workflows

Peter Zakin's open-source framework treats agent orchestration as a compilation problem. Sensors, typed events, and markdown workflows replace the glue code everyone else writes by hand.

Loopy (repo: peterzakin/loopy) is an open-source agent orchestration framework by Peter Zakin that does something most projects in this space haven't tried: it compiles your agent workflows before running them. You write markdown files for workflow steps, Python decorators for sensors, and a single YAML registry for agents, sandboxes, and events. Then loopy compile builds a DAG, validates types, checks that your model-harness pairings make sense, and tells you what's broken. No runtime surprises.

The framework launched on PyPI as loopy-computer in late June 2026. It's at v0.2.0 with 37 stars and 176 merged pull requests in its first month. Thirty-seven stars isn't a ton, but 176 merged PRs in a month is a serious pace for any open-source project. And the scope is unusual: Loopy doesn't just give you a sandbox to run an agent in. It gives you the entire loop, from the webhook that starts the work to the typed event that carries data between steps to the isolated environment where the agent executes.

Most of the open-source agent projects we've covered in this series hand you a piece of the puzzle and wish you luck with the rest. Loopy tries to hand you the whole thing.

Loopy four-part architecture: sensors feed the event bus, which triggers workflows running in sandboxesthe full loopsensorswebhook · poll · built-inevent bustyped events · in-proc or Redisworkflowsmarkdown steps · DAG · templatessandboxeslocal · docker · daytonaGitHubSentryZendeskdata flows down, events flow across

Loopy's four-part architecture: sensors, event bus, workflows, sandboxes.

The shape of the loop

Most open-source agent projects cover one or two pieces of the automation problem. Open-Inspect handles the control plane and sandbox but leaves event sourcing to you. Open-swe gives you the sandbox abstraction and invocation surface but not scheduling or cross-workflow coordination. Claude Code Routines ship a cron trigger but run locally with no event bus. Each project solves its slice well and hands you the rest.

Loopy's pitch is that the full loop belongs in one framework. The architecture has four parts:

Sensors are Python functions decorated with @sensor(webhook="/path", emits="EventName") or @sensor(poll="interval", emits="EventName"). A sensor receives a raw payload from Zendesk, Datadog, Sentry, or any HTTP source and transforms it into a typed event. A polling sensor checks an endpoint on a cadence and emits an event only when the check fails or finds new data. Five GitHub events and three Sentry events are built in, no sensor code required.

The event bus routes typed events to workflows. In-process by default, swappable to Redis for distributed deployments. Sensor-published events and step-emitted events look identical on the bus, so a workflow doesn't know or care whether its trigger came from a webhook or from another workflow's output.

Workflows are directories of markdown files. Each file is one step: YAML frontmatter declares the trigger (on: for entry steps, after: for subsequent ones), the agent, typed outputs, and optionally an event to emit. The prose body is the agent's instruction. Templates like {{ event.ticket_id }} inject data from upstream.

Sandboxes are isolated execution environments. Three providers today: local, docker, and Daytona. Each step gets a fresh sandbox with its own filesystem, cloned repos, and injected credentials. The sandbox is the security boundary: agents run with full tool access inside the sandbox, and the sandbox constrains what they can reach outside.

Loopy four-part architecture: sensors feed the event bus, which triggers workflows running in sandboxesthe full loopsensorswebhook · poll · built-inevent bustyped events · in-proc or Redisworkflowsmarkdown steps · DAG · templatessandboxeslocal · docker · daytonaGitHubSentryZendeskdata flows down, events flow across

Loopy's four-part architecture: sensors, event bus, workflows, sandboxes.

Loopy compiler pipeline: six passes from file discovery to validated manifestcompile pipelineregistry.yml · workflows/ · sensors/P0 discoverP1–P2 registryP3–P5 workflowsP7 sensorsP6 templatesP8 cross-checkLOOPY-E201LOOPY-E102LOOPY-E401LOOPY-E301LOOPY-E506manifest.json

The compiler pipeline: six passes from discovery to manifest.

The compiler is the product

Plenty of frameworks validate configuration at startup. Loopy goes further: it has a genuine multi-pass compiler with stable diagnostic codes, a DAG builder, template reference resolution, and cross-cutting checks that span the entire project.

The pipeline runs six phases. Discovery (P0) reads the project layout. Registry loading (P1–P2) parses agents, sandboxes, and events from registry.yml with type desugaring. Workflow loading (P3–P5) parses frontmatter, builds the step DAG from on:/after: edges, and extracts template references. Sensor loading (P7) validates sensor decorators and injects built-in GitHub and Sentry events. Template resolution (P6) statically verifies that every {{ event.field }} and {{ step.field }} reference points at a real field on a real upstream producer. Cross-checking (P8) runs whole-project validations: lineage tracing, agent-model compatibility, and unused event detection.

Every error gets a stable code like LOOPY-E301 (undefined template variable) or LOOPY-E506 (model-harness mismatch). The codes are documented, never renumbered, and each one has a matching test fixture in the repo. Running loopy docs errors prints the full catalog from the CLI.

This compile-time rigor catches a class of problems that most agent orchestration tools surface only at runtime, if at all. A typo in an event field name? Caught before any agent runs. A Claude model specified on an OpenAI harness? Rejected during compilation. A workflow step referencing an output field that its predecessor doesn't produce? Flagged with the specific line and expected schema. The error messages point at the file and field, not at a stack trace from deep inside an execution engine.

The compiler also produces a manifest: a single JSON document that captures the fully resolved project, the DAG, and lineage data showing which sensors and steps produce and consume each event. The manifest is what the runtime executes against, and it's deterministic. Same project files, same manifest.

Loopy compiler pipeline: six passes from file discovery to validated manifestcompile pipelineregistry.yml · workflows/ · sensors/P0 discoverP1–P2 registryP3–P5 workflowsP7 sensorsP6 templatesP8 cross-checkLOOPY-E201LOOPY-E102LOOPY-E401LOOPY-E301LOOPY-E506manifest.json

The compiler pipeline: six passes from discovery to manifest.

Three agent harnesses: Claude Code, Codex, and OpenCode sharing a common protocolagent-neutral harnessesworkflow stepsame markdown promptclaude-codeclaude-sonnet-4-6codexgpt-5.5opencodeany providershared JSON output protocol{ output: { ... }, emits: { ... } }budget enforcement · model validationtoolchain layering · credential isolation

Three harnesses: Claude Code, Codex, OpenCode. Same workflow, different providers.

Agent-neutral by design

Loopy ships three harnesses today: claude-code for Anthropic models, codex for OpenAI models, and opencode for OpenCode's multi-provider runner. Each harness knows how to build the CLI argv for its agent, parse the response envelope, and extract usage metrics. The shared base class handles the JSON output protocol, budget enforcement, and template rendering.

The practical consequence: you can mix providers in a single project. Route a triage step to a fast, cheap model on one harness, and route the fixer step to a stronger model on a different one. The workflow prose doesn't change. The agent: field in each step's frontmatter points at a registry entry, and the registry entry names the harness and model. Swap claude-sonnet-4-6 for gpt-5.5 by editing one line in registry.yml, not by rewriting the workflow.

The harness abstraction runs deeper than just swapping model names. Each harness declares its own toolchain layer: the apt packages, npm modules, and runtime dependencies that need to be layered onto the sandbox image so the agent CLI is available. The Claude Code harness installs Node and @anthropic-ai/claude-code. The Codex harness installs Node and OpenAI's Codex CLI. These toolchain layers compose onto the user's base image at sandbox build time, so the agent binary is present by construction, not by hope.

Model eligibility is validated at harness construction, not at step execution. If you name gpt-5.5 on a claude-code harness, the compiler rejects it immediately with LOOPY-E506. And budget enforcement is per-step: a budget: field in the step frontmatter caps wall-clock time and (for harnesses that report cost) USD spend. A step with a spend budget on a harness that doesn't report cost is a hard error, not a silent pass.

Three agent harnesses: Claude Code, Codex, and OpenCode sharing a common protocolagent-neutral harnessesworkflow stepsame markdown promptclaude-codeclaude-sonnet-4-6codexgpt-5.5opencodeany providershared JSON output protocol{ output: { ... }, emits: { ... } }budget enforcement · model validationtoolchain layering · credential isolation

Three harnesses: Claude Code, Codex, OpenCode. Same workflow, different providers.

Outputs, events, and the bus

The data model makes a clean distinction between two kinds of inter-step communication. Outputs are workflow-internal. A step declares output: { pr_url: url, verdict: str } in its frontmatter, and the next step in the after: chain reads those values as {{ step_name.pr_url }}. Outputs never touch the bus. They're passed directly along the DAG edges.

Events cross workflow boundaries. A step can declare emits: FixDeployed to publish a typed event to the bus when it finishes. Another workflow, listening with on: FixDeployed, picks it up. Sensors publish events the same way. From the bus's perspective, a sensor-published event and a step-emitted event are identical.

This separation matters because it keeps the common case simple. Most multi-step workflows are linear chains where each step feeds the next. Those don't need a bus at all, just typed references along the DAG. Events are for the cases where one workflow's completion should trigger a different workflow, or where a sensor's signal needs to fan out to multiple consumers. Keeping the two mechanisms distinct means the simple case stays simple and the complex case stays explicit.

The event schemas are defined once in registry.yml as typed field maps: str, int, float, bool, url, enum[a, b, c], or inline JSON Schema objects for nested structures. At compile time, the schemas are validated. At runtime, pydantic enforces them. And at authoring time, loopy compile code-generates Python dataclasses into loopy.events so your IDE's typechecker catches field mismatches in sensor code before you run anything.

Feature coverage: Loopy versus other open-source agent orchestration projectscoverage comparisonloopyotherstyped event contractscompile-time validationagent-neutral harnesseswebhook + poll sensorscron schedulingsandbox isolationmultiplayer sessionsCI feedback loopreal-time streaming UIcomplementary strengths, not a clear winner

Where Loopy sits relative to other open-source agent orchestration projects.

The coverage map

To put Loopy in context, here's how its coverage compares to other open-source projects we've looked at in this series.

Open-Inspect has the broadest trigger surface (Slack, Linear, GitHub, cron, Sentry, webhooks) and the most mature session model, but it's a single-tenant deployment with shared GitHub credentials and no typed contract system. Open-swe ships the cleanest sandbox abstraction and subagent spawning, but has no proactive triggers, no event bus, and no cross-workflow coordination. Claude Code Routines give you cron-triggered workflows on Anthropic's cloud with zero infrastructure, but you can't bring your own sandbox, use non-Anthropic models, or wire event-driven triggers. Aeon ships a self-healing cron runner with skill registries but stays in the scheduled-task lane.

Loopy covers more of the surface than any single project: typed events, a compile-time validator, an agent-neutral harness layer, sandboxed execution, multiple deployment paths, and both webhook and polling sensors. What it doesn't have yet is the session model that Open-Inspect provides (multiplayer sessions, real-time streaming, browser-based UI), or the deep CI integration that production background agents like Ramp's Inspect ship. The admin dashboard exists but is early. And the project is a month old with 37 stars, so the community is nascent.

The gap worth watching is the harness abstraction. The base class defines a clean JSON protocol that all agents are expected to emit. But each agent CLI has its own quirks around context length, tool availability, output format, and error handling. Provider abstractions tend to accumulate edge-case workarounds over time. Whether this one holds up across model updates and new providers without that drift is an open question.

Feature coverage: Loopy versus other open-source agent orchestration projectscoverage comparisonloopyotherstyped event contractscompile-time validationagent-neutral harnesseswebhook + poll sensorscron schedulingsandbox isolationmultiplayer sessionsCI feedback loopreal-time streaming UIcomplementary strengths, not a clear winner

Where Loopy sits relative to other open-source agent orchestration projects.

The markdown-as-prompt pattern

One of Loopy's quieter design choices is also one of its most interesting: the prose body of each workflow step is the agent's prompt. There's no separate prompt template language, no string interpolation library, no prompt management system. You write a markdown file with YAML frontmatter at the top and instructions in the body. The agent reads the body as its task description.

This means the workflow definition and the agent prompt are the same artifact. When you review a PR that changes a workflow step, you're reviewing the exact text the agent will receive. When you diff two versions of a step, you're diffing the exact difference in the agent's instructions. There's no indirection to trace.

The template variables ({{ event.ticket_id }}, {{ entry.pr_url }}) are the only dynamic parts, and they're statically resolved by the compiler. The agent never sees raw template syntax. It receives a fully rendered markdown document with concrete values.

This is a bet that LLMs are good enough at following natural-language instructions that you don't need a structured DSL for agent behavior. The agent's "programming language" is the same markdown you'd write in a GitHub issue or a Notion doc. The structure comes from the typed outputs and events, not from the prose.

When you review a PR that changes a workflow step, you're reviewing the exact text the agent will receive. There's no indirection, no separate prompt file, no string interpolation layer to trace.

Where it goes from here

Loopy launched less than a month ago and it already has a compiler pipeline, three harness integrations, three sandbox providers, three deployment paths, six documented examples, built-in GitHub and Sentry events, and an admin dashboard. The open issue list includes an Islo sandbox provider, suggesting more execution environments are coming.

As far as we can tell, it's the first open-source framework to treat the complete agent automation loop (sensors to events to workflows to sandboxed execution) as a single, compilable, versionable artifact. Most projects in this space ask you to assemble that loop yourself.

Whether that scope is a strength or a liability depends on adoption. A framework that covers the full loop only works if developers trust it enough to hand over the full loop. The compile-time safety, typed contracts, and clean error messages all push in the right direction. The loopy init wizard, the working examples, and the loopy doctor pre-flight checks lower the barrier. But it's still a new project asking you to commit your agent automation infrastructure to a single framework.

For teams that have been building agent loops out of scripts, cron jobs, and ad-hoc webhook handlers, Loopy offers a clear upgrade path: replace the glue code with declarations and let a compiler tell you when they're wrong. For teams already invested in a specific platform, the switching cost is real. At a month old with serious engineering behind it, the remaining question is whether enough developers adopt it to sustain the scope it's taken on.

✦ Newsletter

Liked this essay?

Get the next one in your inbox. One email per essay, no spam.

Posted July 13, 2026 · AgentWorkforce

Issues, PRs, and arguments welcome on GitHub. Or email [email protected].