메뉴
HN
Hacker News 18일 전

AI 에이전트를 안정적으로 만드는 시각적 상태 기계

IMP
7/10
핵심 요약

AI 에이전트의 도구 사용을 단계별로 제한해 오작동을 방지하는 오픈소스 도구 'Statewright'가 공개되었습니다. 상태 기계(State Machine)를 도입해 모델이 현재 단계에서 허용된 도구만 사용하게 강제함으로써, 최소한의 토큰 사용과 작은 모델로도 안정적으로 코딩 작업을 수행할 수 있게 돕습니다.

번역된 본문

에이전트는 제안(suggestion)일 뿐이며, 상태(state)는 법(law)입니다. Statewright는 AI 에이전트가 각 단계에서 사용할 수 있는 도구를 제어하는 상태 기계 기반 가드레일입니다. 워크플로우를 한 번 정의하면 Claude Code, Codex, Cursor, opencode, Pi 등 에이전트 전반에 걸쳐 규칙을 강제할 수 있습니다.

전체 문서 → 빠른 시작 Claude Code의 무료 티어에서 다음 명령어를 실행해 직접 사용해 볼 수 있습니다: /plugin marketplace add statewright/statewright /plugin install statewright /reload-plugins 그런 다음 버그 수정 워크플로우를 시작하거나 /statewright start bugfix를 입력하세요. 프롬프트가 나타나면 API 키를 붙여넣기 하면 됩니다. 최신 버전의 Claude는 경고 메시지를 띄울 수 있는데, 이때 API 키를 다시 붙여넣고 정말로 진행하겠다고 확실히 밝히면 됩니다. Claude가 지나치게 조심하는 것일 뿐입니다.

문제점 AI 에이전트는 강력하지만 취약합니다. 모델에 40개 이상의 도구를 주고 열린 문제를 던져주면 제대로 해결하지 못하는 경우가 많습니다. 흔한 해결책은 더 큰 모델을 쓰거나 프롬프트를 길게 작성하는 것이지만, 이 방법은 가끔만 효과가 있습니다. 관측 가능성(observability)은 사후에 무엇이 잘못되었는지 알려줄 뿐, 문제를 사전에 예방하지는 못합니다.

접근 방식 모델을 더 크게 만드는 대신, 문제를 더 작게 만드세요. 상태 기계는 도구와 해결 공간을 제한하여 모델이 각 단계마다 집중된 문맥(context)에서 추론하도록 만듭니다. 계획(planning) 상태에서는 읽기 전용 도구만 제공됩니다. 에이전트가 구현(implementing) 단계로 전환하면 셸 접근이 제한된 편집 도구가 잠금 해제됩니다(Bash가 허용되더라도 리다이렉트를 통한 쓰기나 파괴적인 명령어는 차단됩니다). 테스트 단계에서는 지정된 테스트 명령만 허용됩니다. 현재 단계에 속하지 않는 도구를 호출하면, 사용 가능한 도구와 다음 단계로 넘어가는 방법을 안내하는 메시지와 함께 요청이 거부됩니다. 이 방식은 최첨단 모델에서는 더 적은 토큰으로 완료되게 하고, 13B 이상의 로컬 모델에서는 기존에 실패하던 작업을 해결할 수 있게 만듭니다.

연구 결과 모델 크기 | 버그 수정 (26줄) | SWE-bench (5개 작업) gemma3 (3.3GB) | 실패 | 실패 gemma4:e2b (7.2GB) | 통과* | 실패 gpt-oss:20b (13.8GB) | 통과 | 통과 (5/5) gemma4:31b (19.9GB) | 통과 | 통과 (5/5) llama3.3 (42.5GB) | 통과 | 통과 (2/2)†

  • 특수 edit_line 도구 적용 포함 † 5개 작업 중 2개에 대해서만 테스트됨 (초기 실험 이후에 추가) 효과가 가장 잘 측정되는 로컬 모델에서 검증을 진행했습니다. 5개 작업으로 구성된 SWE-bench 서브셋에서 2개 모델(13.8GB, 19.9GB)이 Statewright 제약 조건을 적용했을 때 정답률이 2/10에서 10/10으로 향상되었습니다. 동일한 작업, 동일한 하드웨어 환경입니다. 13GB 미만의 모델은 도구 호출은 생성할 수 있지만 파일 내용을 충분히 유지하지 못해 정확한 편집을 만들어내지 못했습니다. 이는 모델 자체의 한계이지 Statewright의 한계가 아닙니다. 기본 시스템 프롬프트를 사용하는 최첨단 모델은 데이터베이스 삭제나 자격 증명 유출 같은 명백한 치명적 행동을 대부분 방지합니다. 하지만 진정한 구조적 이점은 모델이 동일한 파일을 5번 이상 읽으면서도 편집은 하지 않는 읽기 루프(read-loop)의 죽음의 소용돌이를 끊어내고, 도구 공간을 충분히 작게 유지하여 모델이 헤매지 않고 실제로 추론하게 만드는 데 있습니다.

연구 브리프 → 빠른 시작 Claude Code에 설치하기: /plugin marketplace add statewright/statewright /plugin install statewright 브라우저가 열리면 → statewright.ai에서 가입 → 키 생성 → 붙여넣기 → 완료. 그런 다음 워크플로우를 시작합니다: ❯ start the bugfix workflow — fix the failing tests in calc.py ◆ statewright — statewright_start (workflow: bugfix) ◆ [statewright] Workflow activated: bugfix ◆ statewright — statewright_get_state (MCP) ◆ Current phase: planning. Let me read the code first. Read 2 files [statewright] planning => implementing ◆ statewright — statewright_transition (READY) Edit calc.py: 1 line changed [statewright] implementing => testing ◆ statewright — statewright_transition (DONE) Bash: pytest -x — 7 passed [statewright] testing => completed ◆ [statewright] Workflow complete. 46 seconds. 슬래시 명령어를 직접 사용할 수도 있습니다: /statewright start bugfix

작동 원리 핵심은 상태 기계 정의(상태, 전환, 가드, 도구 제한)를 평가하는 Rust 엔진입니다. 결정론적으로 동작하며 루프 안에 LLM이 없습니다. 그 위에 MCP를 통해 코딩 에이전트와 통합하는 플러그인 계층이 있습니다. 워크플로우를 활성화하면 훅(hook)이 각 상태에 따라 도구 제한을 자동으로 강제합니다. 모델은 30개 대신 5개의 도구만 보게 되며, 명확한 안내를 받습니다.

원문 보기
원문 보기 (영어)
statewright Agents are suggestions, states are laws. State machine guardrails that control which tools your AI agent can use in each phase. Define a workflow once, enforce it across Claude Code, Codex, Cursor, opencode, and Pi. Full docs → Quickstart Try it out in Claude Code on the free tier by running the following: /plugin marketplace add statewright/statewright /plugin install statewright /reload-plugins Then start the bugfix workflow or /statewright start bugfix . You'll need to paste your API key when prompted. The latest versions of Claude may complain -- paste the API key again and say you really mean it, Claude is just being cautious here. The problem AI agents are powerful but brittle. Give a model 40+ tools and an open-ended problem and it barely gets out of the gate. The common fix is bigger models and longer prompts... it helps sometimes. Observability tells you what went wrong after the fact; it doesn't prevent it. The approach Instead of making the model bigger, make the problem smaller. State machines constrain the tool and solution spaces so the model reasons in a focused context at each step. A planning state gets read-only tools. When the agent transitions to implementation, edit tools unlock with limited shell access (write-via-redirect and destructive ops are blocked even when Bash is allowed). Testing only permits designated test commands. If you call a tool that's not in the current phase, you get rejected with a message telling you what IS available and how to transition. Works the same way on frontier models (fewer tokens to completion) and local models where 13B+ models start solving tasks they'd otherwise fail. Research results Model Size Bug Fix (26 lines) SWE-bench (5 tasks) gemma3 3.3GB FAIL FAIL gemma4:e2b 7.2GB PASS* FAIL gpt-oss:20b 13.8GB PASS PASS (5/5) gemma4:31b 19.9GB PASS PASS (5/5) llama3.3 42.5GB PASS PASS (2/2)† *with specialized edit_line tool adaptation †tested on 2 of the 5 tasks (added after initial experiment run) We validated on local models where the effect is most measurable. In our 5-task SWE-bench subset, two models (13.8GB and 19.9GB) went from 2/10 to 10/10 with statewright constraints. Same tasks, same hardware. Below 13GB, models can produce tool calls but can't retain enough file content to produce accurate edits — that's the floor, not a statewright limitation. Frontier models with default system prompts handle the obvious catastrophic actions (database deletion, credential leaks)... most of the time. The structural win is bigger: breaking read-loop death spirals where models re-read the same file 5+ times without ever editing, and keeping the tool space small enough that the model actually reasons instead of flailing. Research brief → Quick start Install into Claude Code: /plugin marketplace add statewright/statewright /plugin install statewright Your browser opens → sign up at statewright.ai → generate a key → paste it → done. Then start a workflow: ❯ start the bugfix workflow — fix the failing tests in calc.py ◆ statewright — statewright_start (workflow: bugfix) ◆ [statewright] Workflow activated: bugfix ◆ statewright — statewright_get_state (MCP) ◆ Current phase: planning. Let me read the code first. Read 2 files [statewright] planning => implementing ◆ statewright — statewright_transition (READY) Edit calc.py: 1 line changed [statewright] implementing => testing ◆ statewright — statewright_transition (DONE) Bash: pytest -x — 7 passed [statewright] testing => completed ◆ [statewright] Workflow complete. 46 seconds. You can also use the slash command directly: /statewright start bugfix . How it works The core is a Rust engine that evaluates state machine definitions: states, transitions, guards, tool restrictions. It's deterministic. No LLM in the loop. On top of that sits a plugin layer that integrates with your coding agent via MCP. When you activate a workflow, hooks enforce tool restrictions per state automatically. The model sees 5 tools instead of 30, gets clear instructions for the current phase, and transitions when conditions are met. Guardrails Guardrail What it does Per-state tool enforcement Tools invisible to agent when not in allowed_tools Bash discernment Redirects ( >> ), destructive ops ( rm , shred ), and scripting interpreters blocked in non-write states Edit guards Rejects diffs exceeding max_edit_lines , caps files edited per state Command allow-lists Prefix-matched allowed_commands per state Conditional transitions Guards with programmatic predicates (eq, gt, exists, etc.) on context data Approval gates requires_approval pauses for human review before high-risk transitions Environment scoping blocked_env + env_overrides per state Session isolation Per-session state via CLAUDE_SESSION_ID Full guardrail reference in the docs . Define your own workflows { "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 " } } } State machines aren't DAGs — they loop and retry, which is what agentic work actually needs. Point your agent at the JSON schema and it generates a workflow via statewright_create_workflow . Tweak tools, commands, and environment blocks in the visual editor . 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 but not enforced. Pricing Free for individual developers. The managed cloud at statewright.ai handles workflow storage, run history, and the MCP gateway. (these tiers are likely to be in flux: prices will not increase, tier grants can only increase) Plan Workflows Transitions/mo Run History Price Free 3 200 72 hours $0 Pro 10 2500 7 days $29/mo Team 30 10000 90 days $99/mo Enterprise Unlimited Unlimited to Specification Contact us Self-hosting The engine ( crates/engine ) is Apache 2.0 and embeddable with no runtime dependencies. Single-developer and single-team self-hosting of the full stack is permitted under the FSL license. use statewright_engine :: { MachineDefinition , resolve_transition , validate_definition } ; Tradeoffs Requires MCP support in the agent (or hooks for non-MCP agents like Codex) Workflow definitions are authored by hand, though agents can generate them via statewright_create_workflow Cursor enforcement is advisory, not hard. MCP alone can't gate tool calls in Cursor's architecture Research results are from a 5-task SWE-bench subset, not the full 2294-instance benchmark If a workflow is too restrictive, the agent gets stuck. statewright_deactivate is the escape hatch Docs statewright.ai/docs — install guide, workflow authoring, schema reference , MCP tool reference , and agent-generated workflows . Contributing Workflow definitions, templates, and bug reports welcome. See Create Your Own for how to write workflows. License Apache 2.0 — portions FSL-1.1-Apache-2.0 (converts to Apache 2.0 on May 3, 2029). Managed cloud at statewright.ai . One hook to rule them all.