buildwright
The craftsman who builds per the spec — one model per agent: mechanical steps go to the local model (cheap, fast), important decisions to the remote one (strong). The role→model mapping is configuration, not code — switching models touches zero lines of pipeline.
Install
uv tool install buildwright # once published to PyPI
# or for development:
uv sync
Division of roles (one tool, one job)
| Piece | Role | Where it lives |
|---|---|---|
| LangGraph | the ORDER of the steps (graph, state, retries) | graph.py |
| PydanticAI | EACH STEP (agent with structured output) | agents.py |
| LiteLLM | WHO serves the model (optional proxy, fallbacks) | litellm/config.yaml |
| Langfuse | WHETHER IT WORKED (traces, scores) | observability.py |
The pipeline
START → plan (local) → execute (remote) → review (local) → END
Plan struct. final answer Review struct.
Each node is a PydanticAI agent; the model is decided by the role in
Settings (BW_ROLE_*), resolved against the models.yaml registry.
Quickstart
uv sync
cp .env.example .env # adjust BW_ROLE_* and keys
uv run buildwright models # list local and remote models
uv run buildwright roles # role -> model mapping
uv run buildwright ask "write a snake game in python with pygame"
With no endpoints available, ask fails naming the exact model and the missing
env var.
Local and remote models
The whole registry speaks OpenAI-compatible (models.yaml):
- local/qwen3 → Ollama at
localhost:11434/v1 - local/llamacpp →
llama-serveratlocalhost:8080/v1(your GGUF) - remote/gpt-4o-mini, gpt-4o → OpenAI (key via
OPENAI_API_KEY) - remote/claude-sonnet → Anthropic's OpenAI-compat layer
- remote/zai-glm-flash → Z.ai / Zhipu GLM (key via
ZAI_API_KEY) — small and cheap; a coding plan key needs the/api/coding/paas/v4base_url, otherwise inference fails with error 1113 while/modelsstill lists fine - litellm/* → via the LiteLLM proxy (see
docker-compose.yml)
Registry resolution: BW_MODELS_FILE > project-local ./models.yaml > the
models.yaml bundled with the package. Adding a model = adding 5 lines.
Reassigning one to an agent = changing a BW_ROLE_* in .env.
Optional full stack (LiteLLM + Langfuse + Ollama)
With Docker, docker compose up -d brings up LiteLLM (routing/fallbacks),
Langfuse (traces) and Ollama. Langfuse keys show up in its admin UI; copy them
to .env and tracing turns itself on (without keys, the tracer is a no-op).
Publishing to PyPI
Trusted publishing — no API tokens:
- Create
github.com/jordimarsal/buildwrightand pushmain. - On pypi.org: Add a pending publisher → owner
jordimarsal, repobuildwright, workflowrelease.yml, environmentpypi. git tag v0.1.0 && git push --tags→ the workflow runsuv buildand publishes.
Harness runtime
In a project initialized with harness:
buildwright harness status # board + planned routing (read-only)
buildwright harness run # the FULL feature loop (see below)
buildwright harness run --feature f3_dashboard # specific feature
buildwright harness approve "lgtm" # resume a parked gate: approve
buildwright harness reject "add tests for R1" # resume a parked gate: reject
-
statusparses and schema-validatesharness/feature_list.json(protocol v1) and shows the board plus which model each role would use. -
runis the full feature loop (phase 2) — the graph is the leader. One feature runs batch after batch inside an isolated git worktree (.buildwright/, locally excluded), each batch being the next pending slice oftasks.md(capped at 4, harness discipline):implement_batch → verify → init_gate → advance_batch → reviewer → traceability_gate → audit_gate → completion_gate → finalize- verify re-reads
tasks.mdand diffs the worktree — a chat claim is not evidence. Nothing written = a stall: the same batch is re-dispatched withNothing was written: …; two stalls in a row start a fresh agent session; a batch that makes no progress across 4 dispatches is parked. - hard gates run the scripts this protocol already has (
init.shmust end[OK],check-traceability.py, andaudit-security.sh/bench.shfor standard/strict). A failing gate feeds its log back to the implementer and loops back; 3 consecutive failures park the feature. - the reviewer issues a structured
APPROVED/CHANGES_REQUESTEDverdict written toharness/progress/review_<name>.md; two rejections in a row park.
All cycle counters (
max_batch_attempts,max_gate_cycles,max_review_rounds) count consecutive failures and reset on any progress (a completed batch resets the batch/gate counters, anAPPROVEDverdict resetsreview_rounds). So a humanrejectat the completion gate that sends the feature back to the implementer can loop as many times as you ask it to — it never trips a cap that was counting an earlier, unrelated streak.- completion_gate is a human gate: the loop
interrupt()s and parks, with state persisted in a sqlite checkpointer (.buildwright/checkpoints.sqlite) so it survives restarts.approvemerges to main, writesharness/specs/<name>/APPROVAL, flips status todone, and appends theretro:line tohistory.md;rejectturns the feature back to the implementer with your comments. On approval the feature's worktree is removed and its merged branch deleted — a re-run starts fresh offmain.
- verify re-reads
-
Command allowlist defaults are built in; extend or retime via an optional project-owned
harness/runtime.yaml(alsomax_batch_attempts,max_gate_cycles,max_review_rounds):
extra_allowed_commands:
- terraform plan
command_timeout_s: 300
max_gate_cycles: 3
The unattended multi-phase design lives in
docs/specs/2026-10-27-harness-runtime-design.md.
Tests
uv run pytest # offline: pydantic-ai's TestModel, zero network
Anti-mess rules
- Everything speaks OpenAI protocol; PydanticAI never imports litellm.
- One agent = one node = one job. No agents inside agents.
- Tracing registered exactly once (
observability.py); never scattered. - Offline evals in CI rule; Langfuse is production monitoring.
- Each piece joins when it has a real trigger (fallbacks→LiteLLM, non-linear flow→LangGraph is already in).
Changelog
Release history lives in CHANGELOG.md.
Metadata
Release files for buildwright 0.4.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| buildwright-0.4.3.tar.gz | 207.5 kB | With provenance | Details for buildwright-0.4.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| buildwright-0.4.3-py3-none-any.whl | Python 3 | none | any | Details for buildwright-0.4.3-py3-none-any.whl |
Total release size: 241.7 kB
Release files / buildwright-0.4.3.tar.gz
| Download URL | buildwright-0.4.3.tar.gz |
|---|---|
| Size | 207.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e8a49165f8e4a18d83d85d6bae7ba66066008a7e0a66ca7104ec9a2dfa918f09
|
|
BLAKE2b-256 checksum How to use checksums |
59b9ab46f081f01829b6255c1ff7ebe499967686d5b9c719fedcba13bf15bb39
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logRelease files / buildwright-0.4.3-py3-none-any.whl
| Download URL | buildwright-0.4.3-py3-none-any.whl |
|---|---|
| Size | 34.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
971a0e198ea6261991aa7f7b973baf2e46aefe52c41199d9e49005dd0a00d4b8
|
|
BLAKE2b-256 checksum How to use checksums |
fc219f4b906549666c36402b51ad867620de9d5fba3900b8cd0435a627e669e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logSecurity for buildwright 0.4.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for buildwright-0.4.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.