Skip to main content

statemachine-use

「ステートマシンを実行して」「ステートマシンを作成/作って」「YAMLワークフローを動かして」「ワークフローを回して」「エージェントループを起動して」「このYAMLを実行して」などで発動。作成モード(手順を.statemachine/{名前}/に生成)と実行モード(YAMLをLLM駆動で実行)を持つ。

Source facts

Repository
ynitto/sandbox
Last source activity
September 28, 2026 at 23:15
Detected SKILL.md language
Japanese
Stars
1
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
21 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
statemachine-use
description
「ステートマシンを実行して」「ステートマシンを作成/作って」「YAMLワークフローを動かして」「ワークフローを回して」「エージェントループを起動して」「このYAMLを実行して」などで発動。作成モード(手順を.statemachine/{名前}/に生成)と実行モード(YAMLをLLM駆動で実行)を持つ。
metadata
{"version":"2.3.0","tier":"experimental","category":"workflow","tags":["statemachine","yaml-workflow","agent-loop","hybrid-execution"]}
# YAML ステートマシン スキル YAMLと外部マークダウンファイルで定義されたLLM駆動ステートマシンを**作成・実行**します。 --- ## モードの選択 | ユーザーの意図 | モード | |---|---| | 「〜という手順でステートマシンを作って」 | **作成モード** | | 「〜を実行して」「〜を動かして」「YAMLを回して」 | **実行モード** | --- ## 作成モード ユーザーが自然言語で説明した手順を `.statemachine/{名前}/` フォルダ以下のYAML+マークダウンに落とし込む。 ### ステップ1: 利用可能なスキルを調査する ```bash ls .github/skills/ ``` 出力されたスキル名を記録する。アクション定義でスキル呼び出しを活用できる場合に参照する。 ### ステップ2: 手順を状態遷移として分解する **LLM読み飛ばし防止の設計原則(重要)** 1. **ルーティングロジックをアクションに書かない** — 分岐判断はトランジション条件に書く 2. **出力形式を強制する** — 条件が評価しやすいキーワード出力を要求する(例: `PASS / FAIL`) 3. **将来のステートをヒントとして含めない** — アクションは現在のステートの作業のみを指示する 4. **アクションの末尾に単一指示を付与する** — 全アクションmdの末尾に必ず下記を追記する: ``` この指示に従ってタスクを実行してください。 完了後、指定された形式で出力のみを返してください。次のステップは別途指示されます。 ``` 5. **スクリプトは原則作成しない** — スキル(ステップ1で確認)や他のAI機能でアクションを実行する 6. **スキルへ移譲するときはスキル名を明記する** — アクション本文に `` `skill-name` スキル `` と書く。この記法が無いと実行ハーネスはスキルを読み込まず、スクリプトの場所も分からない 7. **成功条件を `output_validator` で定義する** — 「第1行が `OK` か `FAILED`」のような機械が判定できる出力契約を states に書く。書かないとアクションの成否を確認できず、失敗したまま次のステートへ進む 8. **成果物の正しさは `check` で測る** — `output_validator` が見るのは書式だけで、「OK」と書くのはモデル自身である。**成果物が実際に仕様どおり動くかを見るには、ハーネスが実行する検査コマンドを宣言する**(下記) 9. **1 ステート 1 成果物** — 1 つのステートで作るファイルは 1 つだけにする(`write` に 2 つ以上を宣言した定義は投入前に落ちる)。小さいモデルは成果物を 2 つ同時に渡されると片方を丸ごと落とし、再投入を積んでも同じ落ち方をする(実測: 一括 0/3・1 成果物ずつ 3/3)。実装とテストなら 2 つのステートに割り、それぞれに `check` を付ける 10. **分類・振り分け・段階の評価だけのステートは `judge:` で書く** — 「N 語のどれかを 1 語で答える」ステート(issue_triage の classify、レビューの結論など)は、アクションを書かず `judge:` に問いと選択肢を書く(`references/schema.md`「判定だけのステート」)。判定 AI があれば生成 0 で終わり、無ければ宣言から作った短いプロンプトで 1 回だけ生成する(`action` を併記すればそれが生成用の文になるが、書かない方が短くて安い)。理由や本文が要るステートには使わない(それは通常のアクション) 11. **出力の内容で分岐する遷移は `outcome` で書く** — 同じステートから出る候補ごとに「この遷移が成立する結果」の短い名前を `outcome:` に書く(下記)。判定 AI(agent-herd の judge)はそれを選択肢にして「結果はどれか」を **1 問**で選ぶ——候補ごとに YES/NO を訊くより速く安く、2 つの条件が同時に真になる矛盾が構造として消える。judge が無い環境では同じ `outcome` が条件文として LLM に渡るので、定義を書き分けなくてよい 12. **実行する人が入れる値は `inputs:` で宣言する** — アクションに `{{month}}` のような値を書いたら、 トップレベルの `inputs:` に同じキーを `label`(画面に出す名前)・`required`(既定 true)・`default`・`type` で書く。 定義を読んだだけで何を入れれば動くかが分かり、agent-app はその宣言どおりに入力ダイアログを出す。 ループの上限のような人が入れない固定値は `context:` に置く(`references/schema.md`「入力の宣言」) **`outcome` — 分岐を「条件の列」ではなく「結果の選択肢」として書く** ```yaml transitions: - from: review to: approve outcome: "指摘なしで承認できる" # 判定 AI の選択肢 A priority: 1 - from: review to: revise outcome: "直すべき指摘がある" # 選択肢 B priority: 2 - from: review to: ask outcome: "判断できない" # 選択肢 C(どれでもない、は自動で足される) priority: 3 ``` - 同じ元ステートの **LLM 評価が要る候補すべて**に `outcome` があるときだけ 1 問の選択になる。1 つでも欠けると従来どおり条件ごとの YES/NO - `condition_rule` で決まる候補(`check_ok` など)は選択肢に入らない。測れるものは測り、測れない残りだけを判定 AI に選ばせる - `condition` と併記してもよい(`condition` は judge が無い経路の条件文、`outcome` は選択肢の名前)。`condition` を省くと `outcome` が条件文の代わりになる **`check` — 遷移の材料を自己申告から実測へ移す** ```yaml states: implement: action_file: actions/implement.md output_validator: "startswith:OK" # 書式(モデルが書く) check: "python3 -m pytest tests/test_x.py -q" # 事実(ハーネスが測る) check_retries: 2 transitions: - from: implement to: review condition_rule: "equals:check_ok:true" # 実際に通ったときだけ進む ``` 検査が落ちたら、測った不一致を課題文へ足して**同じステートをやり直す**。再投入を使い切っても 落ちるなら、実行を止めて `escalate`(この段では解けない = 上位の段へ回すシグナル)を返す。 ローカルモデルで定型作業を回すなら、これが**受入率を決める唯一のレバー**である。実測では 検知を伴わない分解は受入を下げ(0/3)、決定的な検知 + 再投入で 3/3 になった。逆に**通る課題に ゲートは課金しない**(呼び出し回数は増えない)。書式・使える宣言の形・失敗時の動作は `references/schema.md` の「決定的検査 (check)」を参照。作例は `examples/gated_implement.yaml`。 **検査を置ける単位で割る** — ステートを細かく割ること自体に効果は無い(実測では逆に下がる)。 分解の目的は**検査を差し込む場所を作ること**である。1 つのステートを設計するとき、 「このステートの成果は、どのコマンドの終了コードで測れるか」を先に決める。決められないなら、 そのステートはまだ割り方が正しくない。 **実行できるスクリプトの範囲**(ハーネスが強制する。定義側もこれに合わせて書く): | 決まり | 意味 | |---|---| | アクション本文が名指しした `.py` / `.js` / `.sh`、または移譲先スキルの SKILL.md に載っている `.py` / `.js` / `.sh` のみ | `scripts/` に置いてあるだけの下請けは呼べない | | 固定インタプリタで実行する(`.py`→python / `.js`→node / `.sh`→bash または sh) | shebang や実行ビットで走らせるものを決めさせない | | スキル名は実行コマンドではない | `` `demo` スキル `` の `demo` を command に置いても動かない。スクリプトのパスを書く | | `bash -c` などの任意シェルは使えない | シェル経由の合成コマンドは拒否される | | コマンドの stdout が空でも exit 0 なら成功 | 出力の有無で成否を判定しない。空の結果は正常な空結果 | **パターンの自動検出** — 詳細テンプレートは `references/patterns.md` を参照: | 手順の特徴 | 適用するパターン | |---|---| | 「同時に」「並列で」「〜と〜を一緒に」 | Fan-out/Fan-in | | 処理後に次があるか確認してループ | ContinueAsNew Loop | | 副作用の大きい操作(変更・デプロイ等)の後 | ゲートステート | | 複雑な判断・推論を含むステート | ReActアンカリング | | 「失敗したら元に戻す」「ロールバック」 | Saga | | 5ステート以上の長いワークフロー | マイルストーンアンカー | ### ステップ3: scaffold で骨組みを生成する フォルダとファイルを手で書かない。ステップ2で決めた状態列を scaffold へ渡す: ```bash python .github/skills/statemachine-use/scripts/scaffold.py {名前} \ --state "first_state:説明" --state second_state ``` - `--state ID[:説明]` を実行順に並べる。終端は `--terminal ID[:説明]`(省略時は complete を自動で足す)。 - `.statemachine/{名前}/` に workflow.yaml と actions/*.md スタブを生成し、**生成直後に検証する** (通らない骨組みは残さない)。 - 骨組みは直列遷移。分岐・ループ・複雑な条件(`conditions/{from}_to_{to}.md`)はステップ4で足す。 - 新スキーマの口(`output_validator` / `check` / `check_retries` / `check_on_exhausted` / `write`)は コメント付きで含まれる——ステップ2で決めた検査コマンドのコメントを外して実値にする。 ### ステップ4: スタブを埋める 生成された workflow.yaml と actions/*.md を以下の形へ埋める。全フィールドの仕様は `references/schema.md` を参照: ```yaml name: "ワークフロー名" initial_state: first_state inputs: # 実行する人が入れる値(アクションの {{キー}} に入る) target: label: 対象 # 画面に出す名前 type: text # text | multiline | number | date | month | email | url | choice mode: label: 進め方 type: choice options: [quick, full] default: quick # 空なら quick note: label: 補足 required: false # 任意(省略時は必須) context: # 人が入れない初期変数(ループカウンター等) config: max_steps: 30 states: state_id: description: "ラベル" action_file: actions/state_id.md # 外部ファイル参照(推奨) output_key: result_key # 任意: context に名前付き保存 terminal: false transitions: - from: state_id to: other_id condition: "自然言語条件" # or condition_file: conditions/...md priority: 1 ``` **actions/{state_id}.md:** ```markdown ## [state_id: 何をするか] (スキル呼び出しや具体的な指示) **入力:** {{input}} **前のステートの出力:** {{last_output}} **出力形式:** XXX または YYY の一語のみで回答してください。 この指示に従ってタスクを実行してください。 完了後、指定された形式で出力のみを返してください。次のステップは別途指示されます。 ``` **conditions/{from}_to_{to}.md(複雑な条件のみ):** ```markdown 以下の条件をYES/NOで評価してください: - {{retry_count}} が {{max_retries}} 未満である、かつ - 最後の出力が RETRY で始まる 両方を満たす場合のみ YES と回答してください。 ``` ### 作成例 ```yaml # .statemachine/review_code/workflow.yaml name: "コードレビュー" initial_state: analyze states: triage: # 判定だけのステートは judge で書く(生成 0) judge: question: "このコードの変更はどの種類か" choices: {BUGFIX: "不具合の修正", FEATURE: "機能の追加", REFACTOR: "振る舞いを変えない整理"} output_key: change_kind analyze: action_file: actions/analyze.md output_key: analysis_result approve: action_file: actions/approve.md terminal: true request_revision: action_file: actions/request_revision.md terminal: true transitions: - from: analyze to: approve condition_rule: "startswith:analysis_result:PASS" # 第 1 行の書式で決まるなら測る priority: 1 - from: analyze to: request_revision outcome: "直すべき問題が見つかった" # 残りは判定 AI に選ばせる priority: 2 - from: analyze to: approve outcome: "問題は見つからなかった" priority: 3 ``` ```markdown <!-- .statemachine/review_code/actions/analyze.md --> ## [analyze: コード品質を分析する] 以下のコードを品質の観点で分析してください。 **対象コード:** {{input}} 確認項目: バグ、コードの臭い、エラーハンドリング漏れ、パフォーマンス問題 **出力形式:** 最初の行に PASS / MINOR / MAJOR / CRITICAL のいずれか一語、その後に問題点を列挙してください。 この指示に従ってタスクを実行してください。 完了後、指定された形式で出力のみを返してください。次のステップは別途指示されます。 ``` ### 定義のメンテナンス — migrate スキーマは加算的に拡張される(check → check_on_exhausted → write)。手持ちの定義は migrate で検査し、追随させる: ```bash python .github/skills/statemachine-use/scripts/migrate.py path/to/workflow.yaml # dry-run(検出と差分) python .github/skills/statemachine-use/scripts/migrate.py .statemachine --apply # フォルダごと適用 ``` 検出項目: check 宣言の無いステートからの `check_*` 分岐(検証エラー・修正案の提示)、 シェル記号入り `check`(投入前に落ちる)、`write` 未割付(編集対象が一意に決まる場合だけ提案)、 `check_on_exhausted` の暗黙既定の明示化。後ろ 2 つはコメントを保ったまま `--apply` で書き換える。 正規化・検証は engine.py の 1 実装を使うので、判定が実行系とずれることはない。 --- ## 実行モード ### ⛔ ハーネス実行プロトコル — 禁止行動(違反時は即座に停止して再確認) | 禁止行動 | 代替行動 | |---|---| | アクション実行前に条件リストを取得する | ① 実行 → 出力確定 → ② 条件取得 の順を守る | | 現在のステート以外の作業を実行する | 現在のステートの作業のみ実行する | | `## [現在のステート: {state_id}]` 宣言を省略する | 毎ステートの冒頭で必ず宣言する | | 条件を評価せずに遷移先を独断で決める | 必ず ④ の Python スクリプトで遷移先を確定する | | 複数ステートをまとめて実行する | 1ステート = 1ターンを厳守する | --- ### Step 0: 検証と開始ステートの取得 ```bash # ワークフローの検証 python .github/skills/statemachine-use/scripts/run_machine.py .statemachine/{名前}/workflow.yaml --dry-run # 入力の確認(inputs を宣言した定義のみ。依頼文から読み取れた値を --context に入れる) python .github/skills/statemachine-use/scripts/next_state.py {名前} --inputs --context '{"target":"…"}' # 開始ステートの取得 python .github/skills/statemachine-use/scripts/next_state.py {名前} --initial-state ``` `--inputs` の `missing` が空でなければ(終了コード 4)、**値を推測して進めない。** `inputs` の `label` で利用者に訊き、揃ってから開始する。以降のアクションの `{{キー}}` には `values` の値を入れる (任意で空の値は空文字)。 出力された `state_id` を現在のステートとして実行を開始する。 **agent-herd の有無を 1 回だけ確かめる。** あれば遷移条件の判定を判定 AI(judge)に任せ、 自分で YES/NO を考えない(③ で使う)。無ければ従来どおり自分で評価する——定義は同じでよい。 ```bash command -v agent-herd >/dev/null 2>&1 && agent-herd config --check judge >/dev/null 2>&1 \ && echo "JUDGE=yes" || echo "JUDGE=no" ``` > `agent-herd harness statemachine --workflow …` が使える環境では、この手順をすべて > ハーネスに任せる方が確実(ハーネスは同じ判定 AI を自分で呼ぶ)。会話の中で 1 ステートずつ > 回すときだけ、以下の手順に従う。 ### Step 1〜N: ステートループ(terminal まで繰り返す) **現在のステートに入ったことを宣言する(毎ステート必須):** ``` ## [現在のステート: {state_id}] ``` **① アクションを実行する(LLM)** 現在のステートのアクションプロンプトを実行し、出力を `last_output` として記録する。 > **重要**: アクション実行前に条件を確認してはならない。出力が確定してから条件リストを取得する。 `judge:` を宣言したステート(判定だけのステート)は、アクションの代わりに次を行う: ```bash python .github/skills/statemachine-use/scripts/next_state.py {名前} --state {現在のstate_id} --state-judge ``` - `judge` が `null` なら通常のステート。上のとおりアクションを実行する。 - JUDGE=yes なら、`question` を `agent-herd judge` に渡す(stdin は `input` の展開文)。答えの `choice` が `last_output`(`other` なら `unsure` の語)。**自分では選ばない。** - JUDGE=no なら、`fallback_action` をそのまま実行し、選択肢のキーを 1 語だけ答える。 **② 条件を自動評価する(Python)** 状態値は `--context` の JSON オブジェクトで渡す(`last_output` と各 `output_key`)。 ```bash python .github/skills/statemachine-use/scripts/next_state.py {名前} \ --state {現在のstate_id} --auto-eval \ --context '{"last_output":"{last_outputの第1行}"}' ``` 遷移先がここで確定する応答は 2 形。どちらも ③④ を飛ばして ⑤ へ進む: - `auto_advance: true` — 無条件トランジション。`conditions` は返らず `next_state` が遷移先。 - `resolved` が `null` 以外 — `condition_rule` だけで確定。 > `auto_advance` が省くのは**条件評価だけ**。① のアクション実行と `output_validator` による成功確認は省略しない。 > アクションが失敗したステートから遷移してはならない。 `resolved` が `null` の場合のみ `needs_llm_eval: true` の条件を LLM で評価する。 > 旧ハーネス互換として `--list-conditions` / `--last-output` / `--output KEY=VALUE` も受け付ける。 > 旧引数は `--context` に無いキーの補完としてのみ効く。新規の呼び出しでは使わない。 **③ 残った条件を評価する(JUDGE=yes なら判定 AI、no なら LLM)** *JUDGE=yes* — ② の応答にある `judge_questions` をそのまま `agent-herd judge` に渡す。 状態(アクションの出力全文)は stdin。自分では評価しない: ```bash printf '%s' "{last_output 全文}" | agent-herd judge --questions '{②の judge_questions}' > .statemachine/{名前}/judge.json ``` *JUDGE=no* — `needs_llm_eval: true` の条件のみ `last_output` に対して YES / NO で評価し、JSON を構築する: ```json {"1": false} ``` (`needs_llm_eval: false` の条件インデックスは省略可。`--eval` 渡し時に自動上書きされる) **④ 遷移先を確定する(Python)** ```bash # JUDGE=yes: judge の答えをそのまま渡す(choice も boolean もスクリプトが読む) python .github/skills/statemachine-use/scripts/next_state.py {名前} \ --state {現在のstate_id} --judge-answers "$(cat .statemachine/{名前}/judge.json)" \ --context '{"last_output":"{last_outputの第1行}"}' # JUDGE=no: 自分で評価した JSON を渡す python .github/skills/statemachine-use/scripts/next_state.py {名前} \ --state {現在のstate_id} --eval '{"1": false}' \ --context '{"last_output":"{last_outputの第1行}"}' ``` 出力: 次の `state_id`、`NONE`(一致なし)、`TERMINAL`(終端) > `condition_rule` がある条件は `--context` から自動評価され、`--eval` / `--judge-answers` の値を上書きする。 > `--judge-answers` が終了コード 3 で止まったら、judge が確度不足で決めていない。その条件だけ > 自分で評価して `--eval` で渡し直す。 **⑤ 完了を記録する** ``` ## [ステート {state_id} 完了] - 出力: {last_outputの第1行}
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub