Agent workflows that run when your data changes.
open source · agent neutral · code-first
Loopy is an open-source, agent-neutral framework for authoring agent automations. Workflows,
skills, and sensors live in your repo as Markdown and code, so they version, diff, and review
like the rest of your codebase. There is no canvas to click together: loopy compile builds
the workflow DAG straight from those files.
Installation
uv tool install loopy-computer # puts `loopy` on your PATH
Tip: Working from a checkout of this repo?
uv tool install .from the repo root installs your local source. Prefer not to install at all? Prefix commands withuv run(e.g.uv run loopy compile).
Quickstart
loopy init my-project # interactive wizard: scaffold, credentials, webhooks
cd my-project
loopy compile --check # is the project valid?
loopy doctor # is it runnable? (names anything still missing)
loopy trigger --json # fire one run end-to-end, full record on stdout
loopy run --in-process . # dev server: compiles, hosts sensors, records every run
loopy admin # in another terminal → http://127.0.0.1:9000
A project is a directory, and its credentials live inside it: secrets/base.env (the sandbox
environment) and loopy.env (control-plane credentials), both gitignored. loopy init sets
all of this up and finishes by running the same checks as loopy doctor, so you know exactly
what's left before a first run.
Why Loopy?
- Files, not canvases. Workflows are Markdown files with YAML frontmatter; the DAG is
compiled from
on:/after:edges. Everything versions, diffs, and reviews like the rest of your codebase. - Agent-neutral. Every agent names its
harness, the runner that drives it. Claude Code, OpenAI Codex, and OpenCode ship today, and the harness registry is built to take more. Mix them in one manifest: route triage to one harness and a fixer to another, and swap a step's harness or model without touching its prose. - Typed contracts. Events and step outputs are typed field maps (JSON Schema under the
hood, validated at runtime by pydantic and code-generated into
loopy.eventsfor your typechecker). - Sandboxed execution. Every agent runs in a declared sandbox (
local,docker, ordaytona) with an explicit image, environment, and cloned repos. The sandbox inherits nothing from your shell. - Budgets and limits. Per-step
budget:(wall clock, spend), plus registry-level caps for a whole workflow or an entire event cascade. - Built to be driven by agents.
loopy docsprints the full authoring reference as markdown straight from the CLI, and every check is exit-code-clean, so a coding agent can drive the whole authoring cycle headlessly. - Observability included. Runs are recorded to a durable store;
loopy adminserves a dashboard of run timelines, emitted events, outputs, and failures, locally or against a hosted control plane, bearer-token-gated end to end.
How it works
A workflow is a directory of steps. Exactly one entry step carries on: (a registered
event, or a built-in cron("<expr>") trigger); every other step carries after: <step> and
consumes its predecessors' outputs. A step is one Markdown file:
---
after: fix # or `on: <RegisteredEvent>` for the one entry step
agent: Reviewer # from registry.yml
output: { verdict: enum[pass, fail], notes: str } # structured outputs, typed
budget: { wall_clock: 20, spend: { usd: 4 } }
---
The agent's objective, in prose; reads {{ event.* }} and {{ fix.diff }} (an output of `fix`).
The reusable entities (Agents, Sandboxes, and Events) are defined once in
registry.yml and referenced by name:
defaults:
agent: { sandbox: default, model: claude-sonnet-4-6, harness: claude-code }
sandboxes:
default:
provider: daytona
image: { debian_slim: "3.12", apt: [git], workdir: /home/loopy, user: loopy }
env_file: secrets/base.env # gitignored; injected as the sandbox's env
repos: [octocat/Hello-World] # cloned into the workspace, git auth injected
agents:
Investigator: { skills: [triage, repro-authoring] } # inherits defaults
Fixer: { model: claude-opus-4-8, skills: [testing] }
Scout: { model: gpt-5, harness: codex, skills: [triage] }
events:
Incident: { source: enum[sentry, linear, datadog], issue_id: str, title: str, link: url }
WorkItem: { link: url, description: str }
A project lays out like this:
my-project/
registry.yml # reused, Capitalized entities: Agents · Sandboxes · Events
workflows/ # each subdirectory is one single-entry workflow
triage/ investigate.md # on: Incident → WorkItem
resolve/ arbitrate.md · fix.md · review.md · ship.md
skills/ # reusable agent skills, referenced by name from registry.yml
triage/ SKILL.md
sensors/ # the event-publish layer: code that emits registered events
sensors.py
Outputs vs. events. Within a workflow, data flows by reference along after: chains
({{ fix.diff }}); those are outputs and never touch the bus. Handoffs between workflows
go through events: a step emits: a registered event, and another workflow subscribes with
on:. The test: does another workflow need this value?
Sensors turn the outside world into registered events: a decorated function triggered by
a poll interval or a webhook route, where returning is emitting:
from loopy import sensor
from loopy.events import Incident # generated from registry.yml
@sensor(webhook="/hooks/sentry", emits="Incident")
def sentry_issues(req) -> Incident:
i = req.json["data"]["issue"]
return Incident(source="sentry", issue_id=i["id"], title=i["title"], link=i["permalink"])
Common GitHub and Sentry events are built in: a workflow can trigger on
on: Github.PullRequestOpened or on: Sentry.IssueCreated with no registry entry and no
sensor at all, and loopy webhooks github registers GitHub's side for you. Webhook signatures
(X-Hub-Signature-256, Sentry-Hook-Signature) are verified at the edge before any sensor
sees the payload.
Examples
examples/ is the cookbook. Each subdirectory is a self-contained project with
its own README, grouped in examples/README.md:
| Example | What it shows |
|---|---|
codefix/ |
The smallest runnable loop: one event, one agent that edits a checkout and opens a PR. Its README is the "run locally" quickstart. Start here. |
incidents/ |
The canonical multi-workflow loop: triage → resolve → confirm, plus a nightly cron scan, wired by events at the workflow boundaries. |
github/ |
The canonical webhook loop: one /hooks/github URL fans out to sensors for PR review and follow-on work. |
effective-agents/ |
Anthropic's Building Effective Agents patterns (prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer), each as a Loopy workflow. |
auto-research/ |
A self-driving research loop: digest → hypothesize → experiment → write up → reflect, bounded by budgets. |
Documentation
The full reference ships inside the CLI, version-matched to your install and readable offline (or by an agent):
loopy docs # the full authoring reference: workflows, registry, sensors, secrets
loopy docs deployment # hosting the control plane: env vars, $PORT, TLS, admin auth
loopy docs errors # the stable LOOPY-E diagnostic catalog
The verify loop is exit-code-clean (loopy compile --check → loopy doctor →
loopy trigger --json), so a coding agent can author and validate a project end to end.
The only two commands that need a human are loopy init (interactive wizard) and
loopy auth github (browser flow).
Deployment
The serve contract is deliberately provider-agnostic (a process env var, $PORT, TLS at the
platform ingress, and durable run state behind the StateStore protocol), so nothing in Loopy
branches on the hosting provider. One public URL is path-routed: webhook deliveries at
$LOOPY_PUBLIC_URL/hooks/*, the bearer-token-gated dashboard at $LOOPY_PUBLIC_URL/admin,
and an open GET /healthz for platform probes.
| Concern | Loopy depends on | Render | Fly / Railway | k8s | Bare VM |
|---|---|---|---|---|---|
| Secret | LOOPY_ADMIN_TOKEN from env |
dashboard env var | fly secrets / env |
Secret → env | env / loopy.env |
| TLS | terminated by the ingress | auto | auto | Ingress + cert-manager | nginx/caddy |
| Port | $PORT (fallback --port) |
injected | injected | containerPort | flag/env |
| Persistence | StateStore (SQLite file) |
persistent disk | volume | PVC | disk |
loopy docs deployment prints the full contract; the design, guardrails, and OIDC upgrade
path live in docs/design/admin-auth.md.
License
Loopy is open source under the Apache License 2.0. You're free to use, modify, and distribute it, including commercially; the license adds an express patent grant and asks that you preserve attribution and note significant changes.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file loopy_computer-0.2.0.tar.gz.
File metadata
- Download URL: loopy_computer-0.2.0.tar.gz
- Upload date:
- Size: 584.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa6ceae543cabae2470a0ab58d36e7c81ed986c0a3efb95730611fc0174c99e7
|
|
| MD5 |
57f2faefa4840ce9fd40649aa8ccf8af
|
|
| BLAKE2b-256 |
3bb5c5e327faeda8d8c26ca41be2f73a9b72d551063b4f471b063d6b36382230
|
File details
Details for the file loopy_computer-0.2.0-py3-none-any.whl.
File metadata
- Download URL: loopy_computer-0.2.0-py3-none-any.whl
- Upload date:
- Size: 287.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffbe18cf4855c56160a36a60e1ebd7637b566314a1d39bfa163af1ae068de9b3
|
|
| MD5 |
dca3fa20953a03af396f49e760fc2b2c
|
|
| BLAKE2b-256 |
db9b87df45ceac83ae4e51ba32ec3d13f8a0cc18d879c62386b47e1c279bac3e
|