最近、出社して最初に開くのはコードエディタではない。社内Slackのボットだ。名前はAnvil。こう書くと自動化の成功談に見えるが、ボットを一つ置いただけでは一日は変わらなかった。変化を生んだのは、誰が仕事を始めても同じ品質に届くよう、ボットの後ろに共通のハーネスを置いたことだった。
以前はQAから「この文言を変えると、どこまで影響しますか」と聞かれるたびに手を止めた。頭の中の文脈を下ろし、リポジトリを開き、該当コードをたどり、返事をしてから元の仕事を組み立て直す。小さな質問が半日を奪うこともあった。QAは回答を待ち、私は集中力が戻るのを待つ。二人とも予定していた作業を進められない。
今はQAがAnvilにチケット番号と短い依頼を送る。ボットはチケットとコードを読み、影響範囲を判定する。小さな修正ならコードを直し、品質検査を通してMRを作る。範囲が広ければ実装前に担当者へ承認を求める。私は昼ごろにたまったMRをまとめて見る。速さより大切なのは、Slackから始まった変更も、私がターミナルで始めた変更も同じ規則を通ることだ。
本文の数値は、私が提供した一件の社内振り返りに限られる。製品性能のベンチマークではなく、別の組織でも同じ結果になるという主張でもない。公開情報として確認できる技術説明にはClaude Code、ESLint、TypeScriptの公式文書を付けた。Anvilという名称、業務の流れ、結果の数値は社内運用メモを材料にしている。
このテーマを取り上げた理由
依頼をボットに送っただけでは、仕事を任せたことにならない。結果のコードを私が最初から全部読まなければならないなら、入力欄が変わっただけだ。手を離した後も同じ水準の結果になる根拠があって、初めて委任と呼べる。その根拠はモデルの賢さではなく、プロジェクトの規則から生まれた。
最初はプロンプトを長くすればよいと思っていた。しかし「一か月は28日として計算する」「最低注文額は5万ウォン」「通貨単位が不正なら保存しない」といった基準を、毎回チャットに貼るのは無理がある。コードのどこかには実装済みでも、新しい作業を始めた全員が同じ順番で見つけられる形ではなかった。
そこで方針ファイル、影響度、検査コマンド、人に引き渡す条件を一つの運用定義に集めた。Slackとターミナルは入口が違うだけで、内側の判断基準は同じだ。Anvil自体は新しい知能ではない。普段使うコーディングエージェントを非対話モードで呼ぶ薄い入口である。Claude Codeのヘッドレス実行文書にも、一度の問い合わせを実行して終了するclaude -pが記載されている。
画面は簡単にまねできる。難しいのは運用定義だ。リポジトリの文脈、権限、終了時の検査が揃わないままSlackの入口だけ作ると、開発者以外の人が不揃いな結果へ早く到達する仕組みになってしまう。
実際に基準にした仕事
基準にしたのは一件のQAチケットだ。依頼を受けたら対象リポジトリと関連ファイルを探し、変更が方針や中核モジュールに触れるかを確かめる。影響が小さければ修正と検査を進めてMRを作る。大きければ、コードを変える前に担当者の承認を待つ。どの経路でも機能の意図とリリースの最終判断は人が持つ。
Slackから始まる経路は意図的に単純にした。
[QAからのSlack依頼]
→ Anvil
→ コーディングエージェントを非対話で実行
→ プロジェクト規則と影響度を確認
→ コード変更
→ lint · typecheck · test
→ MR作成または担当者への承認依頼
Slackはインターフェースにすぎない。プロジェクト定義、検査コマンド、遮断規則が実際のハーネスだ。Claude Codeの設定を調べる公式文書でも、プロジェクト指示は文脈を与え、権限とフックは制限を強制すると区別している。「危険なコマンドを使わない」と文書に書くことと、実行できないようにすることは別だ。
この分離のおかげで、ターミナルから始める仕事にも同じ規則を使える。サブエージェントは長い会話履歴を受け取らなくても、月の日数や必須検査を共有資料から読める。入口が変わっても品質の起点は変わらない。
実際に見比べた点
比べたのはモデルではなく、「検査して」と頼むだけの依頼と、検査が通らない限り応答を終えられない依頼だった。エージェントが停止しようとする時点で品質ゲートを動かす。自動修正できるlint問題はESLint --fixで直し、残ったlintエラー、tsc --noEmit、対象テストがすべて通ってから結果を返す。Claude Codeのフックガイドには、ライフサイクルイベントとStopフックで決まったコマンドを実行する方法が示されている。
危険な動作は二層に分けた。rm -rf、DROP TABLE、.env作成のように、この経路では実行自体が危険なものは遮断する。git push --forceや--no-verifyは例外的に必要になる場合があるため、人が確認して記録を残したときだけ通す。鍛冶場なら、前者は炉の周りの柵、後者は有資格者を呼ぶ警告札に近い。
| 影響度 | 例 | 経路 |
|---|---|---|
| MINOR | 文言修正、単純な対応付け | 実装 → 品質ゲート → MR |
| MODERATE | コンポーネント構造、スタイル整理 | 実装 → 品質ゲート → 担当者確認 |
| MAJOR | 方針定数、検証規則、中核モジュール | 事前承認 → 実装 → MR確認 |
MAJORに意図的な待ち時間を置いたからこそ、MINORとMODERATEを広く開けられた。すべての変更を同じ速さで通すのは自動化ではなく、検証を省くことだ。反対に誤字修正まで事前承認にすると、ボットは待ち時間を自動化するだけになる。
影響度はプロジェクトごとのパスと方針キーワードで決める。万能なセキュリティ分類ではない。あるリポジトリの文言ファイルが、別のリポジトリでは価格を決めることもある。大事なのはラベルより、想定影響と人が入る時点を明示してつなぐことだった。
運用で止まる部分
コードを直接書く時間は減ったが、仕事が消えたわけではない。個人的な感覚では、実装は約60%からほぼ0%、テスト作成は約20%からほぼ0%になった。一方で方針と要件を書く仕事は約60%、レビューは約30%、マージと配布は約10%まで増えた。勤怠記録を測った数値ではなく、役割の変化を振り返った目安なので、前後の合計はきれいな100にはならない。
キーボードは今も使う。ただしコードより、利用者の流れ、入力検証、エラーメッセージ、失敗時の振る舞いを書く。「ログインを改善する」という一行は、どの画面から始まり、何が入力され、失敗したら何を見せ、次にどこへ進むかを書いた作業文書になった。これはエージェントに渡す仕様であり、人が結果を受け入れるための基準でもある。
新しい流れも平凡なところで壊れた。エラーモーダルが複数ある画面で、ボットが修正対象のリポジトリを決められず、最初の入力で止まったことがある。候補リポジトリを利用者が選べる復旧経路を加えると先へ進めた。失敗した自動化を使う人の体験も設計範囲だった。
モデルの能力より、曖昧な方針が原因になる失敗のほうが多かった。「当然こうする」と誰かの頭にだけある業務規則は、エージェントには読めない。失敗が続くほど、コードを直す前に方針文書とハーネスを直すようになった。モデルが私の頭を読めないことは不具合ではなく、システムの境界である。
テストが通っても機能は欠けた
完了した一件を二つの尺度で見直した。技術的完成度は85%、仕様反映率は62.5%だった。Jestテスト151件はすべて通り、モーダルの6状態も揃っていた。それでも仕様40項目と照合すると、製品に反映されたのは25項目。欠けた15項目はカテゴリ方針、担当者の範囲、検索フィルターなど、lintや型、既存テストからは推測できない業務規則だった。
奇妙なのは、エージェントが不足をまったく知らなかったわけではない点だ。報告書にはカテゴリ、担当者表示、保存確認が未完了だと書かれていた。空欄を見つけて記録したのに、その空欄を完了条件へ結び付けずに終わった。コードが有効で既知のテストが緑なら、技術ゲートには見えない失敗だった。
そこで振る舞いと仕様を確認する第二の層を足し始めた。変更が触れる方針を探し、対応する受け入れ基準を実行し、文書と結果が合わなければ警告する。まだ全プロジェクトで動く段階ではなく、書かれていない規則まで自動で発見できるわけでもない。今の目標は控えめだ。「何を満たせば完了か」を実行可能な確認へつなぎ、未完項目が報告書だけに残って通過しないようにする。
もう一度選ぶなら
ボットからは作らない。同じ仕事を二人が始めても、同じ規則と同じ検査に出会えるかを先に確かめる。そこが揃っていなければ、Slackボットは既存の混乱に早く入る入口になる。
残す境界は三つ。危険なコマンドはプロンプトではなく実行制御で止める。影響が大きいほど人の承認を早める。テスト状態と要件状態は別の点数にする。技術ゲートはコードが壊れていないかを答え、受け入れ確認は作るつもりだったものかを答える。
人は流れから消えない。金銭、顧客データ、中核方針に関わる変更は、その分野を知る人が承認する。失敗した自動化からの復旧と最終リリースにも担当者を置く。人を抜くことが目的ではない。繰り返しの確認は機械に渡し、判断で結果が変わる場所に人の時間を使う。
適用前のチェックリスト
- チームが何度も口頭で説明する方針を三つ書き出す。
- 自動実行、人の確認、実行禁止をコマンド単位で分ける。
- lint、型検査、テストを任意の依頼ではなく終了時の強制ゲートにする。
- 文言と対応付け、コンポーネント、方針と中核変更を別の承認経路に置く。
- 合格したテスト数とは別に、仕様項目の反映率を数える。
- 分類に失敗したら利用者がリポジトリや次の行動を選べる復旧画面を用意する。
- 最終マージと外部配布の責任者を一人に決める。
社内Slackボットから始める必要はない。ターミナルで同じプロジェクト定義とフックを使うだけでも価値の多くを得られる。一日に何度も繰り返す質問を一つ選び、低リスク変更だけMRまで送ってみる。節約したと称する時間より、再オープンされたMRと抜けた要件の数を先に見るほうがよい。
運用の境界を記録する
この記事の社内振り返りは一つの運用事例であり、同じ統制が別のリポジトリで検証済み、または同じ効果を出す証拠ではありません。エージェントが変更を始める前に、影響するパス、リスク区分、承認の時点、必要な確認を記録するために使ってください。AIエージェントの変更リスク用ワークシートをダウンロード。
確認した資料
- Claude Codeのヘッドレス実行:
claude -pによる非対話実行 - Claude Codeのフックガイド:ライフサイクルイベントとStop時点の検査
- Claude Codeの設定:プロジェクト指示、権限、共有フック
- Claude Code設定のデバッグ:文脈を与える指示と強制制御の区別
- ESLintのコマンドライン:
--fixで修正可能な問題を処理する方法 - TypeScriptコンパイラオプション:
--noEmitで出力せずに型を検査する方法
私の一日が変わったのは、コードを書かなくなったからではない。何を作るかを以前より正確に書き、境界の内側ではモデルを動かし、外側では人が判断するようにしたからだ。ハーネスエンジニアリングはモデルを強くする技術というより、どこまで任せられるかを見える形にする仕事だった。
参考にした資料
報道内容、公式文書、政策背景、製品情報、変わる可能性のある主張を確認するために参照した公開情報です。
- Claude Code headless modeAnthropic確認した内容: claude -pによる非対話実行; チャット画面の裏側にある実行方式確認日: 2026-08-20
- Claude Code hooks guideAnthropic確認した内容: ライフサイクルフック; Stop時の完了条件; コマンドで強制する境界確認日: 2026-08-20
- Claude Code settingsAnthropic確認した内容: プロジェクト指示; 権限とフックの共有確認日: 2026-08-20
- Debug your Claude Code configurationAnthropic確認した内容: 文脈を与える指示と強制制御の違い確認日: 2026-08-20
- ESLint command line interfaceESLint確認した内容: --fixによる自動修正確認日: 2026-08-20
- TypeScript compiler optionsMicrosoft確認した内容: --noEmitによる型検査確認日: 2026-08-20



