開発の効率化でも、AIを組み込んだ機能の実装でも、つい「AIに任せれば楽になる」と考えがちです。
しかし実際にやってみると、AIの出力は安定しません。同じ指示でも結果がブレます。頼んだことをやらないこともあります。
これはAIの欠陥ではなく、AIの特性です。確率的に次のトークンを生成する仕組みで、決定論的な動作を期待するのは設計として間違っています。
ではどうするか。AIに任せる範囲を限定するのです。
AIに任せる範囲を限定するには
AIに任せる範囲を限定するとは、具体的にはどういうことでしょうか。
AIの仕事を分解すると、大きく三つの要素があります。
- 何をやるか(処理内容)
- いつやるか(実行タイミング)
- 何を返すか(出力形式)
これらのうち、決定論的に決められる部分をAIから取り上げます。
以下ではその一例を紹介します。
1. ルールベース処理を切り離す(静的解析)
AIを使って開発するとき、コードのチェックまでAIに任せたくなります。しかし明確なルールがあるチェックまで、AIに「判断」させてはいけません。
例えば、コーディング規約として「インデントは2スペース」「1行は120文字以内」「変数名はキャメルケース」というルールがあるとします。これらは明確なルールであり、静的解析ツールで決定論的に処理できます。
AIに「規約に違反していないかチェックして」と頼むとどうなるでしょうか。
- 同じコードでも、実行するたびに結果がブレる
- 違反を見逃すことがある
- 「違反していません」と言いながら違反していることがある
ESLintのような静的解析ツールに任せれば、誰が何度実行しても同じ結果が得られます。
// ESLint設定例import { defineConfig } from "eslint/config";export default defineConfig([ { files: ["src/**/*.js"], rules: { indent: ["error", 2], "max-len": ["error", { code: 120 }], camelcase: ["error"], }, }]);コーディング規約だけではありません。以下のようなルールが明確なものは、すべて静的解析に切り出せます。
- 型の整合性 → 型チェッカー
- セキュリティパターン → SAST
- データフォーマットのバリデーション → スキーマ検証
AIには「曖昧な判断が必要な部分」だけを任せます。設計の妥当性・可読性・文脈に依存する判断。これらは人間がルールを書き下せない領域であり、AIの出番です。
2. 実行タイミングを保証する(Hooks)
AIを使って開発するとき、処理をスクリプト化しても、それを 「いつ実行するか」がAI任せでは十分に活かせません。
「ファイルを編集したら静的解析を実行して」と頼んでも、実行されないことがあります。「もう実行しました」と言って実行していないこともあります。これもAIの特性です。
ここではClaude Codeを例に説明します。Claude CodeはAnthropicが提供するAIコーディングツールで、Hooksという仕組みを持っています。Hooksを使えば、特定のイベントに対して自動的にコマンドを実行させることができます。
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "npx eslint --fix 1>&2 || exit 2" } ] } ] }}この設定で「EditまたはWriteが実行されたら、必ずESLintを実施する」が保証されます。AIの判断に依存しません。
git hooksやCIでも似たようなことはできます。ただし、これらはAIの作業が終わった後に動きます。問題が見つかっても、人間がAIに「直して」と指示し直す必要があります。
AIの実行サイクルの中で動くHooksなら、問題があればその場でAIに差し戻せます。

ポイントは、AIの作業の途中で介入できる仕組みがあるかどうかです。Claude Codeに限らず、AIエージェントを使うなら、こうした仕組みの有無を確認しておくとよいでしょう。
3. 出力形式を固定する(JSONスキーマ)
プロダクトにAIを組み込むとき、AIの出力を後続の処理に渡す必要があります。しかしAIの出力は自由形式だと安定しません。同じ質問でも、箇条書きで返ってきたり、文章で返ってきたりします。パースに失敗したり、期待したフィールドがなかったりします。
「こういう形式で返して」とプロンプトで指示しても、守られるとは限りません。
JSONスキーマとStructured Outputsを使えば、出力形式を強制できます。
{ "type": "object", "properties": { "title": { "type": "string" }, "priority": { "enum": ["high", "medium", "low"] }, "tasks": { "type": "array", "items": { "type": "string" } } }, "required": ["title", "priority", "tasks"]}Structured Outputsは、OpenAIやGoogleなどのAI APIが提供する、スキーマ準拠を保証する機能です。プロンプトでの「お願い」ではなく、システムとして形式を強制します。上記のJSONスキーマの例であれば、priorityは必ず「high」「medium」「low」のいずれかになり、tasksは必ず配列で出力されます。後続の処理は、この出力形式を前提として構成することができます。
なぜ任せる範囲を限定するのか
これら3つに共通するのは「AIに任せる範囲を限定する」という考え方です。
AIに任せる範囲が広いほど、確率的な要素が増えます。逆に、任せる範囲を限定すれば、確率的な要素は減ります。

上で紹介したのはあくまで一例です。重要なのは、AIに任せようとしている作業の中から 「実はAIに任せなくてもよい部分」を見つけ出し、それをコード化することです。
AIには、文脈を理解した判断、創造的な生成、曖昧な要求の解釈、といった 「本当にAIでなければできないこと」だけを任せます。これらは人間がルールを書き下せない領域であり、AIの得意分野です。
一方で、ルールが明確な処理、決まった形式での出力、毎回必ず実行すべき処理はコードで書けるため、AIに任せず確実に処理が行われるようにします。
人間に対するアプローチをAIにも
判断余地がある処理とルールに基づく明確な処理の分離は、もともと人間が行う場合と同じです。
例えばDevOpsの自動化を重視する姿勢は、言い換えれば「手作業を信頼しないで済む」設計とも言えます。 これは、人間が本質的に確率的な存在だからであり、作業者が悪いわけではありません。注意力には波があり、記憶は曖昧で、同じ作業でも毎回微妙に違うやり方をします。
- 手順書通りにやったつもりが間違える
- 疲れていると省略する
- 自分だけは大丈夫だと思う
手順書 → 解釈・判断して実行(守らないこともある)コード → 自動実行(必ず守る)Infrastructure as Code、CI/CD、Policy as Code。これらはすべて「人間の判断に依存しない」仕組みです。
AIもまた、次のトークンを確率分布から選ぶ仕組みで動いており、確率的な存在です。人間と同じく、同じ入力でも毎回微妙に違う出力をします。
したがって、人間が実践してきたことはAIにも適用できるはずです。
自律性と統制
「AIが自律的になってきたのに、制限が必要なの?」という疑問もあるかもしれません。
人間は最も自律的な存在ですが、開発現場ではワークフローに従って動いています。チケット管理、ブランチ戦略、レビュープロセス。どれも「自律的な人間」を統制し、確実性を高める仕組みです。 自律的であることと、統制が不要であることは別です。むしろ自律的だからこそ、統制が必要になります。
人間は、承認フローやレビュープロセスといった「コード外」の仕組みで統制が実現されてきました。しかし最近では、これらもコード寄りになってきており、CI/CDで承認ステップを強制したり、PRがないとマージできないようにしたりしています。 一方で、AIは最初から「コード」で制御できます。Hooksやスキーマを使えば、運用ルールではなくシステムとして制約を埋め込めます。

まとめ
AIに任せないというのは、特別なことではありません。 人間が実践してきたことを、AIにも同じように適用するだけです。
この発想を進めると、ワークフロー全体をコードで制御する仕組みも考えられます。工程のような状態管理をAIから分離してワークフローエンジンに任せ、AIには「今のステップ」だけを渡す、といった具合です。
少なくとも、AIが人間の能力を大きく超え、何の統制もなくAI同士ですべてうまくやれるようになるまでは、この構造は必要でしょう。もっとも、AIの進化は速いので、この考え自体が半年後にはひっくり返っているかもしれません。
ただし、今この瞬間にAIを使うなら、任せる範囲を限定することがAIをうまく使うコツです。