Map

statewright

Toolbox toolboxrustai-agentsguardrailsmcpclaude-codeRustApache-2.0 / FSL-1.1-ALv2 โ†ณ show in map Markdown
title
statewright
type
toolbox
summary
Rust state machine that gates which tools an AI coding agent can call in each phase of its work
tags
rust, ai-agents, guardrails, mcp, claude-code
language
Rust
license
Apache-2.0 / FSL-1.1-ALv2
created
2026-05-13
updated
2026-05-13

Statewright is a Rust state-machine engine for AI coding agents that gates which tools are available in which phase. The agent declares a workflow (e.g. planning โ†’ implementing โ†’ testing โ†’ completed); the engine enforces it per state. Tools outside the current state's allowed_tools are invisible to the model. Tagline: "Agents are suggestions, states are laws."

The thesis

Most agent failures are framed as model-quality problems and met with bigger models or longer prompts. Statewright argues the failure mode is the option space: a model with 40+ tools and an open-ended problem spends tokens on flailing instead of reasoning. Shrinking the available tool set per phase is the cheap intervention.

The research-results table in the README shows the effect on local models: in a 5-task SWE-bench subset, gpt-oss:20b (13.8 GB) and gemma4:31b (19.9 GB) both went from 2/10 to 10/10 with statewright constraints โ€” same hardware, same tasks. Below 13 GB models can call tools but can't hold enough file content for accurate edits, so the floor is set by the model, not the harness. Frontier models also use fewer tokens to completion.

How it works

The engine is a Rust crate (crates/engine, Apache-2.0, embeddable, no runtime deps) that evaluates state-machine JSON definitions: states, transitions, guards, tool restrictions. No LLM in the loop โ€” every decision is deterministic.

On top sits a plugin layer that wires the engine into the coding agent over MCP. Statewright registers MCP tools (statewright_start, statewright_get_state, statewright_transition, statewright_create_workflow, statewright_deactivate) and per-tool-call hooks enforce the current-state's allowed_tools. The model only ever sees the tools it's allowed to use in this state.

Guardrails per state

Guardrail Effect
allowed_tools Tools invisible to the agent when not listed
Bash discernment Blocks >> redirects, destructive ops (rm, shred), scripting interpreters in non-write states
max_edit_lines Reject diffs exceeding the limit
max_files_per_state Cap files edited per state
allowed_commands Prefix-matched shell-command allowlist
Conditional transitions Guards with predicates (eq, gt, exists) over context data
requires_approval Pause for human review before a transition
blocked_env / env_overrides Per-state env-var scoping
CLAUDE_SESSION_ID Per-session state, multiple workflows in parallel

A state-machine isn't a DAG โ€” states loop and retry (testing โ†’ implementing on test failure), which matches how iterative agent work actually behaves.

Example workflow

{
  "id": "bugfix",
  "initial": "planning",
  "states": {
    "planning": {
      "allowed_tools": ["Read", "Grep", "Glob"],
      "max_iterations": 8,
      "on": { "READY": "implementing" }
    },
    "implementing": {
      "allowed_tools": ["Read", "Edit", "Write"],
      "max_edit_lines": 20,
      "max_files_per_state": 3,
      "on": { "DONE": "testing" }
    },
    "testing": {
      "allowed_tools": ["Read", "Bash"],
      "allowed_commands": ["pytest", "cargo test", "npm test"],
      "on": {
        "PASS": { "target": "completed", "guard": "tests_passed" },
        "FAIL_TEST": "implementing"
      }
    },
    "completed": { "type": "final" }
  },
  "guards": {
    "tests_passed": { "field": "test_result", "op": "eq", "value": "pass" }
  }
}

Supported agents

Agent Integration Enforcement
Claude Code Hooks + MCP Hard (protocol layer)
Codex Hooks Hard (alpha)
opencode TypeScript plugin Hard (alpha)
Pi Skills extension Hard (alpha)
Cursor MCP + rules Advisory (alpha)

Hard = tool calls blocked at the protocol layer before the model sees them. Advisory = rules injected into context, model can still try. The Cursor case is a structural limitation โ€” MCP alone can't gate tool calls in Cursor's architecture.

Where it fits

Statewright is the structural answer to several recurring problems in the wiki:

  • sandboxing-ai-agents โ€” Filesystem / network / HTTP / syscall isolation tells you what the agent can touch. Statewright is a fifth axis: what tools the agent can call, conditioned on phase. Crabtrap-style HTTP-policy and statewright-style tool-policy are layered defenses.
  • skill-atrophy-supervision-paradox โ€” Constraining the agent in advance is the workflow Cohen's audit-discuss-execute enforces by human discipline, encoded as a machine-checkable spec.
  • acceptance-criteria-ids / specsmaxxing โ€” specs as IDs that agents reference back and state-machines as IDs that agents transition through are complementary moves toward navigable structure around the model.

The "bash discernment" guardrail (block >> and destructive ops in non-write states) is the same pattern hazmat hits via Seatbelt + pf at the OS layer โ€” statewright catches it earlier, before the call reaches the runner.

Pricing

Free tier (3 workflows, 200 transitions/month). Pro ($29), Team ($99). Engine is Apache-2.0 and self-hostable; single-developer and single-team self-hosting of the full stack is permitted under FSL-1.1-ALv2 (auto-converts to Apache-2.0 on 2029-05-03).

Limitations

  • MCP is required for hard enforcement; Codex and opencode use hooks instead (alpha).
  • Cursor support is advisory only โ€” MCP can't gate Cursor's built-in tools.
  • Workflow definitions are hand-authored JSON; the statewright_create_workflow MCP tool lets the agent generate them but the upstream schema still has to be loaded into context.
  • A too-restrictive workflow can leave the agent stuck; statewright_deactivate is the escape hatch.
  • Research validation is a 5-task SWE-bench subset, not the full 2294 instances.

Quickstart (Claude Code, free tier)

/plugin marketplace add statewright/statewright
/plugin install statewright
/reload-plugins

Then say start the bugfix workflow or /statewright start bugfix. The first call asks for the API key from statewright.ai. (The README notes Claude may be cautious about pasted API keys โ€” confirm intent if it asks.)

Repo: https://github.com/statewright/statewright (Apache-2.0 / FSL, 88 stars, fresh). On the watchlist as a young single-vendor project.