StateM: Stateful control for long-horizon agents StateM, a stateful control system for long-horizon agents, ranked #1 on Hugging Face Daily Papers on 2026-08-18 and released a runbook and reproducibility package for DeepSeek-V4-Flash, achieving 88.8% descriptive accuracy (395/445 trials) on Terminal-Bench 2.1. The tool turns agent workflows into inspectable graphs of states, transitions, and executable checks, moving procedural state out of model context into a lightweight, versioned runbook with zero runtime dependencies beyond Python 3.11. 2026-08-18 🤗 StateM ranked 1 on Hugging Face Daily Papers https://huggingface.co/papers/date/2026-08-18 . 2026-08-18 🔥 We released the DeepSeek-V4-Flash StateM runbook and reproducibility release https://github.com/henryqin1997/statem/releases/tag/deepseek-policy9-tb21-artifacts-20260818 , reaching 88.8% descriptive accuracy on Terminal-Bench 2.1 395/445 trials; 88.76% unrounded . Everyone can try StateM turns an agent workflow into an inspectable graph of states, transitions, and executable checks. It keeps planning, execution, verification, repair, and handoff from collapsing into one long prompt. Long agent runs often fail for ordinary reasons: the original goal fades from attention, progress lives only in chat history, verification is postponed, or a new session cannot reconstruct what happened. StateM moves that procedural state out of the model context and into a lightweight, versioned runbook. php prepare - execute - verify - handoff ^ | +-- repair-+ At every state, the agent can ask: - What should I do now? - Which transitions are legal? - What evidence is required before I move? - What happened earlier in this run? The answer is stored in files and runtime history rather than relying on the model to remember everything. | Approach | Remembers phase | Blocks invalid transitions | Supports repair loops | Survives context refresh | Agent-editable | |---|---|---|---|---|---| | Prompt-only workflow | Partial | No | Informal | No | Yes | | TODO list | Partial | No | Informal | Yes | Yes | | CI pipeline | Yes | Yes | Limited | Yes | Usually no | | General workflow engine | Yes | Yes | Yes | Yes | Rarely | StateM | Yes | Yes | Yes | Yes | Yes | StateM is deliberately smaller than a workflow engine. It is a state-aware runbook that an agent can read, author, inspect, and repair from the command line. Explicit phase boundaries — model planning, implementation, review, recovery, and handoff as real states. Executable transition gates — use checklists, commands, predicates, manual approval, and LLM review before leaving a state. Dynamic checks — let an agent register task-specific checks for the current state entry without mutating the shared runbook. Durable runtime history — persist the current node, transitions, hook results, evidence, timestamps, and spec identity. Context lifecycle support — generate safe resume and compaction prompts for long cyclic runs. Zero runtime dependencies — the core package requires only Python 3.11 or newer. Clone the repository and install it in editable mode: git clone https://github.com/henryqin1997/statem.git cd statem python3 -m pip install -e . Check the CLI: statem --help Validate and start the included coding-agent runbook: statem validate examples/coding-agent.yaml statem start examples/coding-agent.yaml --run-id demo statem cur --run-id demo statem next --run-id demo Move only when the current state's checks pass: statem goto plan --run-id demo statem history --run-id demo Runtime data defaults to .statem/ . For durable machine-local state that survives disposable checkouts, place it outside the repository: export STATEM STATE DIR="$HOME/.local/state/statem/my-project" statem start examples/coding-agent.yaml --run-id demo name: implementation-loop initial: plan nodes: plan: prompt: | Read the task and write a concrete implementation plan. before transfer: type: checklist items: - Scope and constraints are recorded - Verification steps are defined execute: prompt: | Implement the plan and keep the change scoped. before transfer: - type: command run: "python3 -m pytest -q" - type: checklist items: - Relevant tests pass - Unrelated files were not changed handoff: prompt: | Summarize the change, verification, and remaining risks. edges: - from: plan to: execute condition: The plan is ready. - from: execute to: plan condition: Verification found a fixable gap. - from: execute to: handoff condition: The implementation and verification are complete. Save it as runbook.yaml , then run: statem validate runbook.yaml statem start runbook.yaml --run-id my-run statem cur --run-id my-run StateM separates the shared workflow definition from per-run execution state: | Layer | Contents | Commit to git? | |---|---|---| | Static runbook | Nodes, edges, prompts, hooks, gates | Yes | | Runtime state | Current node, history, results, timestamps | No | | Dynamic checks | Task-specific current-entry verification | No | | Durable project notes | Plans, decisions, progress, artifacts | Usually yes | A transition is a transaction: - Resolve the requested outgoing edge. - Run the current node's before transfer checks. - Load and run current-entry dynamic checks. - Evaluate the edge's condition . - Run the current node's out hook and the edge hook . - Record the transition, create a new target entry, and run the target node's in hook . If a blocking check fails, the agent remains in the current state with the failure recorded for repair. | Field | Purpose | |---|---| name | Human-readable graph name | initial | Node entered when a new run starts | nodes | Named state definitions | edges | Directed transitions between states | | Field | When it runs | Typical use | |---|---|---| prompt / pre request | While the node is active | State-local instructions | in hook | After entering | Load context or initialize evidence | before transfer | Before leaving | Block on required verification | dynamic before transfer | Before leaving | Run task-specific current-entry checks | out hook | Before the transition commits | Persist progress or handoff notes | | Field | Purpose | |---|---| from / to | Source and target nodes | condition | Transition-specific blocking gate | hook | Prepare-transfer work after exit gates pass | max attempts | Optional positive retry ceiling for this edge and source-node entry | Leaving out max attempts preserves the default unbounded retry behavior. When configured, each real goto consumes one attempt; blocked checks count, and a fresh source-node entry receives a fresh budget. | Type | Behavior | |---|---| message | Display non-blocking guidance | manual | Ask for explicit confirmation | checklist | Confirm a set of completion conditions | command | Run a shell command and use its exit code | predicate | Inspect files declaratively | llm review | Delegate a structured review to an external command/model | Checks can be configured with fields such as blocking , on failure , timeout , and cwd . Prefer checks that exercise the same interface the task promises to its eventual consumer. | Command | Purpose | |---|---| statem start SPEC | Create or resume a run | statem cur | Show the current node and its prompt | statem state | Show the full graph | statem ls NODE | Inspect one node | statem next | Show outgoing transitions | statem goto TARGET | Attempt a checked transition | statem save | Persist state and run the current out hook | statem history | Inspect prior transitions and results | statem prompt | Generate a durable post-clear resume prompt | statem compact-prompt | Generate a safe compaction prompt | statem validate SPEC | Validate graph structure and references | statem validate SPEC --strict | Also reject unknown or misplaced runbook keywords | statem dynamic ... | Manage current-entry dynamic checks | Most commands accept --run-id , --state-dir , and --json for explicit run selection, isolated state, and machine-readable output. Static gates cover invariants known when the runbook is authored. Dynamic checks cover verification discovered during the concrete task—for example, a regression test for the exact bug just fixed. statem dynamic path --run-id demo statem dynamic write checks.json --run-id demo --agent-id implementer statem dynamic list --run-id demo --json Dynamic checks are scoped to the current node entry. StateM records who registered them and runs them before the transition is allowed to commit. Long runs should keep durable facts in project files and use the model context for the current decision. StateM supports that split with: statem history for the durable transition record; statem prompt for restoring attention after a cleared session; statem compact-prompt for safe compaction inside cyclic runbooks;- explicit recovery or session-refresh nodes when another loop should continue; - spec hashes and run identifiers to detect or deliberately rebind edited runbooks. Runbooks belong in version control. Runtime state does not. Add .statem/ to .gitignore when using the default local state directory. StateM works without a host hook. To keep an agent moving after it would otherwise end its turn, register the optional Stop hook as a till-finish mode. When an active run is still on a non-terminal node with outgoing transitions, the hook returns a continuation prompt that tells the agent to inspect StateM and continue from the durable state. - Start the run normally with statem start . - For Codex, merge into codex-stop-autoloop.hooks.json .codex/hooks.json or ~/.codex/hooks.json . - For Claude Code, merge into a project or user settings file. claude-stop-autoloop.settings.json - If the hook runs outside this repository, replace its command with the absolute path to integrations/hooks/statem stop hook.py . Set STATEM STATE DIR too when the run does not use the default .statem/ directory. The hook does not advance StateM by itself, bypass transition checks, run /clear , or run /compact . It allows the host to stop when no active run exists, the current state is terminal, or the graph has no outgoing transition. See the complete setup and behavior reference /henryqin1997/statem/blob/main/examples/hooks/README.md . | Host / environment | Entry point | |---|---| | Codex | plugins/statem/skills/statem/SKILL.md | integrations/claude/statem/ Executable /henryqin1997/statem/blob/main/examples/terminal-bench-2.1-git-webserver-deploy-family.md git webserver deploy family guide examples/hooks/README.md StateM's core remains host-agnostic: any agent that can run shell commands can query and advance a runbook. | Example | What it demonstrates | |---|---| coding-agent.yaml | · /henryqin1997/statem/blob/main/examples/terminal-bench-2.1-git-webserver-deploy-family.yaml git webserver deploy family reproduction guide /henryqin1997/statem/blob/main/examples/terminal-bench-2.1-git-webserver-deploy-family.md DeepSeek server-readiness policy extract /henryqin1997/statem/blob/main/examples/terminal-bench-2.1-deepseek-server-readiness-subset.yaml · guide /henryqin1997/statem/blob/main/examples/terminal-bench-2.1-deepseek-server-readiness-subset.md For advanced guidance on evidence receipts, consumer-facing checks, adaptive verifier plans, freshness, recovery, and benchmark integrity, read the verification guide /henryqin1997/statem/blob/main/docs/verification-guide.md . The accompanying paper evaluates StateM as an execution harness on Terminal-Bench 2.1. These are system-level results, not claims about a new base model: | Configuration | Result | Operating condition | |---|---|---| | GPT-5.5 xhigh + StateM | 92.1% | 89 tasks, 445 trials; 88/89 five-trial coverage | | GPT-5.6 Sol xhigh + frozen StateM profile | 95.28% raw | 424/445 public-submission trials; 89/89 coverage | | DeepSeek-V4-Flash + adapted StateM profile | 88.09% | 392/445 under standard timeouts | | DeepSeek-V4-Flash + adapted StateM profile | 88.76% descriptive | 395/445, replacing one task with disclosed extended-timeout trials | The 95.28% value is the raw pre-adjudication public-submission score. The DeepSeek descriptive aggregate is reported separately from the standard-timeout result. See the paper https://henryqin1997.github.io/statem/statem-paper.pdf for experimental protocol, references, costs, and limitations. The policy-v9 artifact release https://github.com/henryqin1997/statem/releases/tag/deepseek-policy9-tb21-artifacts-20260818 provides: - the exact 54-file task-injected source snapshot https://github.com/henryqin1997/statem/releases/download/deepseek-policy9-tb21-artifacts-20260818/statem-deepseek-v4-flash-policy9-tb21-source-exact-20260818.tar.gz , verified against the manifest stored with every trial; - a runnable reproduction kit https://github.com/henryqin1997/statem/releases/download/deepseek-policy9-tb21-artifacts-20260818/statem-deepseek-v4-flash-policy9-tb21-reproduction-kit-20260818.tar.gz with the host-side bridge, frozen control plane, credential-free provider template, and Harbor dry-run guide; - the redacted 440-trial result artifact https://github.com/henryqin1997/statem/releases/download/deepseek-policy9-tb21-artifacts-20260818/statem-deepseek-v4-flash-0731-policy9-88task-k5-public-redacted-20260813.tar.gz , including ATIF trajectories and StateM states, routes, checks, and receipts; and SHA-256 checksums https://github.com/henryqin1997/statem/releases/download/deepseek-policy9-tb21-artifacts-20260818/SHA256SUMS for all three archives. The result artifact covers 88 tasks and excludes gpt2-codegolf : it records 392/440 raw passes 89.09% . The table above uses the paper's standard 89-task denominator, 392/445 88.09% . These large artifacts are hosted as release assets and are not downloaded when cloning or installing StateM. statem/ Core state machine and CLI examples/ Runbooks and hook examples integrations/ Host adapters plugins/statem/ Codex skill packaging tests/ Unit and integration tests design.md Detailed runtime and schema design docs/verification-guide.md Advanced verification patterns README media is served from the separate henryqin1997.github.io repository, so cloning or installing StateM does not download the demo video. - Start with and remove any states your workflow does not need. examples/coding-agent.yaml - Read when you need the full runtime, transition, hook, and recovery semantics. design.md - Add deterministic before transfer checks at consequential boundaries. - Use dynamic checks only when the concrete task reveals a verification need the shared runbook could not know in advance. - Keep large outputs and durable decisions in files; keep the active model context focused on the current state. @misc{qin2026statemreaching953raw, title = {StateM: Reaching 95.3\% Raw Accuracy, or a \$15 Frontier Run, on Terminal-Bench 2.1 via Harness Scaling}, author = {Ziheng Qin and Yaxin Lu and Zhangyang Atlas Wang and Kai Wang}, year = {2026}, eprint = {2608.15089}, archivePrefix = {arXiv}, primaryClass = {cs.AI}, url = {https://arxiv.org/abs/2608.15089} } We thank Zekai Li and Mengxuan Wu for discussions and feedback on this work. StateM is released under the Apache License 2.0 /henryqin1997/statem/blob/main/LICENSE .