Jigar Gor

Work / Case study

Stateful Indecision

Long-running agents are hard to audit after the fact. This runtime records every decision as a tamper-evident event and limits actions up front.

Role
Solo: design, runtime, tooling, observability
Period
May 2026
Status
Complete
Stack
Python, Pydantic, Docker, uv, JSONL ledgers, SQLite, Parquet, Grafana, Anthropic, AWS S3
Diagram of one agent decision: five phases from state snapshot to ledger commit, an action mask applied before sampling, a tool allowlist applied at execution, and the committed event appended to a hash-chained ledger.

At a glance

  • v1.0.0 pipeline complete; the repository reports 417+ passing tests across contracts, safety, memory, observability, and formalism.
  • Three agents completed alpha runs: 1,632 public ledger events and 118 notebook entries, per the repository README.
  • No hosted demo. It is a CLI plus ledger files, by design.

Challenge

When an agent runs for hundreds of decisions, “what did it actually do, and why” becomes the hard question. Logs are easy to lose, easy to edit, and rarely structured enough to check.

Stateful Indecision is a single-agent research runtime built so the record is the primary artifact: every decision is an event on an append-only ledger that can be verified end to end, and the set of things an agent is allowed to do is fixed before it chooses.

Approach

Each decision moves through five ordered phases, recorded on the event itself: state_snapshot, policy_proposal, policy_sample, executor_run, ledger_commit.

  • Ledgers. Separate hash-chained ledgers hold public events, commons, evaluation signals, and each agent’s private notebook. A verifier walks the chain, and a CLI inspects it. Appends are file-locked and fsynced, so a termination between decisions loses nothing.
  • Constraints before choice. Action masks (blocked_leaf_actions) remove actions before sampling, and a run-config tool allowlist is enforced at the executor, which writes an explicit marker when it blocks something.
  • Typed everything. More than thirty Pydantic payload models validate events, and JSON schemas are exported from them.
  • Memory with provenance. Peer context, forum digests, and retrieval are exposed to the agent through configurable caps, and notebooks are consolidated into rolling summaries.
  • Operations. A multi-stage Dockerfile, optional S3 offload with a SIGTERM-aware shutdown sync for spot instances, and exports to SQLite, Parquet, and Grafana dashboards.

The design follows the Auton framing for separating a cognitive blueprint from a runtime engine, and the README maps each concept to the file that implements it.

Role

Solo. I wrote the runtime, the schemas, the safety layer, the operational tooling, and the tests.

Tradeoffs

  • Auditability over throughput. Every decision pays for a hash, a lock, and an fsync. In exchange, the record can be checked.
  • Frozen policy. Sampling is vocabulary-weighted and uniform under masks. A state-conditioned policy is deferred, so the runtime proves the substrate and does not yet claim smart behavior.
  • Warn, not enforce. The verifier runs in warn mode by default, pending operator acceptance, and experimental reasoning events stay off by default.
  • No interface. Everything is a CLI plus ledger files. That kept scope on the substrate and means there is nothing to click.

Results

Numbers below come from the repository README at the time of writing.

  • 417+ tests across contracts, safety, memory, observability, and formalism.
  • Three agents (biochem-lead, psych-lead, sweng-lead) completed alpha runs, producing 1,632 public ledger events and 118 notebook entries across five agent namespaces.
  • The beta ecosystem holds 3,160 public events across three agents.

Lessons

  • A schema and a verifier turn “trust the log” into “check the log”. The checking tools were as valuable as the runtime.
  • Constraints are cheaper to reason about when they act before the model chooses than when they filter afterward.