
MCP
イベント
マガジン
技術ブログ
こんにちは、ソフトクリエイトでエンジニアをしているKです。 以前、 こちらのブログ で「AI Challenge Day」へ参加した感想を投稿した以来、久しぶりの投稿になります! 最近は、主にAIエージェント周りの開発や検証に取り組んでいます。 はじめに
この記事の要点 AIエージェントと開発を進める中で、「修正を重ねているのに目的に近づいていない」「何か違う」と感じることがあります。その違和感を問いに変え、調査・検証で得た教訓を、次の開発で使える知識として残す。そのための仕組みを作っています。本稿では、この取り組みのうち、蓄積した教訓を改善に活用する効果を比較実験で確かめ、教訓の更新と後日の活用を開発記録から確認します。 Codexと進める開発では、不具合を修正するだけでなく、調査・修正・検証の進め方自体を評価し、必要に応じて組み直します。そこに、過去の問題・解決策・適用条件を蓄積して活用する仕組みを組み合わせています。知識カタログ
はじめに こんにちは、Insight Edgeの小林まさみつです。 ※ 本記事はPoC案件での技術検証の内容であり、商用環境での実用性は今後の検証課題です Claude Codeのようなコーディングエージェントに実装を任せる場面は珍しくなくなりました。一方で、実装を任せたあとの「意図どおりに動いているかを確認する」「レビューする」「マージして後片付けをする」といった作業は、人の手に残りがちです。 今回は、あるPoC案件の開発で、タスクの起票からレビュー、マージ依頼までをAIエージェントに任せる仕組みを作って運用しました。本記事では、背景、設計の考え方であるハーネスエンジニアリング、具体的な仕組み、導入結果と今後の課題を紹介します。 なお、本記事は実務で行った内容をもとにしていますが、案件を特定できないよう、案件の内容はぼかして書いています。 TL;DR タスクの起票、設計、実装、レビュー、マージ依頼、後片付けをAIエージェントに任せ、人は「planとDRのレビュー」と「マージ」の判断だけを担当した 仕組みで強制する制約( deny 、フック、CI)と、プロンプト側で規定する振る舞い(レビューの3分類など)を分けて設計した PoCでの成果であり、商用の開発で通用するかは今後の検証課題 目次 背景 ハーネスエンジニアリングを活用した開発 具体的な仕組み 導入結果 今後の課題 まとめ 参考文献 背景 対象は、ドキュメントを分析し、意思決定を支援するレポートを作るPoCです。バックエンドはFastAPI、フロントエンドはReact、分析はクラウド上のLLMを使ったマルチエージェントで行っています。 このPoCでは、次の状況が重なっていました。 他案件のリリースと時期が重なり、人手が足りない 開発者が1人のため、コードレビューをする人がいない 開発タスクが60件を超え、どれも「worktreeを切る → 実装 → PR → レビュー → マージ → 後片付け」という同じ作業の繰り返しになる 一方で、PoCなので要件が限られており、試したい手法をすぐ検証できる立場でもありました。そこで、定型作業をまとめてAIに渡し、人は「何を作るか」の判断に集中する形を目指しました。 実際にどの程度の範囲を回したかは、タスクの内訳で伝わりやすいと思います。認証認可、セキュリティ対策、性能とコストの改善、テスト戦略とE2Eテスト、インフラのコード化とCI/CD、アクセシビリティの改善といった、機能要件から非機能要件、DevOpsまで幅広い領域が含まれます。これらすべてのタスクを、この仕組みで進めました。 ハーネスエンジニアリングを活用した開発 この仕組みを設計するうえで参考にしたのが、Birgitta Böckelerさんの記事 Harness engineering for coding agent users (martinfowler.com、2026年4月)です。 Agent = Model + Harness 記事では、エージェントを「Agent = Model + Harness」と捉えます。ハーネスとは、モデル以外のすべて、つまりエージェントを取り巻く仕組みのことです。エージェント製品に最初から組み込まれた部分(inner harness)と、利用者が自分のユースケース向けに作る部分(outer harness)があり、本記事で扱うのは後者です。 outer harnessは、2種類の制御で構成されます。 ガイド :エージェントが動く前に方向づける(feedforward) センサー :動いた結果を観測し、自己修正させる(feedback) さらに、それぞれを次の2種類に分けて考えられます。 computational :機械的に決まる。テスト、リンター、権限設定など inferential :LLMの判断に頼る。レビューや方針の記述など 人の役割は、同じ問題が繰り返されたときに、ガイドとセンサーを改善してエージェントを操ることです。 この関係を、本記事の内容に当てはめて図にすると次のようになります。 ハーネス概要 この図は、Böckelerさんの記事にある図を、本プロジェクトの部品で描き直したものです。原典の図は 記事 で確認できます。 人がやること、AIがやること ハーネスで周囲を固めたうえで、人の仕事は「判断」に絞りました。 担当 やること 人 起票の指示、着手の指示、planファイルとDecision Recordのレビュー(重要なタスクはテストケースも確認)、マージ、必要に応じたデプロイ作業 AI 要望の分解と調査、Issueの起票、カンバンの移動、設計、実装、テスト、PR作成、デモ動画の撮影と添付、レビューと指摘対応、マージ依頼、worktreeなどの後片付け Decision Record(DR)は、意思決定の理由と採用しなかった代替案を残すためのMarkdownです。タスクごとにAIが書き、人が読んで方針を確認します。 このプロジェクトの部品を並べる 本プロジェクトの部品を、ガイドとセンサー、computationalとinferentialの2軸で整理すると次のようになります。各部品の詳細は、次章で紹介します。 computational(機械的) inferential(LLMの判断) ガイド (事前) settings.json の deny でPRのマージを禁止、レビュー系エージェントに書き込みツールを与えない、worktreeによる作業の分離 CLAUDE.md の設計原則とコメント規約、DRのテンプレート、Issueの「やらないこと」 センサー (事後) 編集後のformatフック、コミット時のシークレット検査、CI(lint、単体テスト、E2E、ビジュアルとa11yの検査、ライセンス検査)、PRへのカバレッジコメント、ミューテーションテスト レビュー指摘の3分類、デモ動画の比較 この表を作ると、何が「強制」で何が「約束」なのかが見えます。実際には、仕組みで強制できているのは、 deny 、ツール権限、シークレット検査、CIだけです。ループの3ラウンド上限や、指摘の3分類、Slack通知の条件は、プロンプトに書いた約束にすぎません。この線引きをどう考えるかは、 今後の課題 で触れます。 具体的な仕組み 構成 構成は、Claude Codeのスキル2つ( /create-task 、 /run-task )と、サブエージェント3つ(planエージェント、devエージェント、reviewエージェント)です。 エージェントのワークフロー ポイントは、エージェント同士が直接やり取りしないことです。司令塔(Orchestrator、 /run-task )が SendMessage で仲介するため、各エージェントは自分の役割だけを見ればよくなります。また、Claude Codeのサブエージェント機能を利用することで、コンテキストを分離しつつ、必要な情報を共有できます。 1タスクの流れ 全体の流れは次のとおりです。人が関わるのは、planとDRのレビューと、最後のマージだけです。 起票( /create-task ) :要望を分解し、コードベースを並列に調査して既存Issueとの重複を判定します。続いて、選択式の質問で要件を固め、優先度とストーリーポイントを見積もります。最終確認を取ったうえで、固定の節構成(背景・目的、要件、やること、やらないこと、依存関係)と固定のラベル(優先度、ストーリーポイント、変更対象項目など)でIssueを起票し、カンバンに登録します。「やらないこと」を明記しておくと、後のレビューで範囲の逸脱を検出できます。 たとえば、次のように要望を一言伝えるだけで起票されます。以下は、実際に起票されたIssueの例です(一部をマスクしています)。 /create-task 画面サイズが大きいと余白が目立つ。見づらいので幅をディスプレイサイズに応じて調整したい 起票されたIssue 設計(planエージェント) :Issueを確認し、作業用のworktreeとブランチを作ります。カンバンを「進行中」に移し、planファイルとDRを書きます。planが完了するまで実装は始めません。人が確認するポイントはここです。正しい設計が行われているかをレビューし、必要に応じて修正指示を出します。問題が無くなれば、実装フェーズに進みます。 planファイルには、背景と要件の要約、設計方針の結論、ファイル単位の実装ステップ、テスト方針、そして「設計上の懸念点・判断が分かれる点」を書かせます。最後の項目は、人がレビューするときの着眼点になります。DRには、背景、決定事項とその理由、検討した代替案と採用しなかった理由を残します。後から「なぜこうなっているのか」をたどるための記録です。 実装(devエージェント) :planに沿って実装します。テストは必須で、LLM呼び出しのみ時間とコストの兼ね合いからモックにします。formatとテストを通してからPRを作り、PRの先頭行にIssueを閉じる記法を書いてカンバンと連動させます。さらに、人のレビューをしやすくするために、変更前後の画面を並べたデモ動画を録画してPRに添付します。後段のレビュー指摘を受け取った際、内容に同意できない場合は、反論してよいことにしています。 一方で、force push、マージ、Issueの「やらないこと」への着手は禁止です。 PRに添付されたデモ動画。左が変更前、右が変更後 レビュー(reviewエージェント) :次の8観点をレビューします。 シークレットの混入 「やらないこと」への逸脱 要件の充足 アーキテクチャ方針が適切か テストの有無と妥当性 Decision Recordが適切に記録されているか 実装品質 セキュリティ これに加えて、デモ動画の挙動がIssueの要件と一致しているかも確認します。ループは最大3ラウンドで、反論が2往復続いた場合は打ち切って人に判断を仰ぎます。これは過剰な議論や実装を防ぐための仕組みです。試しにラウンド数に制限をかけずに運用してみたところ、4ラウンド以降は些細な指摘が延々と続き、効率が大幅に低下しました。そのため、3ラウンドを上限としました。 reviewerエージェントが投稿したレビューコメントの例 マージと後片付け :レビューが承認されると、SlackのIncoming Webhookにより通知が届きます。人が内容を確認してマージすると、司令塔がマージを確認し、worktree、ローカルブランチ、リモートブランチを削除して main を更新します。マージだけは人が握り、それ以外は自動で片付く設計です。また、Slackのメッセージには追加で対応が必要な事柄(例えば、インフラリソースの変更など)も含めるようにし、何をすれば良いかが一目でわかるように工夫しています。 実装例:computationalなガイドとセンサー 強制力のある部分は、設定ファイルに数行書くだけで実現できます。たとえば、PRのマージをエージェントに禁止し、ファイルを編集するたびに自動でフォーマットをかける設定は、 .claude/settings.json に次のように書きます。 { " permissions ": { " deny ": [ " Bash(gh pr merge:*) " ] } , " hooks ": { " PostToolUse ": [ { " matcher ": " Edit|Write|MultiEdit ", " hooks ": [{ " type ": " command ", " command ": " mise run format " }] } ] } } deny はプロンプトでの「マージしないでください」と違い、エージェントがこのコマンドを実行できなくなります。実は最初の版では、reviewエージェントが承認後に自動でマージしていました。マージだけは人が握る、という方針をルールとして書くのではなく、仕組みで担保した例です。 --- name : review description : devエージェントが作成したPRをレビューし、承認時は司令塔へ報告する。マージは行わない。 tools : Bash, Read, Glob, Grep, SendMessage model : opus --- コミット時のシークレット検査(pre-commit)は、あえて検査を1つに絞っています。整形や単体テストは数十秒かかり、コミットのたびに走らせるには重いためです。フックが守るのは、一度コミットすると履歴から消すのが極めて高コストな「シークレット」だけにし、残りはCIに任せています。CIと同じコマンド、同じgitleaksのバージョンを使うため、フックが通ればCIでも通ります。なお、前述のPostToolUseフックにより、ファイルを編集するたびに自動でフォーマットがかかるようになっているため、基本的にはCIでLinter/Formatterによる失敗は起こりません。 #!/bin/sh set -e exec mise run scan:secrets:staged センサーの事例①:指摘を握りつぶさせない3分類 最初のレビューの運用では、「軽微な指摘ならAPPROVEしてコメントを残す」という余地がありました。その結果、マージ済みの3タスクで、10件以上の指摘が誰にも対応されないまま残りました。「任意対応」は、誰も対応しないことの丁寧な言い換えでした。 そこで、レビューの指摘を必ず次の3つのどれかに分類するようにしました。「任意」という分類は作りません。 分類 判断 扱い 狙い 要修正 このPRの目的や品質に必要 このPRで直す 品質を守り、要件を満たす 別タスク化 重要ではないが、いずれ直すべき 優先度を下げてIssueを起票する レビュー負荷の軽減と、過剰な実装の防止 取り下げ 些細で、直しても価値がほとんどない 理由を書いて撤回する 些細な対応の繰り返しによる、フローの長期化と無駄な実装の防止 「別タスク化」には、いまは過剰でも将来あるとよい改善も含めます。起票が終わるまでは、Slack通知もマージもできない流れにしました。これで、指摘が放置されることも、些細な指摘でPRが延々と往復することも減りました。 reviewエージェントのプロンプトには、次のように書いています(抜粋)。 すべての指摘は、次の3分類のいずれかに必ず割り当てます。 「任意対応」「参考」「好みの問題」「余力があれば」といった曖昧な分類を作ることを禁止します。曖昧な分類は、対応されないことを丁寧に言い換えただけで、実質的に指摘を捨てています。 「取り下げ」を分類に用意しているのは、指摘の水準に達しない些細な気づきを無理に起票させないためです。すべてを別タスク化すると起票が膨張し、Projectsのボードが機能しなくなります。 直す価値があるかを自分に問い、無ければ取り下げてください。 禁止する分類の名前まで具体的に列挙し、「なぜ禁止するのか」「なぜこの分類が必要なのか」という理由を添えている点がポイントです。理由を書いておくと、エージェントが想定外のケースに出会っても、意図に沿って判断してくれます。判定は「要修正が1件でもあればREQUEST_CHANGES、0件ならAPPROVE」と機械的に決まるようにし、別タスク化を提案した指摘は、GitHubのレビュー本文にも「別タスク化を提案」と明記させています。レビューを読んだ人が、その指摘が放置されたのか、起票されたのかを判別できるようにするためです。 センサーの事例②:使い捨てのデモ動画 もう一つのセンサーが、デモ動画です。PRのベースとなるコミットと、PRのブランチを並べて録画し、PRに添付します。コードを読むだけでは気づきにくい「見た目や動きの食い違い」を、レビュー時に確認できます。動画は使い捨てで、リポジトリにはコミットしません。 工夫①:役割ごとにモデルを変える エージェントごとに、使うモデルを変えています。 エージェント モデル 理由 plan fable 設計の質が後工程の品質を決める dev sonnet 設計どおりにコードへ落とす作業のため review opus 品質を担保したいが、最上位のモデルではコストが高すぎるため、折衷案とした 工夫②:運用の手間を減らす 人とエージェントの手作業を、自動化と検出に置き換えました。 カンバンの移動 :カンバンの「Todo → 進行中」だけは、planエージェントが移します。残りはGitHub Projectsの自動化に任せています。PRの先頭行にIssueを閉じる記法があれば「レビュー中」へ、マージされれば「完了」へ移ります。 Slack通知 :通知は1タスクにつき1通に絞りました。送る条件は、レビューがAPPROVEであること、別タスクの起票が終わっていること、PRがマージ可能な状態( MERGEABLE かつ CLEAN )であること、の3つがすべて揃ったときです。なお、MCP経由で投稿すると投稿者が自分自身になり、通知が鳴りません。そのため、Slack Appを作り、Incoming Webhook経由で投稿しています。 投稿はシェルスクリプトに閉じ込めています。Webhook URLを取得し、このスクリプトの中でだけ扱うことで、URLがシェル履歴や会話ログに残らないようにしています。エージェントには、このスクリプトの実行だけを許可します。 #!/usr/bin/env bash set -euo pipefail WEBHOOK_URL = " <YOUR_WEBHOOK_URL_HERE> " RESPONSE = " $( curl -sS -X POST -H ' Content-type: application/json ' \ --data @ " $1 " " $WEBHOOK_URL " ) " unset WEBHOOK_URL [ " $RESPONSE " = "ok" ] || { echo " Slackへの送信に失敗: ${RESPONSE} " >&2; exit 3 ; } 通知の本文には、マージコマンドと、マージ後に人がやることも含めます。たとえばインフラの変更を伴うPRなら、「マージ後にterraform applyを実行し、実環境で確認する」といった手順まで書いてあるため、通知を開いた時点で何をすればよいかが分かります。 Slackに届くマージレビュー依頼の通知 コンフリクト :最初は、並行して進めるタスクのうちコンフリクトしそうな組を事前に予測しようとしましたが、予測は外れました。そこで、予測をやめて検出に切り替えました。人から1件のマージ報告を受けるたびに、司令塔が残りのPRについて次のコマンドを実行します。 for n in { 残っているPR番号 } ; do gh pr view $n --json number,mergeable,mergeStateStatus done 結果が MERGEABLE ならそのまま進め、 CONFLICTING ならdevエージェントにコンフリクトの解消を依頼します。 UNKNOWN は、GitHubがまだ判定を計算中の状態です。これをコンフリクトと誤認すると不要な取り込みを依頼してしまうため、数秒待ってから再取得するようにプロンプトに明記しています。解消はrebaseではなくmergeで行います。rebaseはforce pushが必要になり、devエージェントに禁止しているルールとぶつかるためです。同じPRで解消に2回失敗した場合は、別の変更を壊している可能性があるため、人にエスカレーションします。 導入結果 数値 0.8人月での開発実績は次のとおりです。 項目 値 マージしたPR(bot除く) 86本 PR作成からマージまでの時間 中央値 約0.8時間、平均 約2.6時間 テストコードとプロダクトコードの行数比 約1.7倍 人の工数 1タスクあたり平均 約15分 実装済みの主な機能/非機能は次のとおりです。 区分 主な内容 機能要件:分析 複数の観点での分析と集約、追加の質問チャット、根拠箇所へのトレーサビリティ、追加資料での再分析とバージョン管理、失敗分だけの再実行 機能要件:レポートとUX 経済性シミュレーション、リスク注記、履歴の検索、PDF・JSONの入出力、ブラウザを閉じても続く分析と進捗配信、ダークモードとアクセシビリティ対応 非機能:認証とセキュリティ MFA込みの認証認可とユーザー管理、LLM認証の鍵レス化、保存データの暗号化、シークレット・ライセンス検査 非機能:性能とコスト プロンプトキャッシュと圧縮、ストリーミング化、リトライ、分析結果の永続化 非機能:品質保証 単体テスト、E2E、ビジュアルリグレッションとa11yの自動監査、ミューテーションテスト DevOps・基盤 Terraformによるインフラのコード化、GitHub ActionsのCI、mainマージでの自動デプロイ、依存更新の自動化 定性的な変化 人がやることは、「何を作るか」と「planとDRのレビュー」に絞られました。他案件の対応と並行しながらでも、この案件を止めずに進められたのが大きな変化です。 今後の課題 良い点だけでなく、残っている課題や今後検証したい点も挙げておきます。 設計と適用範囲 AIの処理時間とレートリミット :人の工数は小さくなりましたが、PRが出るまでの時間は、AIの処理時間とレートリミットに縛られます。設計、実装、最大3ラウンドのレビュー、デモ動画の録画にはそれぞれ時間がかかります。並行して回すタスクは最大5件を目安にしていますが、増やすほどレートリミットにぶつかりやすくなります。また、並行するPRが増えるほど、コンフリクトの確率も上がります プロンプト上のルールをどこまで仕組みで強制するか :仕組みで強制できているのは deny 、ツール権限、シークレット検査、CIだけで、ループの3ラウンド上限、指摘の3分類、Slack通知の条件はプロンプトに書いた約束にすぎません。PoCではこれで十分でしたが、商用開発に適用するなら、ここが最初の論点になると考えています 商用開発でも同じ形が通用するか :今回のPoCは要件が限られており、効率を最優先できました。品質や監査の要求が高い商用開発で、同じ人の関与の度合いでよいかは、今後の検証課題です 運用上の課題 devエージェント、reviewエージェント、人が同じGitHubアカウントを使っているため、GitHub上の承認が形式的になりやすい。実際、自分のPRにはGitHubの機能におけるAPPROVEができず、コメントで代用している ミューテーションテストは手動で、適切な頻度は検討中 バックグラウンドで動くサブエージェントが、権限の確認待ちで何も言わずに止まることがある まとめ 本記事では、タスクの起票からレビュー、マージ依頼までをAIエージェントに任せる仕組みを、ハーネスエンジニアリングの考え方とあわせて紹介しました。人によるレビュー粒度とプロンプトの設計を適切に行えば、効果的に使えるという手応えを得ました。商用の開発でそのまま通用するかは、今後の検証課題です。 案件に依存せず、他のプロジェクトにも持ち出せると考えている点は次の3つです。 AIに作業を任せるだけでなく、周囲の仕組みを設計する :事前に縛るガイドだけでも、事後に検知するセンサーだけでも足りません。指摘の3分類のように、抜け道が実際に指摘の放置を生んだ箇所を、センサー側で塞ぎました。 強制できるものは仕組みに寄せる :マージの禁止は deny で、シークレットの混入はpre-commitとCIで防いでいます。プロンプトに書いた約束は、あくまで「守られやすくなる」だけです。また、最初から完成した仕組みではなく、自動マージの全廃、3分類、コンフリクト検出、デモ動画の比較方式への修正など、事故のたびにDRに残して直してきた結果です。 人の仕事を「作業」から「判断」に寄せる :人の仕事を「判断」に絞れたことが、1人でも複数の案件を並行して進められた一番の要因でした。 AIエージェントによる開発の半自動化を検討されている方の参考になれば幸いです。 参考文献 Harness engineering for coding agent users(Birgitta Böckeler、martinfowler.com)
動画
該当するコンテンツが見つかりませんでした












