Workflow orchestrator using LangGraph with Claude (via ACP) and script execution backends
Project description
sqrlly
A high-level interface to and extension of LangGraph for agents in local environments. Declare a workflow in YAML; sqrlly compiles it to a runnable StateGraph and adds the runtime extensions agent workflows need:
- Nodes execute one of: an LLM prompt (agent-with-tools or text-only), an interpreted script (
.py/.js/.ts/.sh), a binary, or a recursive subgraph. - Local context — when run inside a git repo, every node gets its own isolated worktree; agents read dep outputs, edit files on disk, and run tools.
- Quality gates — a script or LLM scorer judges output; failing gates re-run the node with feedback injected, up to a configurable retry budget.
- Branching —
route:sends flow conditionally;fan_out:spawns parallel branches over a JSON manifest. - Resumable — state checkpoints to SQLite;
--resumepicks up where a stopped run left off.
Install
For CLI use (recommended — isolated venv, doesn't touch your project's environment):
pipx install sqrlly # or: uv tool install sqrlly
As a project dependency:
pip install sqrlly # core
pip install "sqrlly[acp]" # + ACP backend
LLM dispatch currently goes through the local claude-code-acp
adapter (also requires npm i -g @zed-industries/claude-code-acp on
your PATH). The direct-API backends (Anthropic / OpenAI / DeepSeek /
custom OpenAI-compatible endpoints) were removed in 0.2.x while the
project consolidates around a single transport — a re-introduced
transport: cli (and possibly transport: api) is on the roadmap.
Python 3.11+. From source: git clone then uv sync.
Quickstart
A two-node workflow — generate jokes, gate them, pick the best (examples/jokes/):
name: "Joke Generator"
version: "0.1.0"
nodes:
- id: generate
name: "Generate Jokes"
execute:
url: "examples/jokes/generate.md"
evaluation:
validator: "examples/jokes/gates/validate_jokes.py"
threshold: 1.0
blocking: true
max_retries: 2
- id: select
name: "Select Best Joke"
depends_on: ["generate"]
execute:
url: "examples/jokes/select.md"
settings:
presets:
default:
transport: acp
provider: anthropic
model: sonnet
default: true
sqrlly validate examples/jokes/workflow.yaml
sqrlly run examples/jokes/workflow.yaml --log run.jsonl
validate— compiles the graph and reports the node count.run— executes the workflow; with--log, writes a JSONL event stream (workflow_start,node_completed,gate_evaluated,node_retried,workflow_end).
How it works
- URL-based dispatch —
execute.url's extension picks the handler:.md/.txt/.prompt→ LLM prompt,.py/.js/.ts/.sh→ script,.yaml→ subgraph, anything else → binary. - Jinja2 templates — prompt files are full Jinja2;
{{generate}}interpolates an upstream node's output;{% if %}/{% for %}/ filters all work. - Retry feedback loop — when a gate scores below
threshold, the next attempt's context gets{{_retry_reason}}auto-populated with the previous score, per-dimension thresholds, and feedback. - Worktree isolation — inside a git repo, each node runs in its own
git worktreeunder<workdir>/.sqrlly/, reused across retries so prompt nodes can iterate on prior files. - Checkpointed state — runs persist to
<workdir>/.sqrlly-checkpoint.db(LangGraphAsyncSqliteSaver);--resumecontinues from the last checkpoint. - Recursive subgraphs — a
.yamlURL runs another sqrlly workflow; the same file works standalone or as a subgraph reference.
Backends and presets
LLM and script execution is configured by presets under settings.presets — named bundles referenced by a node's params.preset. Exactly one LLM preset is marked default: true:
settings:
presets:
default:
transport: acp
provider: anthropic
model: sonnet
default: true
If settings.presets is omitted, sqrlly auto-detects by checking for
npx on PATH and synthesizing an ACP preset against sonnet. The
adapter inherits the local claude CLI session, so no API keys are
required — just npm i -g @zed-industries/claude-code-acp.
Full reference (including CommandPreset for custom script interpreters): docs/schema-reference.md.
CLI
| Command | Purpose |
|---|---|
sqrlly validate <config> |
Compile the workflow; report node count and lint warnings. |
sqrlly run <config> |
Execute the workflow. |
sqrlly graph <config> |
Print the topology as a Mermaid diagram. |
sqrlly view <config> |
Render a self-contained interactive HTML viewer. |
run flags:
--workdir / -w <dir>— working directory (default.).--dry-run— trace topology without executing.--preset / -p <name>— force a named preset as the default.--resume— continue from the last checkpoint.--log <path>— write a JSONL event log.
Examples
Each example directory ships a checked-in view.html (authoring view) and, where the run is deterministic, a view-debug.html from a captured log.
| Workflow | What it shows |
|---|---|
examples/jokes/ |
Minimal: prompt + script gate + select. Start here. |
examples/route_classify/ |
Inline route: case ladder over structured state. |
examples/pipeline_style/ |
route: { goto: <next> } forward-edge authoring; a linear pipeline. |
examples/absurd-paper/ |
13-node multi-stage pipeline with subgraphs and per-item subgraph fan-out. |
examples/wave_planner/ |
Wave-driven dynamic-task pattern — goto: loop-back to a fan-out parent. |
Documentation
- docs/schema-reference.md — every Settings / Node / Execute / preset / route / evaluation field, the URL dispatch table, and the route-predicate namespace.
- TECHNICAL.md — three-layer architecture, pipeline flow, state model, key invariants.
- SKILLS.md — agent skill doc: instructions for an AI coding agent authoring and running sqrlly workflows.
Contributing
- Three-layer split —
schema/(Pydantic models) →compile/(YAML → LangGraph) →runtime/(executors, backends). Layer rules enforced at CI time by an AST import check. - No mocks of external systems — tests run real subprocesses, real
git worktree, and real backends. - See TECHNICAL.md for architecture and contributor reading order.
uv run pytest tests/ --ignore=tests/acp # ~840 tests
uv run pytest tests/acp # ACP integration (needs the npm adapter)
License
Apache-2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 sqrlly-0.2.0.tar.gz.
File metadata
- Download URL: sqrlly-0.2.0.tar.gz
- Upload date:
- Size: 450.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a50bff9a9dafee9c72dd04170944acd43dfedc48923eade3c7900212cbfd853c
|
|
| MD5 |
82f10a421471ce867f807e84175981a6
|
|
| BLAKE2b-256 |
2ca2b734e5ac29566274e224c04dd81edd93298c7809fa1e6ced42d43c9cc9f9
|
Provenance
The following attestation bundles were made for sqrlly-0.2.0.tar.gz:
Publisher:
publish.yml on christopherseaman/sqrlly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sqrlly-0.2.0.tar.gz -
Subject digest:
a50bff9a9dafee9c72dd04170944acd43dfedc48923eade3c7900212cbfd853c - Sigstore transparency entry: 1647107733
- Sigstore integration time:
-
Permalink:
christopherseaman/sqrlly@621d30eac07549b6d84894528e61f96c1d706215 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/christopherseaman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@621d30eac07549b6d84894528e61f96c1d706215 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sqrlly-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sqrlly-0.2.0-py3-none-any.whl
- Upload date:
- Size: 104.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39103fcd8fc3853eae632db168e2a24cd6fc44cdc728b11969f1c74123ad336b
|
|
| MD5 |
514fef0756f478a79b356efa6da96f3b
|
|
| BLAKE2b-256 |
8abd92377ea90975cdd10baa18eeae4c50815c0e5be04179d5dbbbc6b7f3fcc7
|
Provenance
The following attestation bundles were made for sqrlly-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on christopherseaman/sqrlly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sqrlly-0.2.0-py3-none-any.whl -
Subject digest:
39103fcd8fc3853eae632db168e2a24cd6fc44cdc728b11969f1c74123ad336b - Sigstore transparency entry: 1647107889
- Sigstore integration time:
-
Permalink:
christopherseaman/sqrlly@621d30eac07549b6d84894528e61f96c1d706215 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/christopherseaman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@621d30eac07549b6d84894528e61f96c1d706215 -
Trigger Event:
push
-
Statement type: