Skip to main content

hitlwright

A typed, versioned, auditable human-in-the-loop approval contract.

When an agent or a workflow must pause for a human decision, hitlwright writes a typed request and reads a typed decision — both following a versioned JSON Schema (hitl-request-v1), stored as append-only JSONL so the whole approval trail is auditable and nothing is overwritten. Zero dependencies.

from pathlib import Path
from hitlwright import write_request, read_decision, write_decision, pending_request

run = Path("runs/42")
req_id = write_request(run, step_id="publish", action="publish",
                       allow=["approve", "reject"], title="Approve publish")

# the run pauses; is a human still owed a decision?
if pending_request(run):
    ...  # wait / notify

# a human (or another process) responds:
write_decision(run, req_id, response="approve", responder_id="user:ana", comment="ok")

decision = read_decision(run)   # {"response": "approve", ...} or None

Or from the shell:

$ hitlwright request runs/42 --step publish --action publish
hitl_1b2c...
$ hitlwright decide runs/42 hitl_1b2c... --response approve --by user:ana
$ hitlwright decision runs/42        # the latest decision as JSON

Why it exists

Most frameworks offer a generic "interrupt" and leave the rest to you: no typed request, no versioned contract, no audit trail, and no language-neutral way for a different system to answer. hitlwright is the opposite:

Property hitlwright
Typed every request/decision follows hitl-request-v1 (shipped, schema_path())
Versioned the schema id is in every record; v2 can coexist
Auditable append-only JSONL — the full history, nothing overwritten
Two-sided & language-neutral just two JSONL files; any producer writes requests, any responder writes decisions (Python, Node, a CLI, a web UI)
Resumable read_decision / pending_request after a pause — survives a restart
Zero-dep pure stdlib; the schema is validated in your tests, not at runtime

The producer and the responder never call each other — they share two files and one schema. That is what makes it survive restarts and cross language boundaries.

API

  • write_request(run_dir, *, step_id, action=None, allow=None, title=None, ...) -> str
  • read_decision(run_dir) -> dict | None — the latest valid decision (last wins)
  • write_decision(run_dir, request_id, *, response, responder_id="cli", comment=None) -> dict
  • pending_request(run_dir) -> dict | None — latest request with no decision yet
  • latest_request(run_dir) -> dict | None
  • build_request(...) / build_decision(...) — construct & validate shape without IO
  • schema_path() -> Path — the shipped hitl-request-v1 JSON Schema

How it compares

See POSITIONING.md for the evidence-based comparison with LangGraph interrupts, Temporal signals, Inngest waitForEvent, and Humanlayer — and the honest limits (polling-based, no built-in notifications or auth).

Install

pip install hitlwright

MIT licensed. Part of the network-agents-setup ecosystem; extracted from its governed runner so any project can gate on typed human approval.

Metadata

Release files for hitlwright 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hitlwright 0.1.0
File Size Uploaded
hitlwright-0.1.0.tar.gz 11.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hitlwright 0.1.0
File Interpreter ABI Platform
hitlwright-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.7 kB

Release files / hitlwright-0.1.0.tar.gz

Download URL hitlwright-0.1.0.tar.gz
Size 11.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c15d1874128805c52c2b3e44e2626e96bf23b9953719027930d8eb22cfb6c082
BLAKE2b-256 checksum
How to use checksums
bbe081bdfffa8b8bf54f96ce9afc6023a2cd0bd57a6a76af135dfd39917513c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 12, 2026.

Transparency log

Release files / hitlwright-0.1.0-py3-none-any.whl

Download URL hitlwright-0.1.0-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f9ee88d4d31a85460f0a8dc0400e43875630c59f5a02e31c811a9a74fc2bc15b
BLAKE2b-256 checksum
How to use checksums
19f12252a5092c04fdb93a5f6094739511c3f6572fa5a41fd2f3a54a61372dfe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page