Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

lockstepd

CI

Status: experimental · v0.2.0-beta. Kernfunktionen sind durch 187 Tests abgedeckt (185 in der Standard-Suite, grün ohne Keys und Netz; 2 key-gated Live-Smoke-Tests), das Format ist stabil (v1) — die API darf sich vor 1.0 aber noch ändern.

Deterministischer Replay-Debugger für Agent-Läufe. Zeichne jeden LLM-Aufruf, jedes Tool-Ergebnis, jede Uhr- und Zufalls-Lesung in eine manipulationssichere Datei auf. Spiele den Lauf offline bit-exakt wieder — prüfbar per Hash-Kette. Verzweige an beliebiger Stelle und lass lockstepd bisect automatisch den Schritt finden, an dem alles gekippt ist.

Änderungen: CHANGELOG.md.


Das Problem

Agenten sind nicht reproduzierbar: erneutes Laufen lässt das Modell anders samplen, Tools liefern andere Daten, und der Bug ist weg, bevor du ihn siehst. Observability-Tools zeigen dir Traces — aber ein Trace ist Protokoll, kein Debugger: du kannst nicht anhalten, einen Schritt ändern und von dort neu laufen lassen. Genau diese Lücke füllt lockstepd: Aufzeichnung wird zur ausführbaren Wahrheit, gegen die du Code ändern, verzweigen und Ursachen eingrenzen kannst.

Demo-Session

$ make demo

──── 1 · RECORD ────
recorded examples/data/demo.lockstep.gz  events=214 steps=26 trace=c2a74eb72004be11…

──── 2 · REPLAY (offline, kein Netz) ────
replay identical trace=c2a74eb72004be11…

──── 3 · VERIFY ×20 (Determinismus-Nachweis) ────
identical replays: 20/20

──── 4 · SCRUB ────
scrubbed 96 events -> clean.lockstep.gz (remaining suspicious: 0)
clean-check: clean rc=0

──── 6 · BISECT (eingebauter Fehler bei tools:10 finden) ────
┌─────────── bisect result ───────────┐
│ field           │ value             │
│ culprit step    │ 22  (= tools:10)  │
│ first bad fork  │ 23                │
│ probes / budget │ 7 / 7             │
│ total steps     │ 52                │
└─────────────────────────────────────┘

Der Bisect-Lauf oben ist echt: ein 25-Schritt-Demo-Agent mit einem Gift-Wert im Tool-Ergebnis von Schritt 10 — gefunden in 7 Proben (Budget ⌈log₂(52)⌉+2).

Installation

uv add lockstepd            # Kern (msgspec) + CLI (typer/rich)
uv add "lockstepd[httpx]"   # Transport-Instrumentierung (empfohlen)
pip install "lockstepd[anthropic]"   # oder [openai] – optional, SDK-seitige Helfer

Python ≥ 3.12. CI-fähig ohne API-Schlüssel und ohne Netzwerk (Fake-Backend inklusive).

Schnellstart

Variante A — CLI (Subprozess, empfohlen):

lockstepd record run.lockstep.gz -- examples/demo_agent.py --steps 12
lockstepd replay run.lockstep.gz -- examples/demo_agent.py --steps 12   # gleiche Syntax
lockstepd verify run.lockstep.gz --times 100 -- examples/demo_agent.py --steps 12
lockstepd inspect run.lockstep.gz

Der ---Fallback über LOCKSTEP_COMMAND (JSON) funktioniert weiterhin, ist aber nicht mehr nötig.

Dein Agent braucht dafür genau zwei Zeilen:

from lockstepd.runtime import auto_session

session = auto_session()          # liest LOCKSTEP_RECORD / LOCKSTEP_REPLAY / LOCKSTEP_FORK_*
with session:
    ...  # normaler Agentencode; httpx-Clients werden automatisch instrumentiert

Variante B — In-Process-API:

import httpx
from lockstepd.session import Session
from lockstepd.integrations.httpx_transport import LockstepTransport
from lockstepd.patchers.concurrency import OrderedExecutor

with Session.record("run.lockstep.gz") as s:
    client = httpx.Client(base_url="https://api.provider.test/v1",
                          transport=LockstepTransport(s))          # zeichnet auf
    # ... LLM-Aufrufe über client, Tools über OrderedExecutor ...
    s.final_state.update({"answer": answer})
print(s.trace_hash_hex)

Replay desselben Codes:

with Session.replay("run.lockstep.gz") as s:
    client = httpx.Client(..., transport=LockstepTransport(s))     # serviert vom Band
    ...
assert s.trace_hash_hex == recorded_hash                          # bit-exakt

Fork & Bisect siehe lockstepd fork --help / lockstepd bisect --help sowie examples/check_failed.py.

Was aufgezeichnet wird

LLM-Anfragen/-Antworten inkl. Streaming-Chunks mit relativen Ankunftsabständen, Tool-Aufrufe mit Abschlussreihenfolge (completion_index), Uhren (time, datetime), Zufall (random, uuid4, os.urandom), gelesene Umgebungsvariablen (redaktiert), optionale FS-Zugriffe, Retries und Fehler — alles in einer gzip-JJSONL-Datei mit BLAKE2b-Hash-Kette. Details: FORMAT.md.

CLI

Befehl Zweck
lockstepd record OUT -- script.py args… Lauf aufzeichnen
lockstepd replay TAPE -- script.py args… offline wiederabspielen; Divergenz ⇒ Fehler mit Diff
lockstepd verify TAPE --times N -- script.py … Integrität + N-facher Identitätsnachweis
lockstepd inspect TAPE interaktiver Trace-Browser (rich)
lockstepd diff A B erste Divergenz + Unified-Diff + Kind-Statistik
lockstepd fork TAPE --at N --out F -- script.py … Prefix abspielen, Suffix live
lockstepd bisect BAD --predicate check.py -- script.py … Ursachen-Schritt per Binärsuche
lockstepd scrub TAPE -o CLEAN / --check Secrets entfernen / nachweisen
lockstepd export TAPE -o otlp.json OTLP/JSON-Spans

Echte SDKs ohne API-Key

Die echten anthropic-/openai-Clients laufen keyless gegen das Fake-Backend (lockstepd.testing.SdkFakeBackend, echte Wire-Formate inkl. SSE). Integrationstests beweisen Record → Replay bit-exakt durch den genuine SDK-Pfad — Sync und Async. Instrumentiert werden beide HTTP-Stapel: httpx und der httpx2-Fork aktueller SDKs.

Live-Smoke (opt-in, nie in CI)

Ein minimaler Record→Replay-Zyklus gegen die echten APIs liegt unter tests/test_live_smoke.py (Marker live). Er läuft nur, wenn LOCKSTEP_LIVE_SMOKE=1 und der jeweilige Provider-Key gesetzt ist — sonst Skip. Die Standard-Suite und CI schließen ihn explizit aus:

LOCKSTEP_LIVE_SMOKE=1 pytest -m live   # kostet echte Tokens; bewusst manuell

Garantien — und wo sie enden

verify --times N beweist Wiederholbarkeit empirisch; die Hash-Kette macht jede Manipulation und jede Divergenz sofort sichtbar (kryptografisch, nicht heuristisch).

Hook-Striktheit: Zeit-, Zufalls- und Env-Lesungen laufen über eigene sequentielle Queues, getrennt vom strukturellen Ereignis-Cursor. Im Standard (strict_hooks=True, Subprozess- Betrieb) ist jede Abweichung in diesen Strömen ein harter Fehler. Mit strict_hooks=False fällt lockstepd stattdessen auf reale Werte zurück und notiert die Abweichung transparent in session.soft_divergences — nützlich für In-Process-Replays, bei denen Bibliotheksräuschen (pytest-interne UUIDs, Cookie-Jar-Uhren) keine harte Divergenz wert sein soll. Die Liste macht jeden weichen Fallback sichtbar statt ihn zu verschweigen.

Was nicht reproduzierbar ist — von Set-Iteration bis C-Level-getenv — steht schonungslos in LIMITS.md. Ehrlicher Vergleich zu bestehenden Werkzeugen: PRIOR_ART.md. Aufzeichnungsformat: FORMAT.md. Entscheidungen: DECISIONS.md, Status: PROGRESS.md.

Entwicklung

make check   # ruff + ruff format --check + mypy --strict + pytest (185 Tests, ohne Keys/Netz)
make bench   # 10k-Ereignis-Benchmark
make demo    # obige Session

Lizenz: MIT.

Metadata

Release files for lockstepd 0.2.0b0

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

Source distribution (sdist)

Source distribution for lockstepd 0.2.0b0
File Size Uploaded
lockstepd-0.2.0b0.tar.gz 163.7 kB Details

Built distribution (wheel)

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

Total release size: 216.7 kB

Release files / lockstepd-0.2.0b0.tar.gz

Download URL lockstepd-0.2.0b0.tar.gz
Size 163.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0f9cb9e3671c07bef3e62bdeb004e828d0cba6dd0c6776532caf2e58cbab82c7
BLAKE2b-256 checksum
How to use checksums
41d2f17930f4fd2110be72ed2782c7d0b333aec95b0e992a17f633efc0d53ac0
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 Aug 26, 2026.

Transparency log

Release files / lockstepd-0.2.0b0-py3-none-any.whl

Download URL lockstepd-0.2.0b0-py3-none-any.whl
Size 53.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0cc72562ab81f841200495e85a9e306494c3d051f4f5c1354b46abe9a5b7709a
BLAKE2b-256 checksum
How to use checksums
f53255412fdf4480654ada614729da11e15fa8d590db06deda19dd2b720ec0fa
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 Aug 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0b0 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