{"slug": "statem-stateful-control-for-long-horizon-agents", "title": "StateM: Stateful control for long-horizon agents", "summary": "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.", "body_md": "[**2026-08-18**]🤗 StateM ranked [ #1 on Hugging Face Daily Papers](https://huggingface.co/papers/date/2026-08-18).\n\n[**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!\n\nStateM 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.\n\nLong 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.\n\n``` php\nprepare -> execute -> verify -> handoff\n              ^          |\n              +-- repair-+\n```\n\nAt every state, the agent can ask:\n\n- What should I do now?\n- Which transitions are legal?\n- What evidence is required before I move?\n- What happened earlier in this run?\n\nThe answer is stored in files and runtime history rather than relying on the model to remember everything.\n\n| Approach | Remembers phase | Blocks invalid transitions | Supports repair loops | Survives context refresh | Agent-editable |\n|---|---|---|---|---|---|\n| Prompt-only workflow | Partial | No | Informal | No | Yes |\n| TODO list | Partial | No | Informal | Yes | Yes |\n| CI pipeline | Yes | Yes | Limited | Yes | Usually no |\n| General workflow engine | Yes | Yes | Yes | Yes | Rarely |\nStateM |\nYes |\nYes |\nYes |\nYes |\nYes |\n\nStateM 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.\n\n**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.\n\nClone the repository and install it in editable mode:\n\n```\ngit clone https://github.com/henryqin1997/statem.git\ncd statem\npython3 -m pip install -e .\n```\n\nCheck the CLI:\n\n```\nstatem --help\n```\n\nValidate and start the included coding-agent runbook:\n\n```\nstatem validate examples/coding-agent.yaml\nstatem start examples/coding-agent.yaml --run-id demo\nstatem cur --run-id demo\nstatem next --run-id demo\n```\n\nMove only when the current state's checks pass:\n\n```\nstatem goto plan --run-id demo\nstatem history --run-id demo\n```\n\nRuntime data defaults to `.statem/`\n\n. For durable machine-local state that survives disposable checkouts, place it outside the repository:\n\n```\nexport STATEM_STATE_DIR=\"$HOME/.local/state/statem/my-project\"\nstatem start examples/coding-agent.yaml --run-id demo\nname: implementation-loop\ninitial: plan\n\nnodes:\n  plan:\n    prompt: |\n      Read the task and write a concrete implementation plan.\n    before_transfer:\n      type: checklist\n      items:\n        - Scope and constraints are recorded\n        - Verification steps are defined\n\n  execute:\n    prompt: |\n      Implement the plan and keep the change scoped.\n    before_transfer:\n      - type: command\n        run: \"python3 -m pytest -q\"\n      - type: checklist\n        items:\n          - Relevant tests pass\n          - Unrelated files were not changed\n\n  handoff:\n    prompt: |\n      Summarize the change, verification, and remaining risks.\n\nedges:\n  - from: plan\n    to: execute\n    condition: The plan is ready.\n  - from: execute\n    to: plan\n    condition: Verification found a fixable gap.\n  - from: execute\n    to: handoff\n    condition: The implementation and verification are complete.\n```\n\nSave it as `runbook.yaml`\n\n, then run:\n\n```\nstatem validate runbook.yaml\nstatem start runbook.yaml --run-id my-run\nstatem cur --run-id my-run\n```\n\nStateM separates the shared workflow definition from per-run execution state:\n\n| Layer | Contents | Commit to git? |\n|---|---|---|\n| Static runbook | Nodes, edges, prompts, hooks, gates | Yes |\n| Runtime state | Current node, history, results, timestamps | No |\n| Dynamic checks | Task-specific current-entry verification | No |\n| Durable project notes | Plans, decisions, progress, artifacts | Usually yes |\n\nA transition is a transaction:\n\n- Resolve the requested outgoing edge.\n- Run the current node's\n`before_transfer`\n\nchecks. - Load and run current-entry dynamic checks.\n- Evaluate the edge's\n`condition`\n\n. - Run the current node's\n`out_hook`\n\nand the edge`hook`\n\n. - Record the transition, create a new target entry, and run the target node's\n`in_hook`\n\n.\n\nIf a blocking check fails, the agent remains in the current state with the failure recorded for repair.\n\n| Field | Purpose |\n|---|---|\n`name` |\nHuman-readable graph name |\n`initial` |\nNode entered when a new run starts |\n`nodes` |\nNamed state definitions |\n`edges` |\nDirected transitions between states |\n\n| Field | When it runs | Typical use |\n|---|---|---|\n`prompt` / `pre_request` |\nWhile the node is active | State-local instructions |\n`in_hook` |\nAfter entering | Load context or initialize evidence |\n`before_transfer` |\nBefore leaving | Block on required verification |\n`dynamic_before_transfer` |\nBefore leaving | Run task-specific current-entry checks |\n`out_hook` |\nBefore the transition commits | Persist progress or handoff notes |\n\n| Field | Purpose |\n|---|---|\n`from` / `to` |\nSource and target nodes |\n`condition` |\nTransition-specific blocking gate |\n`hook` |\nPrepare-transfer work after exit gates pass |\n`max_attempts` |\nOptional positive retry ceiling for this edge and source-node entry |\n\nLeaving out `max_attempts`\n\npreserves the default unbounded retry behavior. When\nconfigured, each real `goto`\n\nconsumes one attempt; blocked checks count, and a\nfresh source-node entry receives a fresh budget.\n\n| Type | Behavior |\n|---|---|\n`message` |\nDisplay non-blocking guidance |\n`manual` |\nAsk for explicit confirmation |\n`checklist` |\nConfirm a set of completion conditions |\n`command` |\nRun a shell command and use its exit code |\n`predicate` |\nInspect files declaratively |\n`llm_review` |\nDelegate a structured review to an external command/model |\n\nChecks can be configured with fields such as `blocking`\n\n, `on_failure`\n\n, `timeout`\n\n, and `cwd`\n\n. Prefer checks that exercise the same interface the task promises to its eventual consumer.\n\n| Command | Purpose |\n|---|---|\n`statem start SPEC` |\nCreate or resume a run |\n`statem cur` |\nShow the current node and its prompt |\n`statem state` |\nShow the full graph |\n`statem ls NODE` |\nInspect one node |\n`statem next` |\nShow outgoing transitions |\n`statem goto TARGET` |\nAttempt a checked transition |\n`statem save` |\nPersist state and run the current `out_hook` |\n`statem history` |\nInspect prior transitions and results |\n`statem prompt` |\nGenerate a durable post-clear resume prompt |\n`statem compact-prompt` |\nGenerate a safe compaction prompt |\n`statem validate SPEC` |\nValidate graph structure and references |\n`statem validate SPEC --strict` |\nAlso reject unknown or misplaced runbook keywords |\n`statem dynamic ...` |\nManage current-entry dynamic checks |\n\nMost commands accept `--run-id`\n\n, `--state-dir`\n\n, and `--json`\n\nfor explicit run selection, isolated state, and machine-readable output.\n\nStatic 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.\n\n```\nstatem dynamic path --run-id demo\nstatem dynamic write checks.json --run-id demo --agent-id implementer\nstatem dynamic list --run-id demo --json\n```\n\nDynamic checks are scoped to the current node entry. StateM records who registered them and runs them before the transition is allowed to commit.\n\nLong runs should keep durable facts in project files and use the model context for the current decision. StateM supports that split with:\n\n`statem history`\n\nfor the durable transition record;`statem prompt`\n\nfor restoring attention after a cleared session;`statem compact-prompt`\n\nfor safe compaction inside cyclic runbooks;- explicit recovery or session-refresh nodes when another loop should continue;\n- spec hashes and run identifiers to detect or deliberately rebind edited runbooks.\n\nRunbooks belong in version control. Runtime state does not. Add `.statem/`\n\nto `.gitignore`\n\nwhen using the default local state directory.\n\nStateM works without a host hook. To keep an agent moving after it would\notherwise end its turn, register the optional `Stop`\n\nhook as a till-finish\nmode. When an active run is still on a non-terminal node with outgoing\ntransitions, the hook returns a continuation prompt that tells the agent to\ninspect StateM and continue from the durable state.\n\n- Start the run normally with\n`statem start`\n\n. - For Codex, merge\ninto`codex-stop-autoloop.hooks.json`\n\n`.codex/hooks.json`\n\nor`~/.codex/hooks.json`\n\n. - For Claude Code, merge\ninto a project or user settings file.`claude-stop-autoloop.settings.json`\n\n- If the hook runs outside this repository, replace its command with the absolute path to\n`integrations/hooks/statem_stop_hook.py`\n\n. Set`STATEM_STATE_DIR`\n\ntoo when the run does not use the default`.statem/`\n\ndirectory.\n\nThe hook does not advance StateM by itself, bypass transition checks, run\n`/clear`\n\n, or run `/compact`\n\n. It allows the host to stop when no active run\nexists, the current state is terminal, or the graph has no outgoing\ntransition. See the [complete setup and behavior reference](/henryqin1997/statem/blob/main/examples/hooks/README.md).\n\n| Host / environment | Entry point |\n|---|---|\n| Codex |\n`plugins/statem/skills/statem/SKILL.md` |\n\n`integrations/claude/statem/`\n\n[Executable](/henryqin1997/statem/blob/main/examples/terminal-bench-2.1-git-webserver-deploy-family.md)`git_webserver_deploy`\n\nfamily guide`examples/hooks/README.md`\n\nStateM's core remains host-agnostic: any agent that can run shell commands can query and advance a runbook.\n\n| Example | What it demonstrates |\n|---|---|\n`coding-agent.yaml` |\n\n[·](/henryqin1997/statem/blob/main/examples/terminal-bench-2.1-git-webserver-deploy-family.yaml)`git_webserver_deploy`\n\nfamily[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).\n\nThe 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:\n\n| Configuration | Result | Operating condition |\n|---|---|---|\n| GPT-5.5 xhigh + StateM | 92.1% | 89 tasks, 445 trials; 88/89 five-trial coverage |\n| GPT-5.6 Sol xhigh + frozen StateM profile | 95.28% raw | 424/445 public-submission trials; 89/89 coverage |\n| DeepSeek-V4-Flash + adapted StateM profile | 88.09% | 392/445 under standard timeouts |\n| DeepSeek-V4-Flash + adapted StateM profile | 88.76% descriptive | 395/445, replacing one task with disclosed extended-timeout trials |\n\nThe 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.\n\nThe [policy-v9 artifact release](https://github.com/henryqin1997/statem/releases/tag/deepseek-policy9-tb21-artifacts-20260818) provides:\n\n- the\n[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\n[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\n[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.\n\nThe result artifact covers 88 tasks and excludes `gpt2-codegolf`\n\n: 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.\n\n```\nstatem/                  Core state machine and CLI\nexamples/                Runbooks and hook examples\nintegrations/            Host adapters\nplugins/statem/          Codex skill packaging\ntests/                   Unit and integration tests\ndesign.md                Detailed runtime and schema design\ndocs/verification-guide.md\n                        Advanced verification patterns\n```\n\nREADME media is served from the separate `henryqin1997.github.io`\n\nrepository, so cloning or installing StateM does not download the demo video.\n\n- Start with\nand remove any states your workflow does not need.`examples/coding-agent.yaml`\n\n- Read\nwhen you need the full runtime, transition, hook, and recovery semantics.`design.md`\n\n- Add deterministic\n`before_transfer`\n\nchecks at consequential boundaries. - Use dynamic checks only when the concrete task reveals a verification need the shared runbook could not know in advance.\n- Keep large outputs and durable decisions in files; keep the active model context focused on the current state.\n\n```\n@misc{qin2026statemreaching953raw,\n  title         = {StateM: Reaching 95.3\\% Raw Accuracy, or a \\$15 Frontier Run,\n                   on Terminal-Bench 2.1 via Harness Scaling},\n  author        = {Ziheng Qin and Yaxin Lu and Zhangyang Atlas Wang and Kai Wang},\n  year          = {2026},\n  eprint        = {2608.15089},\n  archivePrefix = {arXiv},\n  primaryClass  = {cs.AI},\n  url           = {https://arxiv.org/abs/2608.15089}\n}\n```\n\nWe thank Zekai Li and Mengxuan Wu for discussions and feedback on this work.\n\nStateM is released under the [Apache License 2.0](/henryqin1997/statem/blob/main/LICENSE).", "url": "https://wpnews.pro/news/statem-stateful-control-for-long-horizon-agents", "canonical_source": "https://github.com/henryqin1997/statem", "published_at": "2026-08-22 14:07:09+00:00", "updated_at": "2026-08-22 14:44:09.444356+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-research"], "entities": ["StateM", "Hugging Face", "DeepSeek-V4-Flash", "Terminal-Bench 2.1", "henryqin1997"], "alternates": {"html": "https://wpnews.pro/news/statem-stateful-control-for-long-horizon-agents", "markdown": "https://wpnews.pro/news/statem-stateful-control-for-long-horizon-agents.md", "text": "https://wpnews.pro/news/statem-stateful-control-for-long-horizon-agents.txt", "jsonld": "https://wpnews.pro/news/statem-stateful-control-for-long-horizon-agents.jsonld"}}