
この記事は個人ブログと同じ内容です
はじめに|ハーネスエンジニアリングという言葉と、この記事のスコープ
ここ 1 年ほどで、「ハーネスエンジニアリング(harness engineering)」という言葉が、AI 開発の文脈でかなり頻繁に使われるようになってきた。 たとえば Martin Fowler の記事では、 「Agent = Model + Harness」 という図式で整理されている。AI エージェントの振る舞いを決めているのは、モデルそのものよりも、それを取り囲む guides(事前にエージェントを誘導する仕掛け) と sensors(事後にエージェントを観測・自己修正させる仕掛け) の組み合わせだ、という整理だ。 別の論者は、ハーネスを「LLM をラップするソフトウェア基盤の総体(ツール接続、メモリ、コンテキスト管理、検証、モジュール性)」と定義していたり、さらに別の場所では「AI のコントロールプレーン」と呼ばれていたりする。
要するに、 言葉自体は急速に広まっているが、定義の輪郭はまだバラバラ だというのが正直なところだ。 コーディングエージェントを動かす個人開発者の道具立てを指している場合もあれば、エンタープライズの「エージェント統治基盤」を指している場合もある。
なので、本稿ではハーネスエンジニアリングを一般論として論じるのはやめておく。 代わりに、論点を 1 つに絞る。
「アウトカムベースで開発を進めるときに、僕らが今ハーネスとして何を作っているのか」
これだけに集中して書く。 他の文脈――エージェントの内部構造、ツール統合、メモリ管理――については、すでに優れた記事がいくつもあるので、最後に参考リンクを並べる。
具体例として後半で詳しく取り上げるのは、 リリースノートの運用をハーネス化した話 だ。地味なテーマだが、アウトカムへの効き目は驚くほど大きい。
第 1 章|「やりきった」を再定義する
エンジニアの目標を 1on1 で書き換える時、初めはほとんどの人が「〜機能をリリースする」という形で持ってくる。これは別に怠慢ではなくて、ソフトウェア業界全体の慣性だと思う。リリースを目標にすれば、マージしてデプロイすれば達成、と判定できる。便利だから消えない。
ただ、AI でリリース速度が上がれば上がるほど、 「リリースしたが、誰も使っていない」 という機能が積み上がりやすくなる。手元で動くものを作る摩擦が下がっているから、その分、現場に届くまでの摩擦のほうが相対的に重く見えてくる。
だからチームでは、目標の言葉を少しずつ書き換えてきた。 「機能を出した」ではなく、 「使われて、行動が変わった」 を達成基準にしよう、と。
これは要するに、 アウトカムベース で考えるという話だ。 言い換えると、リリースを「終点」ではなく「中継点」にする、ということでもある。終点は、ユーザーの行動が変わったところに置く。
ここまでの主張:アウトカムベース思考は、リリースを終点から中継点へ移し、エンジニアにリリース後の工程まで視野を広げることを要求する。
第 2 章|なぜ仕組みがいるのか
アウトカムベースに切り替えた瞬間に、現実的な壁にぶつかる。
機能ベースの目標なら、エンジニア一人でも達成できる。コードを書いて、テストを書いて、デプロイすれば終わり。 でもアウトカムベースの目標は、エンジニア一人では絶対に達成できない。CS の運用変更があって、現場が新機能の存在を認知して、ユーザーが触ってみて、初めてアウトカムが動く。 ここにいる関係者は、エンジニアが直接コントロールできる相手ではない。
この記事にも記載した 本質的複雑度 と 偶有的複雑度 の話が関連してくる。 AI は偶有的複雑度――ツールやプロセスが生み出す複雑さ――を劇的に下げてくれた。一方で、本質的複雑度――そもそも何を作るべきか、どうしたら使われるか、どうやって価値が届くか――は、AI が肩代わりしてくれるわけではない。
そして本質的複雑度は、エンジニア一人で抱え込める種類のものではない。 だからチームと組織で抱えるための 仕組み が必要になる。これを僕はハーネスと呼んでいる。
ここまでの主張:アウトカムベース化は責務範囲を一気に広げ、その重さを支えるためにチームと組織で使えるハーネスが要る。
第 3 章|「アウトカム文脈のハーネス」を切り出す
冒頭で書いたとおり、世間で語られている「ハーネス」は範囲が広い。 ツール統合、メモリ、コンテキスト管理、検証、サンドボックス、オーケストレーション……どれも大事な構成要素だが、全部いっぺんに語ろうとすると話がぼやける。
そこで、本稿は アウトカムベース開発という観点から見たときに必要になる切り口 だけを取り出す。 言い換えると、 「リリースしたものを、ちゃんと届けて、使われ方が観測できる状態にする」ためのハーネス に絞る。 コーディングエージェントのプロンプト設計や、エージェントのメモリ層といった話題には踏み込まない。
絞った結果、残るのは 3 つのレイヤだ。 これは僕オリジナルの分類というより、Fowler の guides / sensors の枠組みを、「リリースしたあとの世界」へ寄せて並べ直したものに近い。
(a) 高速にリリースできる土台(guide 寄り)
毎日、毎週、何度も小さく出せる状態にしておくこと。 ここがちゃんとしていないと、「届いていない」が見つかってもすぐに直せない。 バージョンの上げ忘れ、ドキュメントの書き忘れ、画像の貼り忘れといった「人が忘れがちなこと」は、CI で省略不能にしておくのが基本姿勢になる。
そして、CI の縛りと同じくらい大事なのが、 そもそも「小さく安全に出せる」コード設計 にしておくことだ。 具体的には、後で詳しく触れる Vertical Slice Architecture のように、機能 1 つを縦に閉じたディレクトリへ収め、機能間の依存をできるだけ薄く保つ書き方を意識する。 影響範囲が機能スライス内に閉じている状態を作っておくと、フィーチャーフラグでの段階公開や緊急ロールバックが「現実的に回る運用」として成立する。逆にここが緩いと、CI を厳しくしてもリリース粒度を小さく保てない。
(b) 変更が「読める」形で届く経路(guide × sensor)
リリースしただけで届いた気にならないこと。 リリースノートが、現場の人の目に触れる場所に、目に留まる形で並んでいる状態をつくる。テキストだけ流して終わらせないことが、まず一歩目になる。
(c) 使われ方を観測できるレイヤ(sensor 寄り)
機能が出たあと、誰がいつ何をして、どこで離脱したのかを、後から問い合わせられる状態にしておくこと。 ここに何かしらのログ/イベントの蓄積基盤がないと、「届いた/届いていない」を感覚論でしか語れなくなる。
3 つはバラバラに作っても効かない。 3 つそろって初めて、アウトカム文脈でのハーネスとして機能する 。 本稿では特に (a) と (b) を、リリースノート運用というかたちで具体化した話を、次の章で詳しく書く。
ここまでの主張:ハーネスは広い概念だが、アウトカムベースの観点で必要になるのは「高速リリース/読める変更通知/観測」の 3 層に整理できる。
第 4 章|ケーススタディ|リリースノートをハーネス化する
ここからは、僕が実際に取り組んでいる、 リリースノート運用をハーネスとして組み上げる話 を、できる限り再利用可能な形で書いていきたい。 扱っているのはあるプロダクトのリリースノートだが、書くこと自体はどの会社でも応用できるはずだ。
きっかけ|「こんな機能、あったんですか?」と CS / FS に言われた
このリリースノート整備に手を入れる直接のきっかけは、 CS や FS の口から、「こんな機能、あったんですか?」という言葉が出てきたこと だった。
お客様にプロダクトの価値を届けるうえで、CS と FS は最重要のカウンターパートだ。彼らが新機能を握っていない状態でお客様と話している間は、どれだけ機能をリリースしても、それは 「存在しない機能」と同じ になってしまう。 驚きだったのは、彼らがプロダクト全体を理解していないわけではなかった、という点だ。むしろ全体像はちゃんと押さえている。 にもかかわらず、 「最新の機能」だけが、まるごと抜け落ちていた 。
原因をたどっていくと、構造的な話だった。
- リリース頻度がかなり高い
- 結果として、変更の総量が、CS / FS の通常業務の中で追いきれる量を超えていた
- 既存の通知(テキストの Slack 投稿など)では、「重要な変更」と「小さな修正」がフラットに並んでしまい、流れていく
つまり、 リリースが多すぎて追えない こと自体が、お客様に届けるパスのボトルネックになっていた。 これに気づいたとき、 リリースノートは単なる開発者向けドキュメントではなく、CS / FS を通じてお客様に価値を届けるための、ハーネスの中心装置だ という認識にはっきり切り替わった。 変更が「読める」「追える」「拾える」状態にならない限り、どれだけ機能を出しても、お客様までは届かない。
Before|抱えていた問題
- リリースは週に何度も走っているのに、CS / FS が把握しているのは月に数件
- 通知は Slack のテキストのみで、画面のどこが変わったかが分からない
- 「重要な追加機能」と「軽微な修正」がフラットに流れ、CS / FS の側で優先度が判断できない
- フィーチャーフラグの状態と「いまユーザーから見えているもの」が一致しない
- 結果として、「告知すべきリリース」と「告知しなくていいリリース」の判断が属人化する
設計|リリースノートを 3 階層で持つ
最初にやったのは、リリースノートというドキュメントを、3 つの粒度に分けて整理することだった。
- フィーチャー(個別機能のページ) その機能は何で、どう使うのかを説明するページ。基本は機能ごとに 1 ページ。
- スナップショット(最新の状態) 今この瞬間、何が使えるのかをまとめた一覧。新メンバーや顧客のオンボーディング資料としても機能する。
- リリース差分(変更履歴) いつ、何が変わったのかを時系列で並べたページ。
ファイル構成も、この 3 階層がそのままディレクトリに落ちるようにした。
docs/content/ ├── releases/ # v0.10.59.mdx のような「リリース差分」ファイル ├── snapshots/ # feature-1.mdx のような「機能ごとの最新状態」ファイル └── snapshot-mapping.json # コードパス → スナップショットの対応表
snapshot-mapping.json は、
{ "features/feature-1": "snapshots/feature-1.mdx", "features/feature-2": "snapshots/feature-2.mdx" }
のように 「コードのこのディレクトリが変わったら、このスナップショットを更新せよ」 を機械可読な形で持っている。これが後で CI チェックの心臓部になる。
ポイントは、 3 つを別々に書かない ことにある。
リリース差分・機能ページ・スナップショットを、1 つの MDX ソース(<MediaEmbed> などの共通タグ込み)から組み立てる構造にしておくと、リリースのたびに 3 つすべてが同時に更新され、「機能ページだけ古い」「変更履歴に書いていない」みたいな乖離が起きにくくなる。
実装|順番に積んだ仕組み
ここからは、実際に積み上げていった打ち手を、順番に書いていく。 すべてが同時に必要なわけではなく、ボトルネックを 1 つずつ潰していった結果として、こういう順番になった。
1. バージョンバンプとリリースノートを、CI で同時に強制する
最初に潰したのは「バージョンを上げ忘れる」「リリースノートを書き忘れる」という、ありふれた事故だった。
具体的には、PR の opened / synchronize / reopened / labeled / unlabeled で動く GitHub Actions を 1 つ用意し、次の 3 段チェックを順番に走らせている。
# Step 1: 対象パッケージにコード変更があるか確認
CODE_CHANGES=$(git diff --name-only "$BASE_SHA"...HEAD -- "$PKG_DIR/" \
| grep -v "^$PKG_DIR/package.json$" || true)
if [ -z "$CODE_CHANGES" ]; then
echo "✅ コード変更なし — バージョンチェックをスキップ"
exit 0
fi
# Step 2: バージョンが上がっているか
BASE_VERSION=$(git show "$BASE_SHA":"$PKG_DIR/package.json" | grep '"version"' | ...)
HEAD_VERSION=$(grep '"version"' "$PKG_DIR/package.json" | ...)
if [ "$BASE_VERSION" = "$HEAD_VERSION" ]; then
echo "❌ コードを変更しているのに version が上がっていません"
exit 1
fi
# Step 3: 対応するリリースノートと、関連スナップショットがあるか
if [ ! -f "$PKG_DIR/docs/content/releases/v${HEAD_VERSION}.mdx" ]; then
echo "❌ リリースノートが見つかりません: v${HEAD_VERSION}.mdx"
exit 1
fi
SNAPSHOT_CHANGES=$(git diff --name-only "$BASE_SHA"...HEAD -- \
"$PKG_DIR/docs/content/snapshots/" || true)
if [ -z "$SNAPSHOT_CHANGES" ] && <機能コードに変更あり>; then
echo "❌ 機能コードを変更しているのに、スナップショットが更新されていません"
exit 1
fi
ポイントは 3 つある。
- チェックを 1 ジョブに束ねず、段階で落とす:「コード変わってないからスキップ」「バージョンだけ間違ってる」「ノートだけ抜けてる」を、それぞれ別のエラーメッセージで返すと、開発者が次に何をすればいいかが一発で分かる。
- Step 3 で
snapshot-mapping.jsonを機械的に参照できる:機能コードのどのディレクトリが変わったら、どのスナップショットを更新するべきかが事前に分かるので、レビュアーが目視チェックする必要がない。 labeled / unlabeledイベントでも走らせる:あとで触れるinternalラベルを途中で付け外しできるようにするための布石でもある。
たった数十行のシェルスクリプトだが、これが入っているだけで「バージョン据え置きでマージ」「リリースノート無しでリリース」が物理的にできなくなる。 ここがハーネス全体の 土台 になる。
2. ドキュメントサイトを独立させて配信する
リリースノートをアプリの中に閉じ込めると、見られない人が出る。 専用のドキュメントサイトを Cloudflare Pages のような静的配信基盤の上に立て、 「リリースノートが読める場所」を、アプリと独立した URL で持つようにした。 社内・顧客・将来のユーザー、誰でも同じ URL を共有できる状態が、ハーネスの起点になる。
3. 認証とフィーチャーフラグでゲートを掛ける
実はフィーチャーフラグは、ハーネスの中で 二重の役割 を担っている。 1 つは、 高速リリースの土台 としての役割。もう 1 つは、 リリースノートの可視性制御 としての役割だ。同じフラグ仕組みを 2 つの目的に使い回している。
(i) コード側|Vertical Slice Architecture × フィーチャーフラグで影響範囲を絞る
リリースを高速に回せている前提条件として、 機能ごとに Vertical Slice Architecture を採っている ことが大きい。
- 機能 1 つにつき 1 つのディレクトリ(UI/状態管理/API クライアント/テストまで全部その中に閉じる)
- 機能間は薄いインターフェースだけで繋ぐ
- リリースは「機能単位のフラグ」で ON / OFF できる
こうしておくと、ある機能の変更が他機能に波及しにくく、 影響範囲をスライス単位に閉じてリリースできる 。 結果として、「壊れていてもこの機能だけフラグ OFF」「特定顧客だけフラグ ON で先行投入」みたいな運用が成立し、リリースの粒度を物理的に小さく保てる。
(ii) ドキュメント側|同じフラグでノートの可視性を制御する
そして同じフィーチャーフラグの仕組みを、 リリースノートとスナップショットの可視性 にも噛ませている。 「機能コード側でフラグ OFF」のものは、ドキュメントサイト側でも自動的にフラグ OFF になり、関連するノートやスナップショットが表示されない、という挙動だ。
具体的には、ドキュメントサイトに以下のレイヤを重ねている。
- Google OAuth による認証
- ドメインや個人単位での閲覧範囲制御
- コードと同じフィーチャーフラグ による「機能ごとの公開/非公開」段階制御
これにより、 「社内だけ」「特定の顧客まで」「全公開」 を機械的に切り替えられるようになる。 社外向けのリリースを、社内向けより遅らせる/同時に開ける/後ろ倒すといった戦略を、コードに落として運用できる。 重要なのは、 「コードでこの機能はまだ ON にしていません」と「リリースノートにもまだ載せません」を、別々に管理しなくていい ことだ。フラグが 1 つ動けば、コードもノートも一緒に動く。
ハーネスの中で同じ概念を二重に使い回せているのは、Vertical Slice Architecture のおかげで「機能 = 1 単位」がコード・ドキュメント両側で揃っているから、という側面もある。
4. 「全開バイパス」のフラグを忘れずに用意する
ゲートを作ると、必ず「全部見せたい」状況が来る。社内レビューの瞬間、外部監査の瞬間、緊急障害の瞬間。
そのために、 docs:all のような「ゲート全開」フラグ を必ず用意しておく。これがないと、せっかく作ったゲートが運用上の足枷になる。
5. 「書かなくていいリリース」をラベルで識別する
リファクタや依存関係更新みたいな内部変更まで全部リリースノートに書こうとすると、運用が止まる。
そこで、 internal ラベル を PR に付けたら、リリースノート・スナップショットのチェックだけ自動でスキップする仕組みを入れている。
GitHub Actions 側ではこんな書き方になる。
- name: Check documentation updates if: ${{ !contains(github.event.pull_request.labels.*.name, 'internal') }} run: | # リリースノートとスナップショットの存在チェック ...
ここで重要なのは、 バージョンバンプチェックは絶対にスキップしない ことだ。 内部リファクタでもストアの再サブミットには version 更新が必須なので、ノートだけスキップしてバージョンは強制する、という非対称を CI に埋め込んでおく。
書く・書かないが個人の審美的な判断にならないように、 ラベルというルール に逃がしてあげるイメージだ。
6. UI が変わる PR にはスクリーンショット必須
「こんな機能あったんですか?」が起きる一番大きな要因は、 CS / FS がリリース文を読んでも、画面が頭の中で再現できない ことだった。 テキストだけでは、 「どこに」「どう出ているか」 が伝わらない。 そこで、UI に変更がある PR には スクリーンショットを添付しないとマージできない ようにした。 撮影自体は、Storybook 上のモックを並べてコマンド一発で書き出すスクリプトを用意し、撮る側の負担をできるだけ削っている。
7. Storybook → 画像 → MDX の自動連結
Storybook で作っているコンポーネントの状態は、そのまま PNG として書き出せる。
書き出した画像は、リリースノートの MDX に <ScreenShot /> のような独自タグでそのまま埋め込めるようにし、 画像置き場と本文を分けない 設計にした。
こうすると、機能ページ・スナップショット・リリース差分のどこに画像を出すかを意識せずに、 1 か所書けば 3 か所に出る 状態が作れる。
8. Slack 通知を「画像が貼られたスレッド」に変える
リリースが走ったときの Slack 通知は、テキストの 1 通だけにしないこと。 親メッセージにはざっくりとしたサマリと URL を書き、 そのスレッドに画像を添付したリプライをぶら下げる 設計にした。 こうしておくと、通知を見た瞬間に「何が変わったか」を絵で確認できる。テキストだけだとどうしても流される。
実装上は、Slack の本文に画像を直に貼り込むには公開 URL が必要になるという制約があるので、
- 親メッセージは
chat.postMessageでテキスト - 画像は
files.completeUploadExternalでアップロードしつつ、thread_tsを指定して同じスレッドにぶら下げる
という二段で投げる方式に落ち着いた。 Block Kit のレイアウトは保ちつつ、公開ストレージを新設しなくて済む、現実解だと思っている。
9. 配布チャネル側のイベントも能動的に拾う
Chrome 拡張機能のように、ストア側の審査タイミングが読めない配布チャネルだと、 「マージはしたがユーザーには届いていない」 期間が必ず生まれる。 そこで、ストアの公開ステータスを定期チェックするワーカーを置き、 「公開された瞬間」に Slack へ通知 するようにした。 これによって、開発者の手元のリリースタイミングと、現場が「使えるようになった」と感じるタイミングのズレが、限りなく小さくなる。
10. AI レビュアー向けに、ドキュメントの書き方そのものをルール化する
ここまでは「形式チェック」の話だった。けれど、リリースノートの本当の価値は 「中身がユーザー目線で書かれているか」 にかかっている。
ここを CI のシェルスクリプトで縛るのは難しいので、 AI コードレビュアー(Gemini Code Assist)に読ませるスタイルガイドを別ファイルで持たせる ようにした。
リポジトリ直下に .gemini/styleguide.md を置いておくと、Gemini Code Assist が PR レビュー時にそのスタイルガイドを参照してくれる、というシンプルな仕組みを使っている。
中身は、たとえばこういう内容を書いている。
- 対象読者は現場ユーザー(エンジニアではない):技術的な前提を置かない。
- 禁止用語の明示:コンポーネント名・ファイルパス・ライブラリ名・API 名・フィーチャーフラグ名・英語の技術用語などは、リリースノートに登場させない。
- リリースノートの frontmatter 規約:
version、date、titleを必須にする。さらにversionがpackage.jsonと一致することを Gemini にもチェックさせる。 - スナップショットの構造規約:「この機能でできること」セクション必須、ステップ形式での説明必須、画像キャプションは日本語のユーザー目線で書く。
- 文体ルール:です・ます調で統一、太字は重要箇所だけ。
- コード変更時の連動チェック:機能コードが変わっていてバージョンが上がっている PR では、
releases/v{新バージョン}.mdxが作成されているか、対応するsnapshots/*.mdxが更新されているか、snapshot-mapping.jsonで対応関係が取れているかを Gemini にも見させる。
CI の形式チェックと、AI レビュアーへのスタイル指示を 二段重ね にすると、 「ノートはあるが意味不明」「ファイルパスが本文に直接書いてある」みたいな、人間レビュアーが見落としやすい品質劣化も拾えるようになる。
11. 同じルールを、コード生成側の AI にも教える
最後の一押しとして、リリースノート運用のルール一式を コード生成側の AI(Claude Code 等) にも認識させる。
具体的には、リポジトリ直下の CLAUDE.md / AGENTS.md に、以下のような短い節を入れるだけだ。
- フロントを変更する PR では
package.jsonのversionをパッチバンプすること(Chrome Web Store への再サブミットに必要)。- リファクタリングや依存関係更新などユーザー向けリリースノートが不要な技術的変更の PR には
internalラベルを付けること。これにより CI のリリースノート・スナップショットチェックがスキップされる(バージョンバンプチェックはスキップされない)。
これを置いておくと、AI にコードを書かせた瞬間から、
- バージョンバンプ済みの diff
- 対応する
releases/v{新バージョン}.mdx - 必要に応じて
internalラベル提案
を自分から出してくるようになる。 CI(強制)/Gemini styleguide(レビュー)/CLAUDE.md・AGENTS.md(生成) の三段で同じルールを束ねるのが、ハーネスとして一番抜けが少ない構成だと思っている。
After|何が変わったか
積み上げ終わってみると、リリースノートが、ただの差分ログから、いくつかの仕組みを束ねた 一個のハーネス に変わっていた。
- マージのときに、ノートとスクショと画像通知が同時に走る
- CS / FS が、画像つきで「いま何が新しく使えるのか」を把握できる
- 顧客向け/社内向けの公開タイミングをゲートで切り替えられる
- 「いま全体として何が使えるか」をスナップショットで誰でも確認できる
- 配布チャネルの遅延も、Slack に流れてくる
派手な機能ではない。 けれど、 CS / FS から「こんな機能あったんですか?」が消える方向に、確実に景色が変わってきている 。 そしてそれは、お客様の手元で機能が使われ始めるための、いちばん地味で、いちばん効くテコだと思っている。
ここまでの主張:リリースノートをハーネスとして組むと、「リリースしたが届かない」という最頻出の失敗が、運用ではなく仕組みで防げるようになる。
第 5 章|ハーネスがアウトカムを引き寄せる構造
リリースノートの話に偏らせてきたけれど、最後に少しだけ抽象に戻る。 ハーネスがアウトカムを動かすメカニズムは、僕の中ではこういう連鎖になっている。
リリース頻度が上がる × 認知遅延が縮む × 観測が効く = 使われる = アウトカムが動く
3 つは独立して効くというより、 掛け算で効く タイプのレバーだ。 リリースが速くなっても、認知が遅ければ使われない。認知が速くても、観測が無ければ何が刺さっているか分からない。観測が効いていても、リリースが遅ければ反映されない。
だから 3 つに同時に投資する。これがハーネスを「揃える」という発想の根っこにある。
ここまでの主張:ハーネスの 3 層は、リリース頻度・認知遅延・観測という 3 つのレバーに対応し、3 つの掛け算でアウトカムが動く。
第 6 章|まとめ|手元で使える原則
最後に、自分とチームが迷ったときに立ち返るためのチェックリストを置いておく。 完成品ではなくて、これからもアップデートしていくつもりのものだ。
- アウトカムを言語化する。 リリースを終点ではなく中継点として書く。
- リリースを CI で強制する。 バージョン、ノート、スナップショット、すべて「省略不能」にする。
internalラベルだけが唯一の逃げ道。 - 変更を「読める」形に変える。 Storybook → 画像 → MDX → Slack スレッド添付までを 1 本でつなぐ。
- ゲートと全開バイパスを必ずセットで用意する。 認証とフラグで段階的に開きつつ、緊急の全開もできるようにする。
- AI レビュアー向けにスタイルガイドを書く。 形式は CI、中身の質は AI レビューへ寄せる二段構成にする。
- AI 生成側にも同じルールを教える。
CLAUDE.md/AGENTS.mdに運用ルールを書いて、CI・レビュー・生成を一致させる。 - 使われ方を観測できる場所をつくる。 後から SQL で問えるところにイベントを残す。
- 配布チャネルの遅延も、ハーネスに含める。 マージ完了ではなく、ユーザーが触れるようになった瞬間を起点にする。
派手さはない。 ただ、こういう地味な仕組みを 1 つずつ積み上げていくことで、リリースが少しずつ「届く」方向に動いていく実感がある、という話だ。
ハーネスエンジニアリングは広い概念で、論者によって切り取る場所が違う。 本稿はそのうちの一部、 アウトカムベース開発から見たハーネス という切り口だけを取り出して書いた。 別の切り口、別の現場では、また違うハーネスの形が出てくるはずで、そのへんはまた別の機会に書きたい。
参考|ハーネスエンジニアリングをもっと広く知るために
本稿で扱わなかった文脈(コーディングエージェントの内部設計、ツール統合、メモリ層、エンタープライズ統治)は、以下の記事が良い入口になると思う。
- Martin Fowler, Harness Engineering for coding agent users —
Agent = Model + Harnessの枠組みと、guides / sensors の整理。 - Parallel Web Systems, What is an agent harness in the context of large-language models? — LLM をラップするインフラ全体としてのハーネス定義。
- Adnan Masood, Agent Harness Engineering — The Rise of the AI Control Plane — エンタープライズ統治レイヤとしての視点。
- ai-boost, awesome-harness-engineering — ツール、パターン、評価、メモリ、MCP、観測などを体系的に集めた一覧。
PR
- ROXXってどんな会社?気になった方はこちらから👇
careers.roxx.co.jp note.roxx.co.jp
- エンジニア採用ページはこちらから👇