株式会社ラクスのブログ - TECH PLAY

TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

全982件

はじめに プロダクト開発支援課フロントエンド推進チームの安彦です。 プロダクト開発支援課は2026年10月に発足したばかりの組織です。私たちのチームが顧客としているのは、プロダクトの先にいるエンドユーザーだけではありません。社内でプロダクトを作っている開発者もまた、私たちが価値を届けるべき顧客として捉えています。 現在、社内の複数のプロダクトで共通して使えるデザインシステム「 Libero(リベロ) 」を構築しています。 ラクスには、用途もブランドも異なる複数のプロダクトが存在します。開発者がそれぞれの現場で迷わず安全にLiberoを使えるようにするためには、最初に「 Liberoが何を持ち、何を持たないか 」を決める必要がありました。 この記事では、Liberoの設計において決めたことを、次の問いに沿ってお伝えします。 はじめに 複数プロダクト向けに、何を持たないか 見た目と振る舞いを、何を根拠に決めたか 画像だけでは表現しきれない領域 UI品質を担保する「5つの層」 値を根拠から逆算し、CIで品質を担保する プロダクトからLiberoへ、何を渡せるか デザインガイドラインと接点の関係 AIが組んだUIの品質を、誰が担保するか おわりに ※Liberoのコードやドキュメントを社外公開する予定はありません。設計のケーススタディとしてこの記事がお役に立てば嬉しいです。 複数プロダクト向けに、何を持たないか Liberoは、プロダクトのドメインやブランドを持ちません。 ドメインの知識 *1 はプロダクトごとに異なり、変わり続けるので、Liberoが追従し続けることは困難です。また、ブランド *2 についても、複数ある中でのどれか1つの表現をLiberoの既定値にしてしまうと、他のプロダクトにとっては不要なスタイルを打ち消す余計な作業が発生してしまいます。 「全社横断のデザインガイドラインを先に作らないのか?」と疑問を持たれるかもしれませんが、Liberoではそのアプローチをとりませんでした。各プロダクトでガイドラインの整備状況や目指す表現が異なるからです。 そのためLiberoは、あとからどのガイドラインが注入されても受け入れられる基盤を先に作りました。APIにはドメインの言葉を持ち込まず、提供するコンポーネントの既定の見た目や振る舞いにも、特定のブランド表現を入れていません。 このように持たないものを明確に決めた上で、デザイントークンを起点に、44のコンポーネントを提供しています。 Liberoのコンポーネントの既定の見た目。特定のプロダクトのブランド表現を持たない 見た目と振る舞いを、何を根拠に決めたか 既定にドメインもブランドも入れない分、見た目と振る舞いの値には別の根拠が必要です。Liberoでは、エンジニアが画面を組むときに毎回決めているものを整理することから始めました。 画像だけでは表現しきれない領域 画面を組むとき、画像という静的な形式だけでは、どうしても表現しきれない領域があります。 状態: hover、押している途中、送信中、エラー、空データ、長い文字列、文字サイズの拡大 操作: キーボードだけで操作できるか、スクリーンリーダーに何が読み上げられるか 更新: 使っているライブラリを更新したあとの見た目 これらが仕様として明記されない場合、実装するフロントエンドエンジニアの個人の判断に委ねられます。機能開発のスピードが優先される現場では、UIの細かな品質までを受け入れ基準に定める余裕がないことも少なくありません。個人の判断に委ねられ、気づかれなかった実装は、次に誰かがそのコードに触れるまで残り続けます。 UI品質を担保する「5つの層」 そこでLiberoは、個人の判断に委ねられていたUI品質を、層に分けて整理しました。 UIは単一の面ではなく、土台から順に依存しながら積み上がる多層的な構造をしています。最下層にはブラウザやOS、支援技術といった変えられない実行環境があり、最上層にはプロダクト固有の判断が乗ります。 Liberoは、この両者の間に位置する5つの層を自身の責務と定めました。層ごとに何を満たせば品質が守られるかを定義し、すべてのコンポーネントに適用しています。 セマンティックHTML: 用途に合ったHTML要素とroleで組み立てる アクセシビリティ: キーボードで操作でき、支援技術に名前・役割・状態を伝える 状態表現: hover・focus・disabled・処理中などの状態を見た目で示す テーマ: 色や形をトークンとして持ち、値をまとめて差し替えられる フレームワーク対応: UIフレームワーク・CSSライブラリの更新に追従する 最上層のプロダクト固有の判断(情報設計、画面の構成、文言、操作後の処理)は、引き続き各プロダクトが持ちます。Liberoが間にある5つの層を引き受けるのは、プロダクト側がこのドメイン固有の判断に集中できるようにするためです。 値を根拠から逆算し、CIで品質を担保する Liberoが引き受ける層の品質は、感覚ではなく明確な根拠と自動化によって担保しています。具体的には、次の2つの観点を満たすように既定の振る舞いを決めています。 Web標準: ブラウザ標準の振る舞いを上書きせず、 Baseline のWidely availableに含まれる機能で作る アクセシビリティ: WCAG 2.2 AA の達成基準を満たす この2つの観点はCIで検査しています。Web標準はWidely availableを外れる機能を使っていないかをlintで、アクセシビリティは違反がないかを axe-core で確かめます。 見た目の値も同様に根拠から逆算します。色はコントラスト比から候補を絞り、角丸は要素の高さとの比から決定します。値そのものではなく導き方を決めているため、将来値を変える必要が出た際も、同じ導き方で安全に決め直すことができます。 プロダクトからLiberoへ、何を渡せるか Liberoは既定値のままでも、UI基盤として品質が保たれ、そのまま問題なく機能するように作られています。 しかし、実際のプロダクトに組み込む現場からは「プロダクト固有のブランドカラーやスタイルをコンポーネントに適用したい」といった需要が生まれます。そこでLiberoでは、影響範囲をコントロール可能な状態に保ちながら、各プロダクトのドメインやブランドを安全に受け入れる経路として、明示的に以下の3つのみを接点として開放しています。 props: コンポーネントに、variant・状態・表示する文言を値として渡す theme: 色や形の役割(primaryなど)に、ブランド表現の値を渡す events: ユーザー操作の発生をプロダクト側へ通知し、その後の処理を委ねる この3つは、変えても影響範囲が予測できる経路です。 開く範囲を絞っている最大の理由は、前節で述べた品質と振る舞いの一貫性を無秩序に壊さないためです。また、依存の向きをプロダクトからLiberoへの一方向に制限することで、ライブラリ更新時の予期せぬレイアウト崩れを防ぎ、保守の負担をLibero内で完結させる目的もあります。 デザインガイドラインと接点の関係 各プロダクトのブランド表現は、横断のデザインガイドラインとして先に定めてからコンポーネントに落とす流れが一般的ですが、冒頭で触れたとおり、Liberoはこの順で作っていません。 すでにガイドラインが存在するプロダクトは、その固有の表現をthemeの値として差し替えます。例えばprimaryの役割に値を渡せば、ボタンやリンクなど同じ役割の要素が、まとめてブランドカラーに置き換わります。一方、ガイドラインが整備中のプロダクトは、まずLiberoの既定に乗り、固有の表現が増えてきたタイミングでガイドラインとして育てていくことができます。特定のブランド表現を持たないプレーンな基盤にしたのは、この両方の状況を単一の接点で受け止めるためです。 プロダクトは値を渡し、どの部分にどの役割を当てるかはLiberoが固定する もし提供している接点の範囲で既定から外れる値を入れる場合や、接点だけでは表現できない要件が出た場合は、Web標準やアクセシビリティとの整合性が崩れるリスクが生じます。その際は、Liberoの利用を強制するのではなく、なぜこの制約になっているのかという根拠を共有し、トレードオフを一緒に評価した上でプロダクト側に判断を委ねる対話を重視しています。 基準を下回る上書きをしたくなったときの判断の分岐 AIが組んだUIの品質を、誰が担保するか ここまでは、フロントエンドエンジニアが画面を組む前提で書いてきました。しかし現在では、AIによってUIの生成が容易になり、フロントエンドエンジニア以外がコードに手を入れたり、プロトタイプを作ったりする場面が増えています。生成された画面は一見すると見た目が整っています。しかし、focusの制御が漏れていないか、選択状態が色だけで示されていないか、disabledのときに何が起きるかといった見えない層の品質まで、生成段階で担保できているケースは多くありません。ここで見過ごされたものは、直す工数として現れます。 画面を作る費用が下がった分、コードを保守し続ける負担の比重は上がります。だからこそ、コードを書く人が増えるAI時代において接点を絞る意味がより大きくなります。 Liberoの提供する3つの接点(props・theme・events)だけを通って組まれた画面であれば、人が書いてもAIが書いても、その下にある5つの層は、同じ品質の水準が保たれます。非エンジニアがAIで作ったプロトタイプであっても、接点だけで組まれていれば、フロントエンドエンジニアは画面の構成や文言の確認に集中し、安心してそのまま実装に進めることができるのです。 おわりに デザインシステムやガイドラインのような共通の基盤は、揃えるための強制力を持ちます。しかし一方で、その強制力がプロダクトの開発スピードを落としたり、何を自分たちで決めてよいのか迷わせてしまう場面もあります。私自身も、前身となるデザインシステムの実装と利用の両方に携わる中で、同じ難しさを感じていました。このもどかしい経験を振り返ってみると、問題は強制力そのものではなく、「なぜその形なのか」「どこまで変えてよいのか」が辿れず、現場の判断が止まってしまうことでした。Liberoの設計には、当時の自分たち自身の反省が活かされています。 UIは作って終わりではなく、技術の変遷に伴って求められる品質の水準も変わり続けます。Liberoが責務の境界を明確にし、根拠を開示しているのは、強制力を最小限に留めつつ、各プロダクトがこの変化へ追従しやすくするための基盤でもあるからです。 判断をプロダクト側に残す分、各プロダクトとの対話は欠かせません。導入の検討段階から使い始めたあとまで、プロダクトで見つかる課題を持ち寄ってもらい、一緒に決めていきます。Liberoだけでは完成しないからこそ、プロダクトと育てていくシステムでありたいと思っています。 複数のプロダクトに向けて基盤を作ろうとしている方はもちろん、日々の開発でエンジニアが毎回決めているものに名前を付け、その責務を捉え直すきっかけになれば嬉しいです。 *1 : 特有のデータ構造、業務フロー、文言など *2 : テーマカラーやタイポグラフィ
楽楽請求の開発チームに所属している takayama です。 本番環境で ERROR ログのアラートが届いたとき、最初の時間を何に使っていますか。 私は、過去の Issue を探したり、障害対応シートに情報を書き写したりする作業に、その時間の多くを使っていました。 そこで、ERROR ログを1行渡すだけで一次対応の下準備をしてくれる Claude Code のスキル「error-triage」を作り、書き写しや整形の作業をスキルに任せるようにしました。 この記事では、その経緯や工夫した点を紹介します。 はじめに 背景と課題 一次対応の流れ 一次対応の課題 この記事で扱う範囲 error-triage の概要 全体の流れ スキル定義 gws でスプレッドシートを操作する 実行例 設計で工夫した点 手順書を分けて、必要なときだけ読ませる 書き込む前に dry-run で確認する 分からない値は「分からない」と書かせる 結果と考察 導入してみて変わったこと 残っている課題と今後 まとめ はじめに この記事で伝えたいこと ERROR ログ1行から、既知のエラーかどうかの判定、原因箇所の当たり付け、初動の資料づくりまでを Claude Code に任せています。 スプレッドシートの操作に gws(Google Workspace の CLI)を使い、手順書は必要なときだけ読み込ませる構成にすることで、既存の運用フローを変えずに AI エージェントを導入できました。 こんな方に読んでほしいです アプリケーションの運用保守を担当している方 障害対応の初動に、Claude Code などの AI エージェントを取り入れたいと考えている方 背景と課題 一次対応の流れ 楽楽請求では、本番環境で ERROR ログが出力されると Grafana からアラートが届き、運用担当者が一次対応を行います。 最初に判断するのは、そのエラーが既知のものか新規のものかです。 既知のエラーは GitHub の Issue で管理し、各 Issue には影響範囲を調べるためのクエリ(LogQL)を記載しています。 判断の結果によって、一次対応は3つのパターンに分かれます。 パターン 状況 対応 1 既知のエラー Issue に記載したクエリで影響を調べる 2 新規の軽微なエラー Issue を起票し、調査を依頼する 3 新規の重大なエラー 障害対応シート(※)を作り、関係するチームと情報を共有しながら対応する ※障害対応シートは、障害ごとに作る Google スプレッドシートです。 テンプレートを複製して、発生日時、スタックトレース、影響を受けたお客様、原因などの欄を埋め、開発チームや事業部と状況を共有する起点にしています。 障害対応テンプレートのイメージ 一次対応の課題 パターン3では、手順に沿って次のような作業を手で進めていました。 テンプレートを複製し、決められたフォルダに置く ログから読み取れる情報(発生日時など)をシートに書き写す 並行して、スタックトレースからソースコードの原因箇所を探す 重大なエラーで大切なのは、影響を受けたお客様を早く特定し、案内や復旧に向けて動き出すことです。 しかし実際には、その手前の書き写しや整形に初動の時間を取られていました。 この定型作業を Claude Code に任せたい、というのが取り組みの出発点です。 この記事で扱う範囲 error-triage は3つのパターンすべての初動に対応していますが、この記事ではパターン3に絞って紹介します。 障害を Google スプレッドシートで記録するのはチーム独自の運用で、AI に扱わせるための工夫がこのパターンに集中しているためです。 error-triage の概要 全体の流れ error-triage は、Grafana から取得した ERROR ログの JSON を1行渡して呼び出します。 /error-triage [ERROR ログの JSON 1行] ERROR ログの JSON(1行) → 1. GitHub で同じ例外の Issue を検索する → 2. ソースコードから原因箇所を探し、修正方針を考える(修正はしない) → 3. 既知か新規かで分岐する ├ 既知:Issue の URL と、ログの値を埋め込んだ調査クエリを返す(パターン1) └ 新規:障害レベルを推定し、作るもの(障害対応シート/Issue)を担当者が選ぶ(パターン2、3) → 書き込む内容を提示して承認を得る → 障害対応シートを作成する、または Issue を起票する 障害対応シートを作るときは、テンプレートの複製から各欄の記入までをスキルがまとめて行います。 スキル定義 error-triage/ ├── SKILL.md # 処理の流れと分岐だけを書く(約70行) └── references/ ├── incident-sheet.md # 障害対応シートの作成手順(約120行) └── issue-template.md # Issue のテンプレートと起票手順(約120行) SKILL.md (抜粋) 詳細な手順・テンプレートは ` references/ ` 配下に分割しています。 各ステップで必要になったタイミングで読み込んでください。 ## 手順 1. 既知の Issue を検索する 2. 原因箇所を調査する 3. 次の対応を ` AskUserQuestion ` ツールで確認する (以下省略) references/incident-sheet.md (抜粋) 1. テンプレート(****)を gws で複製し、年ごとのフォルダ(****)に置く 2. 各欄に値を書き込む (以下省略) gws でスプレッドシートを操作する スプレッドシートの操作には、 googleworkspace/cli ( gws コマンド)を使っています。 Drive 上のファイルの複製もシートへの書き込みもコマンドラインから行えるので、Claude Code から Bash でそのまま呼び出せます。 手作業のときと同じテンプレートと保存先フォルダを使えるため、運用を変えずに、シートの作成だけをスキルに任せられました。 実行例 ダミーのログで、新規の重大なエラーとして実行した例です(内部実装に関わる部分は省略しています)。 【次の対応方針について確認】 ← ☐ 次の対応 ✔ Submit → │ この後どの対応を作成しますか?(複数選択可。どちらも選ばない場合は調査報告のみで終了します) ❯ 1. [ ] 障害対応シートを作成 障害対応テンプレートを複製し、シートの叩き台を作成する(実行前に書き込む値の dry-run を提示) 2. [ ] Issue を起票 (調査対象リポジトリ)に Issue 本文+AI推測コメントを起票する(実行前に全文の dry-run を提示) 【障害対応シートに書き込む値(dry-run)】 ┌────────────────┬──────────────────────────────────┐ │ フィールド │ 値 │ ├────────────────┼──────────────────────────────────┤ │ Trace ID │ 0123456789abcdef0123456789abcdef │ ├────────────────┼──────────────────────────────────┤ │ 概要 │ (推定されるエラーの概要) │ ├────────────────┼──────────────────────────────────┤ │ 発生日時 │ 2026/10/16 10:23:45 │ └────────────────┴──────────────────────────────────┘ (中略) この内容で作成してよろしいですか? 設計で工夫した点 手順書を分けて、必要なときだけ読ませる error-triage は、最初は Issue の起票だけを手伝うスキルとして作り、後から障害対応シートの作成手順を追加しました。 すると SKILL.md が一気に長くなり、シートの手順が要らない既知のエラーの判定でも、毎回すべてを読み込ませることになりました。 そこで、成果物ごとの手順を references/ に切り出し、必要になったときだけ読み込ませるようにしました。 これは、Claude Code のスキルで推奨されているプログレッシブディスクロージャー(段階的開示)の考え方を参考にしたものです(詳しくは Agent Skills のベストプラクティス を参照)。 使わない手順でコンテキストを埋めないぶん、原因の調査にコンテキストを回せると考えています。 書き込む前に dry-run で確認する 障害対応シートは、作った瞬間に関係するチームの目に触れます。 誤った内容で作ると訂正や削除の手間が増え、初動をかえって遅らせかねません。 そこで、当初は調査後にそのまま書き込んでいた流れを改め、書き込む前に担当者が確認するステップを設けました。 スキルはシートの各欄に書く値を dry-run として提示し、担当者が見直して承認したものだけを作成します。 選択された対応については、実行前に必ず dry-run(更新内容)を提示して承認を得たうえで、 承認された対応を最後にまとめて実行してください。 分からない値は「分からない」と書かせる 障害対応シートの原因や対応方針の欄は、一次対応の時点ではまだ確定していません。 空欄では叩き台にならないため、調査結果から推し量った内容を書かせていますが、推測の材料すらない値をもっともらしく埋めさせないようにしています。 もっともらしい値があると、見直す担当者がそれを事実として受け取ってしまうおそれがあるためです。 推測の材料もない値は、妥当そうなデフォルト値を捏造せず ` 不明 ` と記載する。 実際には、テンプレートの書き方に合わせて、原因は「調査中」、対応方針は「検討中」と書き分けています。 結果と考察 導入してみて変わったこと 導入後、障害対応シートを作る場面はまだ1件で、効果を語るには実績が少ない段階です(重大なエラーが少ないのは喜ばしいことですが)。 その1件では、30分以上かかっていたシートの準備が10分程度で済みました。 数字以上に大きいと感じているのは、気持ちに余裕を持って初動にあたれるようになったことです。 書き写しに追われることがなくなり、影響を受けたお客様の特定や関係チームへの共有など、次の対応を落ち着いて考えられるようになりました。 残っている課題と今後 1つ目は、調査を始めるきっかけです。 今は担当者が自分の環境の CLI からスキルを実行するため、調査の開始が人に左右されます。 今後は、アラートの通知をきっかけにクラウド上の Claude Code が調査を始め、結果を Slack のスレッドに共有するところまでを自動化したいと考えています。 障害対応シートへの書き込みは、これまでどおり担当者の承認を挟む想定です。 2つ目は、AI だけで調査できる範囲です。 今の error-triage が障害対応シートの影響顧客の欄に書けるのは、渡されたログ1行に含まれるお客様だけです。 同じエラーがほかのお客様にも起きていないかは、担当者が Grafana でログを検索して洗い出しています。 今後は、Grafana Labs が公開している Grafana MCP サーバー を使ってスキルがログを検索し、影響を受けたお客様の一覧と件数まで埋めた叩き台を作れるようにしたいと考えています。 そうすれば、担当者は結果を確かめて対応を決めることに集中できます。 まとめ この記事では、Claude Code スキル「error-triage」のうち、障害対応シートを作る部分を紹介しました。 ログ1行を渡すだけで、既知のエラーの検索から障害対応シートの叩き台づくりまでを Claude Code に任せています。 gws で手作業のときと同じテンプレートと保存先フォルダを扱い、手順書を必要なときだけ読み込ませることで、既存の運用フローを変えずに AI エージェントを組み込めました。 テンプレートの複製や情報の書き写し、原因箇所の当たり付けといった初動の作業をスキルに任せたことで、担当者は、影響を受けたお客様の特定や、案内・復旧に向けた対応に集中して取りかかれそうだという手応えを得ています。 障害対応の初動に AI エージェントを取り入れたいと考えている方の参考になればうれしいです。
■ 目次 はじめに 社内ドキュメント検索MCPとは MCP は「AI が外部データ/サービスを使うための共通ルール」 中身は、社内ドキュメントを索引にした RAG 何ができるようになったか 聞くだけで探せる 「探す役」と「読む役」を分担する 検索以外にできること 使い始めるまでの手間を減らす 最初の版でぶつかった 2 つの壁 壁① 中身が古くなる 壁② 登録が続かない 使われ続けるための 3 つの工夫 工夫① 聞いたときが最新 工夫② フォルダに置くだけで検索対象になる 工夫③ 入れたくないものは確実に外せる おわりに はじめに 「あの手順、どこに書いてあったっけ」「この仕様が決まった経緯は、どの議事録だったか」。 こうした資料探しに時間を取られた経験は、多くの方にあるのではないでしょうか? 自分の所属するチームでも、資料は GitHub の wiki・issue・プルリクエスト(PR)・リポジトリ内のドキュメント、そして Google Drive に散らばっていました。 どこを探せばよいかを知っている人に聞くか、心当たりの場所を順番に開いていくしかありません。 そこで、AIアシスタントに「社内の資料で〇〇を探して」と頼めば見つけてくれる仕組みを、MCP サーバーとして作りました。 作ってみて分かったのは、 検索の仕組みは作るより、中身を最新に保つ方がずっと難しい ということです。 本記事では、この仕組みで何ができるようになったかと、使われ続けるものにするために工夫したことを紹介します。 なお、前回の記事「 「動いた」で終わらせないAI機能開発 ── 検証から本番運用までの4ステップ 」では、AI 機能をどう作るかという進め方をまとめました。 今回は、チームで AI を活用するための「仕組みづくり」の話です。 社内ドキュメント検索MCPとは MCP は「AI が外部データ/サービスを使うための共通ルール」 MCP(Model Context Protocol)は、AIアシスタントと外部のデータやサービスをつなぐための共通ルールです。 ルールに合わせて構築しておけば、さまざまな AIアシスタントから呼び出せます。 MCP でつながった AI は、用意された「ツール」(AI が呼び出せる機能)を、会話の流れに応じて自分で選んで使います。今回のように「資料を検索する」というツールを用意しておけば、利用者が「〇〇の資料を探して」と頼んだときに、AI が自分の判断でそのツールを呼び出します。(検索の際のクエリもAIが自分で考えます!) 中身は、社内ドキュメントを索引にした RAG 今回作った仕組みは、実質的には社内ドキュメントを対象にした RAG(Retrieval-Augmented Generation)です。 RAG とは、AI が答える前に関係しそうな資料を探し、それを読ませたうえで答えさせる仕組みのことです。 あらかじめ社内の文書を細かく区切って「意味で検索できる索引(インデックス)」を作っておき、知りたいことに意味が近い箇所を探します。 見つかった箇所を含む文書を AI に渡すことで、AI は社内の資料に基づいて答えられるようになります。 何ができるようになったか 聞くだけで探せる これまでは、資料を探すときに wiki の検索、Drive の検索、issue の一覧を行き来する必要がありました。 いまは AIアシスタントに次のように頼むだけです。 wikiで社内ポータルのリリース手順を調べられますか? AI が検索ツールを呼び出し、該当する資料を見つけて要約し、元の資料へのリンクを添えて返してくれます。 現在は wiki・issue・PR・リポジトリ内のドキュメント・Google Drive の資料を合わせて、約 3,800 件の文書を検索の対象にしています。 「探す役」と「読む役」を分担する この MCP がいちばん得意なのは、たくさんの資料の中から「どれが該当するか」を見つけることです。 見つけた資料の全文を返すこともできるので、それだけで内容を把握できる場面も少なくありません。 実際に使ってみると、AI は検索で資料を特定したあと、GitHub や Google Drive が提供している MCP で元の資料(正本)を開いて確かめる、という使い方を自然にしていました。 そこで、この流れを前提にした分担にしました。 正本を読むと、索引だけでは分からないことまで把握できます。 最新の状態 : Google Drive で編集中の資料は、編集が落ち着くまで取り込みを待ちます(後述)。直前の編集内容は正本にしかありません。 索引に入れていない情報 : issue なら親子関係や、その issue を閉じた PR。PR なら実際のコードの変更点や自動テストの結果、レビューでの指摘が解決済みかどうか。Google ドキュメントやスライドなら、資料に付いたコメント。こうした情報は GitHub や Google Drive の MCP から取得できます。 返信や編集に進むとき : issue にコメントを返す、資料を直すといった作業は正本でしか行えません。 全文を渡さずに正本を読んでもらう方式には、もう 1 つ利点があります。AIアシスタントが一度に読む量を抑えられることです。 索引している資料は 1,600 字ほどのものが中心ですが、Google Drive の資料には数十万字を超えるものもあります。 検索結果の上位 5 件の全文をそのまま渡すと、関係の薄い資料まで大量に読ませることになります。 そこで、まずは該当箇所だけの軽い一覧で候補を挙げ、本当に必要な 1〜2 件だけを正本で読む、という二段構えにしています。 図書館にたとえると、この MCP は「あらすじ付きの蔵書目録」です。 目録で本を探し、たいていはあらすじで用は足りますが、最新の書き込みや付箋まで確かめたいときは、書架から本そのものを取ってくる、という分担です。 GitHub や Google Drive の MCP はすでに提供されているので、自分で作成する必要はありませんでした。 検索以外にできること 検索のほかにも、日々の仕事で使いやすいツールを持たせています。 依頼の例 できること 「自分の担当 issue を一覧して」 担当者ごとの issue を一覧する 「〇〇機能の開発はどこまで進んでいる?」 PR の本文やレビューでのやり取りまで含めて探し、状況をまとめる 「最近 Drive に追加された資料は取り込まれた?」 新しい資料の取り込み状況と、その理由を確認する 「このリポジトリの wiki も検索対象に追加して」 検索の対象を会話の中で追加・削除する PR まで検索できるようにしたのは、思った以上に役立ちました。 よく使っているのは、開発の進捗の確認と、チームの成果の振り返りです。 「〇〇機能の開発はどこまで進んでいる?」と聞けば、関連する PR の状態やレビューでのやり取りから、いまどの段階にあるかをまとめてくれます。 「今月チームで取り組んだことをまとめて」と頼めば、その月の PR をもとに成果の一覧を作ってくれます。 PR には「何を・なぜ変えたか」が書かれ、レビューでのやり取りも残っているので、そのまま作業の記録として使えます。 使い始めるまでの手間を減らす どれだけ便利でも、使い始めるまでの準備が面倒だと広まりません。 そこで、接続の設定と「AI 向けの使い方の手引き」を 1 つのパッケージにまとめ、インストールするだけで使えるようにしました。 手引きには、「資料を探すときは検索ツールを使う」「添付や書きかけの内容まで確かめるなら GitHub や Drive の MCP で正本を読む」といった判断の流れを書いています。 そのため利用者は特別なコマンドを覚える必要がなく、AIアシスタントに「社内の資料で〇〇を探して」と普段どおりに頼むだけで済みます。 最初の版でぶつかった 2 つの壁 最初に作った版は、検索そのものは問題なく動きました。 ところが使い続けるうちに、2 つの壁が見えてきました。 壁① 中身が古くなる 最初の版では、索引の更新を「決まった時刻の定期実行」と「必要なときの手動実行」に頼っていました。 これでは、新しく書かれた資料が索引に入るまでに時間差が生まれます。 たとえば、索引の更新を毎朝 5 時に設定していたとします。 その日の朝会で議事録を書いても、索引に入るのは翌朝 5 時です。 午後に「今朝の朝会で決まったことは?」と聞いても、その議事録は見つかりません。 古い答えが一度返ってくると、利用者は「この検索は当てにならない」と感じて使わなくなります。 検索の仕組みにとって、中身の古さは致命的です。 壁② 登録が続かない もう 1 つの壁は、検索の対象を増やす手間です。 最初の版では、検索させたい資料の URL を 1 件ずつ登録する必要がありました。 資料は毎日のように増えていきます。 利用者に「資料を作ったら登録してください」とお願いしても、続けてもらうのは難しいでしょう。 MCPの管理者が登録し続けるのも現実的ではありません。 登録が追いつかなければ、結局「探しても出てこない」状態に戻ってしまいます。 使われ続けるための 3 つの工夫 2 つの壁を越えるために、仕組みを作り直しました。 壁①には工夫①で、壁②には工夫②と③で答えています。 工夫① 聞いたときが最新 定期実行をやめ、 利用者が検索するたびに、その場で更新を確かめる ようにしました。 先ほどの例でいえば、午後に質問した時点で今朝の議事録が取り込まれ、検索結果に出てきます。 とはいえ、検索のたびにすべての資料を読み直していては時間がかかりすぎます。 そこで、資料ごとに「内容が変わったかどうか」を見分けるための目印を記録しておき、目印が変わったものだけを読み直しています。 目印には、資料の内容から計算される短い文字列(ハッシュ)や、最終更新日時など、資料の置き場所ごとに確かめやすいものを使っています。 Google Drive については、Drive が持っている変更の履歴をまとめて確認し、変わった資料だけを拾っています。 利用者を待たせないための線引きもしています。 同じ対象を直前 60 秒以内に確かめていれば、確認を省きます。 GitHub と Google Drive は、並列で更新確認します。それぞれ 40 秒を上限に打ち切り、間に合わなかったときは今ある索引で答えます。続きは次の検索で取り込みます。 Google Drive で編集中の資料は、編集が落ち着いてから(最後の更新から 30 分後に)取り込みます。書きかけの内容で何度も取り込み直すのを避けるためです。 実は、2 つ目の線引きは運用中に見直したものです。 当初は GitHub と Google Drive を順番に確認し、全体で 20 秒を上限にしていました。並び順は GitHub が先です。 GitHub はリポジトリごとに wiki・issue・PR などを確かめるため対象が多く、それだけで 20 秒を使い切ることがありました。 すると、後ろに並んだ Google Drive の確認がいつまでも始まりません。 実際に丸 1 日以上、検索は何度も行われていたのに Drive の確認は一度も行われず、「今朝の朝会の議事録が見つからない」状態も発生していました。 そこで、GitHub と Google Drive の確認を別々に分けて同時に進め、時間の上限もそれぞれに持たせるように改めました。 検索の待ち時間は最長で 40 秒ほどに延びますが、直前 60 秒以内に確認した対象は省くので、多くの検索では待ち時間は変わりません。 「検索のたびに確かめる」仕組みにしても、確認が後回しにされ続ける対象があれば、そこは古いままになります。最新に保つには、更新のきっかけだけでなく、確認が全体に行き渡るかどうかまで気を配る必要がありました。 この方式には、誰も検索しない間は更新も止まるという弱点があります。 ただ、誰も検索しない間は、誰も最新の索引を必要としていません。 必要になったその瞬間に最新にできるので、実用上は困らないと考えています。 たとえば Google Drive で 1 日に追加・編集される資料は、普段は 10 件前後です。1 日に数回でも検索があれば、その日の更新はすべて取り込めます。 工夫② フォルダに置くだけで検索対象になる Google Drive については、ファイルを 1 件ずつ登録する代わりに、 フォルダごと登録できる ようにしました。 登録したフォルダの中に新しい資料が置かれると、それが取り込みの候補になります。 ただし、フォルダの中には検索の対象にしなくてよいものも混ざります。 そこで、候補の資料を取り込むかどうかを AI が審査するようにしました。 審査の基準は「迷ったら取り込む」です。 取り込まないのは、2 年以上前の議事録のような古い記録や、そもそも文書ではないファイルなどに限っています。 探したい資料が見つからないことの方が、余計な資料が混ざることより困るからです。 AI の判断とその理由は、あとから人が確認できます。 判断が間違っていれば、「この資料はやはり取り込んで」と頼むだけで覆せます。 この仕組みで、資料を作った人も、MCPの管理者も、資料の新規登録のことを意識する必要がなくなりました。 工夫③ 入れたくないものは確実に外せる 自動で取り込むようになると、今度は「これは検索に出したくない」という資料の扱いが問題になります。 検索の対象から一度外しても、その資料が後で編集されると、再び取り込みの候補に戻ってしまいます。 そこで、「この資料(このフォルダ、この名前のもの)は取り込まない」と宣言できる除外リストを用意しました。 除外リストに入れた資料は、どの段階でも取り込まれません。 工夫②で「迷ったら取り込む」という方針にできたのは、この除外リストがあるからです。 入れたくないものを確実に外せるので、それ以外は積極的に取り込めます。 おわりに 社内ドキュメント検索 MCP を作り、使われ続けるものにするまでの工夫を紹介しました。 振り返ると、苦労したのは検索の精度よりも、中身を最新に保つことと、検索の対象を増やし続けることでした。 今回の工夫は、MCP に限らず、社内のナレッジ検索や RAG 全般にも当てはまると考えています。 更新は、時刻ではなく利用をきっかけにする。 必要とされたその瞬間に最新にできます。 登録の手間は人に頼らず、仕組みでなくす。 人のがんばりに頼った運用は長く続きません。 自動で入れるなら、確実に外せる手段をセットで用意する。 外せる安心があってこそ、積極的に取り込めます。 検索は作るより、最新に保つ方が難しい。 社内の情報を AI に活用させたいと考えている方の参考になれば幸いです。
■ 目次 目的は少ない人数でリリースの量を上げること 使う側から見た1件の流れ ready を付けると、トリアージが始まる 仕様書が PR で届く 実装も PR で届き、いつも通りレビューしてマージする 迷わないための工夫 構造: 状態ラベルとループ 人の判断の置き場所 承認ゲートは2つに絞る チェックシートは AI が下書きし、人が確定する 安心して任せられる理由 指示・手順で頼むことと、コードで強制することを分ける 迷ったら止まり、どこからでも再開できる 何が変わったか まだ甘いところと、これから こんにちは!楽楽精算でモバイルアプリを開発しているhirakawaです。 私たちのチームでは少ない人数でリリースの量を上げるために、開発プロセスを Claude Code で動く自律 AI のループで無人化しています。 Issue に ready というラベルを付けると、トリアージ、仕様書の作成、実装までを AI のループが順に進めます。人の判断が要るところに来ると、AI は止まって人を待ちます。 人がすることはこれまでと大きく変わりません。Issue・PR・チェックシートという、いつもの場所で、いつも通り返事をし、レビューをし、PR の承認・マージをします。 工場に例えるなら、人が作業台に張り付かなくても仕事が流れ、人は要所の検査と判断にだけ立ち会う、ソフトウェアファクトリーのような形です。ループをノード、状態をエッジとしてつなぐ「グラフエンジニアリング」も、近い考え方です。 この記事では無人で回るプロセスに人の判断をどう残したかを、設計の考え方を中心に紹介します。 目的は少ない人数でリリースの量を上げること 最初に何のために作ったかですが、目的は限られた人数のままリリースの量を増やし、届けられる価値を増やすことです。 制約は人の時間でした。指示を書く、定型作業をこなす、AI とのペア作業に立ち会う、レビューする。こうした時間が足りず、大きな機能開発をしている間は、他の対応がなかなか進みませんでした。 1件ずつの速さなら、人と AI がペアで進めるほうが速いです。ただ、ペアでは人がその場に張り付く時間は減りません。無人のループが勝つのは、人が張り付かなくても工程を跨いで並行に回せる量です。人の時間は判断にだけ使う。無人で回すのはそのための手段です。 使う側から見た1件の流れ 使う側から見ると、この仕組みは同僚に仕事を頼むのに近い感覚で使えます。1件の Issue が ready からマージまで進む様子を、人の目線でたどってみます。 ready を付けると、トリアージが始まる 担当者が自分の Issue に ready というラベルを付けます。人がすることはこれだけです。平日の日中なら、トリアージの定期ループがその Issue を拾います。 AI はトリアージの結果と、仮説つきの質問を Issue に書き、Slack で知らせてきます。「こういう意図だと理解しましたが、合っていますか」という形で聞いてくるので、人は普段通りに返信すれば答えになります。 3日たっても返事が無ければ、AI はその Issue を作業中から外し、論点をまとめたコメントを残して待つのをやめます。人が話し合って方針を決め、もう一度 ready を付ければ再開します。 仕様書が PR で届く 疑問が解けると AI が仕様書を書き、PR として届けます。このとき AI はチェックシートの下書きも作り、その結果を PR の本文に載せます。レビュー待ちになったことは Slack で知らせてきます。人は PR をレビューし、問題がなければマージします。 PR に指摘を書けば、AI が仕様書を直して PR を更新し、また Slack で知らせてきます。指摘が仕様の前提を覆すような内容なら、AI はトリアージからやり直します。 小さな修正では仕様書を省きます。その代わりに、Issue に書かれた対応方針を確認してほしいと AI がコメントしてくるので、人は「OK」と返すだけで先に進みます。 実装も PR で届き、いつも通りレビューしてマージする 仕様書の PR をマージすると、順番が来たところで実装が始まります。実装が終わると、AI が実装 PR を作り、Slack で知らせてきます。実装 PR には、動作確認の観点とチェックシートの確認欄が付いています。 実装 PR は AI が作るので、依頼した人はいつも通りレビューして、承認・マージできます。レビューで指摘を書けば、AI が直してもう一度レビュー待ちにします。 迷わないための工夫 無人で回る仕組みは、人が「いま何を待たれているのか」を見失うと止まります。そこで、人が迷わないための工夫をいくつか入れています。 AI が止まって人に何かを頼むときのコメントは、お願いしたいことを最初に書きます。その後に、次に何が動くか、人の追加操作は要らないこと、急ぐときは手動で実行して良いことを続けます 人は自分が assignee になっている Issue だけを見れば良いようにしています。担当が別の人なら、その人のループが受け持ちます Slack の通知は営業時間内に新しい出来事があったときだけ、担当者宛てに届きます。通知が来たら見る、という使い方で回ります 構造: 状態ラベルとループ この体験を支えている骨格は単純です。 記事用に簡略化した図 Issue に状態ラベルを1つ付け、工程ごとのループがそれぞれ担当の状態を拾って、処理を終えたら次の状態へ渡します。ループは7つあり、トリアージ、仕様書の作成、実装、PR のレビュー、開発完了処理、テストで見つかった不具合の一次調査を受け持っています。残りの1つは Slack への通知を受け持ち、PR がマージされたといった外で起きたことを見て、状態ラベルを先へ進める役も兼ねています。 全体を指揮する司令塔は置いていません。各ループは自分の担当の状態の Issue があるかを見て、あれば処理するだけです。このため、ループごとに責務がはっきり分かれ、1つのループを直しても他に波及しにくくなっています。 状態の移り方は状態遷移表で制限しています。表にない遷移を AI が試みると、ラベルを付け替えるスクリプトが拒否します。入口の ready は人だけが付けられるラベルで、AI 側からは付けられないようにしています。 各ループが何を受け取り、何を作り、どの状態へ渡すかは、ループごとの定義ファイルで宣言しています。宣言した遷移が状態遷移表に無ければ、機械の検査が落ちます。全体図もこの定義ファイルから生成しているので、図だけが古くなって取り残されることが起きにくくなっています。 人の判断の置き場所 量が増えるほど、人のレビューがボトルネックになります。人の判断の負荷を抑えつつ、判断そのものは手放さない。この章ではそのために人の判断をどこに置いたかを書きます。 承認ゲートは2つに絞る 主な承認ゲートは仕様書のレビューと実装 PR のレビューの2つです。小さな修正では仕様書の代わりに、Issue 上で対応方針を確認してもらいます。実装の途中やテストの実行には承認ゲートを置いていません。判断が要らない工程に人を立ち会わせると、そこで量が止まるからです。 仕様書のレビューを承認ゲートにしているのは、SDD(仕様駆動開発)の考え方を取り入れているからです。仕様の段階で人と AI が合意しておけば、実装はその仕様に沿って進められます。 チェックシートは AI が下書きし、人が確定する 私たちの開発ではリリースまでにいくつかのチェックシートを通す必要があります。この記入は AI が下書きし、判定の確定は人がします。この境界を守るために、次の決まりを設けています。 AI は人が確定した判定を上書きしません 開発の途中では AI が付けた「要確認」を AI 自身は取り下げません。完成したコードで見直した結果を提案することはありますが、確定するのは人だけです AI の記入には印を付け、人の記入と区別できる形で書きます 人が普段通りに書いた確定のメモを、AI の側で読み取ります。読めない形なら、保留して人に聞きます 最後の決まりは、人に入力の型を覚えさせないためです。人の書き方に、機械のほうを合わせています。 また、AI の記入には、人がどれくらい注意して見るかの目安として、確信度を付けています。 安心して任せられる理由 無人で回すからには、事故を起こさないこと、起きたときに後から追えることが欠かせません。 指示・手順で頼むことと、コードで強制することを分ける AI への指示・手順はどれだけ丁寧に書いても一定の確率で破られます。そこで、指示・手順で頼むことと、コードで強制することを分けました。 AI の操作は3つの層で限定しています。 GitHub や社内の資料、スプレッドシートといった外への書き込みは、ラッパースクリプトを通してしか行えません。ラッパースクリプトに無い操作は、そもそも実行する手段がありません 実行して良いコマンドは許可リストで決めています。リストに無いコマンドは、無人の実行では誰も許可しないので、そこで止まってしまいます そうなる前に hooks が検知して止め、代わりに使う正しいコマンドを AI に伝えます。許可したコマンドを使った抜け道も、同じ hooks が塞ぎます このため、Claude Code の auto モードに頼らなくても、無人で回る設計になっています。 例えば git の操作は、ラッパースクリプトに決まったものしかありません。 できるのは、ブランチを作る、コミットする、push する、PR を作る、といった開発に必要な操作だけです マージ、force push、ブランチの削除は、コード自体がありません 対象のリポジトリと、使って良いブランチ名の形は決まっています。main への直接の push はできません push や PR の作成のあとは、実際に反映されたかを読み直して確かめます マージは人だけの操作として残るので、承認ゲートが仕組みとして守られます。 迷ったら止まり、どこからでも再開できる 状態は Issue のラベルにあるので、どこで止まっても次の実行で続きから再開できます。再開する位置が分からなければ、推測で進めずに人に聞きます。実行ログと会話の記録も残しているので、問題が起きたら AI に原因を調べさせられます。 何が変わったか 今は大きな機能開発と並行して、不具合修正などを複数件リリースできています。少ない人数で、サーバとモバイルアプリなど複数のプラットフォームの開発を並行して回せています。 まだ甘いところと、これから もちろん、全てがうまくいっているわけではありません。 人がレビューで指摘したことが、次の案件に引き継がれません 実装を全てマージした後のリリース準備は、まだ人が担っている部分も多いです 今は自分の PC で定期実行しています。イベントをきっかけに動かすことと、PC を閉じていても回るよう、クラウドや self-hosted environments へ移すことを検討しています 他のチームにも広げたいと考えています。1件を早く仕上げたい仕事や判断の多い仕事は AI と人のペアで、数をこなしたい仕事は無人のループで、という使い分けと、無人のループで回るためのコンテキストの用意を合わせて広げていくつもりです AI を利用して無人で回すほど、人が手を動かす時間は減ります。その分、人の判断がボトルネックになるため、上記をやりつつ、人が判断する負担を減らしたいと考えています。
朝、森を歩いていた旅人が、木を切っている木こりを見かけました。夕方、同じ道を戻ると、木こりはまだ同じ木を切っています。見ると、ノコギリの刃はぼろぼろに欠けていました。 旅人が声をかけます。「木こりさん、ノコギリの刃を研いだらどうですか」。木こりは答えます。「木を切るのに忙しくて、研いでいる暇なんてないんだよ」。 『7つの習慣』の「刃を研ぐ」の文脈でよく引かれる寓話です。初めて聞いたとき、私は笑えませんでした。私のことだったからです。 こんにちは。KNDです。 仕事を進めるだけでは、仕事しか進みません。自分の仕事の仕方やスタンスをチェックして、調整して、次の行動を決める。この「自分自身への PDCA」が成長には要る、と私は思っています。 ただ、分かっていても回らない。それが木こりのジレンマです。私の個人の振り返りも続きませんでした。正確に言うと、書く週は書くのですが、 Keep / Problem / Try(KPT)を埋めて満足して終わる。翌週には先週何を書いたか覚えていない Try が「もっと主体性を発揮する」のような抽象的な宣言になり、当然のように果たされない 忙しい週は後回しにする。個人の振り返りには締切も相手もいないので、サボっても誰も困らない という状態でした。刃を研いだ方が速いと分かっていて、研げない。 この記事は、その「研げない」を、気合ではなく仕組みで解きにいった5ヶ月の記録です。やったことを一言で言うと、 毎週金曜12時に、Claude Code が向こうから振り返りにやってくる ようにしました。 木こりのジレンマ ■目次 1. 「研ぐ時間がない」の正体は、やる気ではなくコスト 2. 仕組みの全体像 3. 準備ゼロ。金曜12時、向こうから振り返りがやってくる 4. 雑でいい。整えるのは AI の仕事 5. 忘れない。1ファイル追記で AI に長期記憶を持たせる 5-1. やり逃げ防止 5-2. 週をまたいだパターン検出 6. 続けていたら、自分の成果を自分が見落としていた 6-1. デフォルトの AI は、優しすぎる 6-2. 「当たり前フィルタ」の発見 6-3. AI も間違える。事実を保証するのは自分 7. Try を「宣言」から「実験」に変える 8. 足りなかったのは相手ではなく、期日だった 9. 5ヶ月で何が変わったか、続けるための小さなルール 9-1. 変わったこと 9-2. 続けるために足したルール 10. 注意点 おわりに 1. 「研ぐ時間がない」の正体は、やる気ではなくコスト 最初は、続かないのは意志が弱いからだと思っていました。ただ、続かなかった理由を「かかっていたコスト」として並べてみると、別の構造が見えてきました。私の場合、払っていたコストは3つです。 振り返りが死ぬ理由 払っていたコスト 「さあやるぞ」と自分で始めないといけない 準備コスト。忙しい週ほど、始める気力が先に尽きる 人に見せる前提で、ちゃんとした文章にしようとする 品質コスト。書くのが億劫になり、書いても本音が丸まる 先週、先月に何を書いたか自分で覚えていないといけない 記憶コスト。毎週ゼロから書くので、点が線にならない そして4つ目。この3つを払わなくても、誰も困らない。相手がいないので、締切が永遠に来ない。 逆に言えば、この4つを仕組みで消せば、意志に頼らなくても回るはずです。そう考えて、AI に「向こうから来てもらう」設計にしました。 2. 仕組みの全体像 言い換えると、仕事の仕方の PDCA が「始まらない」「C で止まる」「D まで行かない」理由を、一つずつ潰しにいきました(この記事では C=チェック、A=調整、P=次の Try を決める、D=実行、の順で使っています)。打ち手は5つです。4つは第1節のコストを消すもので、残りの1つは運用してから分かった問題(AI が優しすぎる)への手当てです。 消したいコスト 打ち手 PDCA のどこを担うか 準備コスト プッシュ型起動。Windows のタスクスケジューラで、毎週金曜12時に Claude Code が起動する C が始まる 品質コスト 雑に書いていい。評価の物差しと出力フォーマットを AI 側に持たせ、整えるのは AI の仕事にする C が続く 記憶コスト 記録を1ファイルに追記し続け、AI の長期記憶にする C が診断になり、A と P(Try の書き直し)に繋がる 「優しすぎて何も変わらない」 AI の「いい人モード」を外す指示 C を甘くしない 「相手がいない」 Try に期日を付けて、人に言う。AI はその練習相手 D まで行く 仕組みの全体像 3. 準備ゼロ。金曜12時、向こうから振り返りがやってくる 仕組み自体はそっけないです。Windows のタスクスケジューラで、毎週金曜12時に Claude Code を起動するだけ。 プログラム: cmd.exe 引数: /k cd /d C:\work && claude %date%の週次コンピテンシー評価を振り返ります。Keep/Problem/Tryで一言ずつ書きます。 タスクスケジューラ(Windows) 短い1行ですが、設計意図が4つ詰まっています。 /k : コマンド実行後もウィンドウを閉じない。そのまま Claude Code との対話が始まる %date% : 当日の日付がプロンプトに入り、「どの週の記録か」が自動で決まる プロンプトが一人称の宣言文 : 「振り返ります」「書きます」。金曜の自分に「やるぞ」と期待しても裏切られるので、ウィンドウが開いた瞬間、もう書き始めるしかない状態を作る コマンド名を覚えなくていい : プロンプトに「コンピテンシー評価」とあるだけで、コンピテンシー評価に関するスキルが自動で起動する(このスキルは第4節で説明)。覚えることが無いのが、そのまま「運用が続く」に直結する 金曜12時にしたのは、AI の回答待ちのような5〜10分の隙間で書けるからです。 4. 雑でいい。整えるのは AI の仕事 ウィンドウが開いたら、私は雑に書きます。本当に雑です。 keep 設計書の1稿出した。AIに書かせて全部読んで直した。初動が楽 problem レビュー対応、期限聞かれてから出した。だめ 稼働入力 2週分たまってる。。 これはあくまで一例で、言いたいことが溜まっている週は長文を殴り書きすることもあります。粒度も量も、その週次第。Try が無くても気にしない。人に見せる文章ではないので、文の体裁も、順番も、整えません。 この「雑でいい」が、仕組みの中でかなり重要でした。書き始めるハードルが下がるだけでなく、本音が丸まらなくなります。 人に話す前提の振り返りには「これを言ったらどう見えるか」というフィルタが入る。AI 相手だとこれがゼロになり、「納得していなかったのに、角が立つと思って折れた」のような体裁の悪い事実を、そのまま出せる。振り返りの精度は入力の正直さで決まるので、これは思った以上に効きました。 雑な入力を「診断」に変えるために、AI 側には2つのものを持たせています。 1つ目は、評価の物差しです。 弊社には等級ごとに「この等級ならこういう行動が期待される」という定義があり、その Markdown(md)版を AI に読ませています。 第3節で自動起動していたスキルの正体は、別のチームのエンジニアが作ってくれたコンピテンシー評価用のスキルです。等級定義の md と記載ガイドラインが同梱されていて、これがそのまま物差しになります。 2つ目は、出力フォーマットの固定です。 毎回、KPT、各行動が「今の等級の要件か、一つ上の要件か」を示す表、辛口の解剖メモ、判定可能な形に直した Try、来週の確認観点、の5つの要素で返ってきます。 物差しとフォーマットがあると、雑に書いた Keep に「それは今の等級で求められる行動か、一つ上の行動か」という軸が入ります。「いい一週間でしたね」という感想ではなく、基準に照らした診断が返ってくる。 5. 忘れない。1ファイル追記で AI に長期記憶を持たせる この仕組みの本体は、たぶんここです。 振り返りの結果は、毎回同じ md ファイルに追記します。AI は毎週、そのファイルを頭から読んでから会話を始める。つまり AI はこれまでの記録を持った状態で、今週の話を聞いている 。 効果は2段階ありました。 5-1. やり逃げ防止 会話は毎回「先週の Try はどうでしたか」から始まります。しかも申告が鵜呑みにされない。 3回目の振り返りで、こんなやり取りがありました。 AI : 先週の Try は「レビューの場で、質問や提案を1つ出す」でした。どうでしたか。 私 : 今週は、該当する機会がありませんでした。 AI : 今週の Keep に「仕様書レビューで『このケースは除外する』と言われて、『結合テストは網羅でやるべきでは』と返した」とありますね。これは、まさにレビューの場で提案を出したことになりませんか。 私 : ……言われてみれば、そうですね。 やった本人が、Try の達成だと認識していなかった。この週から「Keep を書いたら先週の Try と照合する」手順が加わりました。 5-2. 週をまたいだパターン検出 これは運用して初めて分かった効果で、単発の AI 壁打ちでは原理的に起きません。 テスト作業を効率化する小さなツールを自作して、チームに共有したことがありました。次の Try は「実際に1人に使ってもらって、フィードバックをもらう」。 ところが、この依頼が5週間出せませんでした。「ツールを磨く」「共有範囲を広げる」は毎週できているのに、依頼だけが毎週「未達」として積まれていく。 4週目に AI が出してきた診断は、同じ週の2つの行動の対比でした。 私のチーム宛てに来ていた、誰の担当でもない設定の修正依頼は、自分から拾ってその日に直せた。詳しくない技術でも、AI に聞けば壁は溶ける 自作ツールの使用依頼は、4週間止まっている 技術の壁は越えられるのに、人に負荷をかける依頼だけを避けている。5週目には「スケジュールの問題ではなく、回避だ」と言い切られました。 実際、軽い依頼ではありませんでした。相手が慣れているテストの進め方を、私のツールに切り替えてもらう。便利になるか、かえって手間が増えるか分からない変更です。しかも自分で始めたことなので、期限もない。先送りするには十分でした。 6週目に依頼を出すと、翌日には使ってもらえ、フィードバックももらえました。 その週、AI はもう1つの行動を並べて、診断を絞り込みます。同じ週、私は新人の日報にコメントを書いていました。誰に言われるでもなく、すぐに書けている。相手に負荷のない「贈り物」はすぐ出せて、相手に手間を負わせる「依頼」だけが5週間止まった。避けているのは対人のやり取り全般ではなく、特定の1人に負荷をかける依頼だけだ、と。 毎週ゼロから書く振り返りでは、何週も離れたこれらの行動が同じ視界に入ることがありません。記録が1ファイルに乗っているから、AI が点を線として読める。 6. 続けていたら、自分の成果を自分が見落としていた 6-1. デフォルトの AI は、優しすぎる そのまま使うと、AI は何を書いても「素晴らしい取り組みですね」から入ります。気持ちよくはなるけれど、何も変わらない。 なので、AI の「いい人モード」を外す指示を入れています。一時期話題になった「AI の良い人フィルターを外す」プロンプトと同じ発想で、肯定から入らない・避けている盲点を指摘する・自分に嘘をついていたら教える、といった趣旨の指示です。実際に、容赦のない指摘が返ってきます(プロンプトに口調の指定は無いのに、なぜか口調まで強めになります……)。 この指示の効き目を思い知った回があります。10月のある金曜、なぜか辛口の指示が読み込まれないまま分析が始まりました。返ってきたのは、長いだけで何の役にも立たない文章でした。「物足りない」と言って起動し直し、やっといつもの診断が返ってきた。辛口は、あったら嬉しいオプションではありません。この仕組みの前提です。 6-2. 「当たり前フィルタ」の発見 辛口にしたら叱られるだけかと思っていたら、一番多く言われたのは逆のことでした。「あなたはこれを Keep に書いていない」です。 一番効いたのは8月の回です。ある文書の期限を優先して振り返りを1回飛ばし、次の回で2週分をまとめてやりました。私が書いた Keep は3つ。AI は PR の一覧を開いて、こう返してきました(実際のやり取りを一般化しています)。 AI : 設計文書の初版が、8月の第1週にマージされています。自分で決めた期限の当日です。Keep の候補にも入っていないのはなぜですか。 私 : 追加の修正がまだ揉めていて、説明の場も延期になったので……。それに、列挙していたとしても Keep には書かなかったと思います。過大評価ではないですか。 AI : 揉めているのは追加の修正の方で、初版ではありません。初版はレビューを通ってマージ済みです。過大評価かどうかは、感覚ではなく現物で判定できます。 その期でいちばん重要な出来事でした。「延期」という直近の悪い知らせが、もう終わっている成果を丸ごと塗りつぶしていた。忘れていたのではなく、知っていて、書くほどのことだと思えなかったのです。 AI はさらに、6月の回に自分で書いた指摘を引いてきました。振り返りで最初に出てこない行動は、月次の 1on1 や期末の評価では確実に消える。これがその最大の実例だ、と。2ヶ月前の自分の言葉を持ち出してくるのは、記録を全部読んでいる相手ならではです。 5ヶ月続けると、この「当たり前フィルタ」には変種があることも分かってきました。 一つ上の等級に相当する行動を、下の等級の言葉に翻訳して書く。実装を「早く、指摘なく終わらせた」と書いた週、PR で設計に提案して採用された事実は、聞かれるまで出てきませんでした 行動したのに「今週は機会がなかった」と申告する(自分の行動が Try に該当すると気づいていない) やっていることを、やっていないと思い込む。「期日はあまり言ってこなかった気がする」と書いた週、記録を数えたら3週で8回言っていました 仕組みや段取りの工夫は Keep に上がるのに、対人の「攻め」は上がらない。上司の提案に別の案を論理で返して合意を得た週、それは私の Keep に無く、AI が PR のレビュー履歴から拾い上げてきました 共通するのは、嘘も謙遜も無いことです。本気で「書くほどのことではない」と思っている。だから自力では直せない。 これは私だけの癖ではないのかもしれない、とも感じています。謙遜する人の多い日本の職場なら、同じフィルタを持っている人は少なくないのではないでしょうか。 6-3. AI も間違える。事実を保証するのは自分 ただし、AI の拾い上げが全部正しいわけではありません。この振り返りは Claude Code 上で動いているので、AI は PR や Slack の送信履歴を開いて突き合わせに行きます(Slack は MCP でつないでいます)。それでも間違えます。 たとえば、私がレビュー依頼の順番をわざと遅らせていたのを、AI が「無駄な待ち」と批判してきたことがあります。実際には、以前 1on1 でもらった助言に沿った順番でした。そう伝えて結果を見せると、AI は撤回しました。 逆に、AI 自身が書いた未レビューのドラフトを私の成果だと思い込み、「今期最強の成果物」と数えてきたこともあります。これは突き返しました。第6-2節とは、ちょうど逆向きです。 過大は削り、過小は主張する。AI は物差しにも記憶にもなるけれど、事実の最終保証者にはなれません。記録の信頼性を最後に支えるのは、本人が事実を盛りも削りもしないことです。 7. Try を「宣言」から「実験」に変える 振り返りが次に繋がらない理由のひとつは、Try の書き方にあると思うようになりました。 5月のある週、レビュー対応の予定を自分から出さず、上司に「いつ対応?」と聞かれたことがありました。その反省で書いた Try が「全タスクで主体性を発揮する」。悪くない宣言ですが、達成したかどうかを金曜に判定できません。判定できないものは、未達にもならない。だから何も変わらない。 AI に書き直させると、こうなります。 次にレビュー指摘を受けたら、聞かれる前に24時間以内に「対応範囲・完了予定日・次のレビュー出し先」を自分から上司に提示する。 誰に、何を、いつまでに。できたか判定できる形です。そして未達なら、未達と記録される。 未達になる Try は毎週あります。ただ、「5週間出せなかった依頼」がそのまま壁の発見に繋がったように、 未達の記録は失敗ログではなく診断データになります 。 これは、仕事の中身とも繋がっています。等級定義に書かれた行動は、私の読み方では「顧客に届く価値を、どれだけ自力で、周りを巻き込んで、速く出せるか」の段階です。レビュー対応の期日を自分から言う、という小さな Try は、リリースの予定を守ること、つまり顧客との約束を守ることに直結しています。研ぐのは、木を切るためです。 8. 足りなかったのは相手ではなく、期日だった 9月の記録に、私はこう書いていました。 人にやることを出していくといい。人との約束は破れないから。 AI の返事は「半分正しい」でした。記録の中に反例があったからです。 8月の終わり、レビューの指摘を直して「ご確認お願いします」と返した件があります。相手は翌日にコメントをくれたのに、私はそのあと8営業日、返していません。一方で、「明日出します」と相手に言った文書は、翌日に出せています。 違いは期日でした。「ご確認お願いします」には、自分の期日がありません。効いていたのは、人に言ったことではなく、 いつまでにを自分の口で言ったこと でした。 そこで、期日を2か所で口に出すことにしました。 1つは Claude です。 返信や資料の下書きができたら、毎日使っている Claude に「いつ出すか/何の後に出すか」を言う。言えないなら、後回しにしているだけ。AI 相手でも、日時を言っておかないとなあなあになるのは同じです。そして人に言うよりずっとラフに言えるので、期日を口にする練習になります。 もう1つは上司です。 10月のある金曜、振り返りの日の午後にちょうど 1on1 があり、その日に決めた Try を口に出しました。「レビューの指摘をもらったら、いつまでに直して返すかを先に伝える」。上司は、じっくり耳を傾けてくれました。私がしたのは、口に出して聞いてもらうことだけです。それでも、人に言った後は「やっていかなければ」という気持ちが一段上がります。この回から、Try は1つに絞って 1on1 で口に出しています。 結果は、まだ途中です。9月半ばからの3週で、外に向けて言った期日は8回。守れたのは3回でした。言えば守れる、というわけではありません。それでも、言ってあれば、崩れそうになった時点で自分から調整を切り出せます。 役割分担はこうです。 掘るのは AI と。 忖度がなく、体裁の悪い事実をそのまま出せる相手だから、正直に掘れる。 期日は人に言う。 AI は、そのための練習相手です。 9. 5ヶ月で何が変わったか、続けるための小さなルール 9-1. 変わったこと 続いた。 5ヶ月で19回。皆勤ではなく、体調や繁忙や連休で飛ばした週もあります。ただ「途切れてそのまま消滅」は起きていません。やる気を必要としない設計にしたからだと思っています。 行動が変わった。 4月の記録には、チームの運用で気になる点があったのに「まあいいか」で動かなかった、とあります。6月には、結合テストで検証環境の取り合いが起きているのを見て、QA に「調整用の場所を作りませんか」と自分から持ちかけました。話はスプレッドシートでの管理に落ち着き、環境の調整がしやすくなりました。振り返りが先か行動が先かは、正直に分離できません。ただ、記録の上では別人です。 振り返りが平日に食い込み始めた。 仕事中に何かつまずくと「これは金曜の振り返りで書こう」と、その場で考えるようになりました。反省を捕まえる網が、金曜だけでなく普段から張られている状態です。狙い以上の効果でした。 9-2. 続けるために足したルール 振り返りの仕組みは、立ち上げより延命の方が難しいです。5ヶ月の間に、破綻しかけては直したルールを挙げます。 翌営業日ルール : 金曜に急ぎの仕事があれば、無理せず翌営業日にやる。「来週まとめて」が消滅の入り口なので、先送り先を1日に固定する。ただし、1日の遅れでも影響は出ます。月曜に回した週の記録には「月曜に回すと処方が1週間分抜ける」とありました。翌営業日はあくまで逃げ道で、基本は金曜です 5分の縮退運転 : それも無理な週は「今週作ったもの・出したものの列挙だけ」を5分でやる。内省は後日でいい。振り返りの第一の価値は内省ではなく 捕捉 で、捕捉だけは後から取り戻せません。第6-2節の設計文書も、振り返りを1回飛ばした間の出来事でした 列挙は記憶ベースでなく成果物ベース : KPT を書く前に、PR 一覧や案件フォルダの更新ファイルから「作ったもの・出したもの」を機械的に並べる。記憶ベースだと、当たり前フィルタを通過したものしか出てこない 人に出したものは Slack の送信履歴から引く : 人に向けた行動ほど記録から落ちる、と分かったので、自分の送信履歴を日付で検索して並べる。文面を作っただけで送っていないものは「未送」と書く。「送ったつもり」が一番見つけにくい穴でした 10. 注意点 評価そのものを AI にやらせているわけではありません。自己評価を書くための壁打ち相手で、評価するのは人間です 評価基準のドキュメントや業務の話を扱うので、使う AI ツールが社内のルール上問題ないか(入力したデータの扱いなど)は確認した上でやっています おわりに 私は「研ぐ時間」を自分で捻出するのをやめました。10分ですら、自分からは捻出できなかったからです。研ぐ時間は、向こうから来る。来たら雑に書く。覚えておくのは AI の仕事。事実を確かめるのは、自分の仕事。これなら、忙しい週でも回ります。 仕事の PDCA は、仕事をしていれば勝手に回ります。仕事の仕方の PDCA は、仕組みがないと回りません。D はまだ途中ですが、C・A・P が毎週来るようになっただけで、記録の上の自分は4月とは別人になりました。 フル装備でなくてもいいと思います。タスクスケジューラの1行と、記録を1ファイルに溜めること、そして AI のいい人モードを外す指示。この3つだけでも、AI の返答は「感想」から「診断」に変わります。 ここに出てくる行動は、一つずつ見れば薄いものばかりです。期日を自分から言う、環境の調整方法を持ちかける、1人に試してほしいと頼む。それ単体で何かが変わるわけではありません。 それでも、 そういう薄い一つを取りこぼさずに捕まえて、内省して、次の行動に変える。その積み重ねが、自分の糧になる。 私はそう信じています。薄いからこそ、放っておけば当たり前フィルタに消される。 木こりにとっての「刃を研ぐ」は、そういう地味な作業のことだと思っています。
はじめに 楽楽販売を担当している梶です。 運用の知識をAIから引ける(AIが検索して参照できる)ようにして、開発フローの概要設計に運用影響の確認を組み込むところまで来たので、その経緯を書きます。最初から全体を設計していたわけではなく、気づきのたびに一段ずつ足してきた記録です。 運用への影響は、できるだけ設計の段階で拾っておきたいと考えています。サービスを利用するお客様の業務を止めないため、そして、そのための運用を無理なく続けるためです。 「運用のことは、あの人に聞かないと分からない」という状況に心当たりのある開発者や運用担当の方に、読んでいただけたらうれしいです。 はじめに 設計の段階で、運用影響に気づくきっかけが限られていた 段階1:Markdown化とMCPサーバ 段階2:AIに先に引かせる案内文 段階3:概要設計の確認工程 よさそうだが、測りづらい 概要設計で運用影響を確認するスキル 1か月の評価期間 これから おわりに 設計の段階で、運用影響に気づくきっかけが限られていた 楽楽販売は長く提供しているサービスで、運用手順や「この作業ではここに気をつける」といった判断の知識が積み重なっています。その知識は、長く在籍しているメンバーや運用を担当しているメンバーに集まっていました。資料自体は存在していても、どこに何があるかを知っている人は限られていました。 そのため、設計時に運用への影響を考慮できるかどうかは、次のような条件で決まっていました。 運用を担当しているメンバーが、意図的にレビューに入る 開発を担当するメンバーが、似た過去事例を知っている 案件の性質から「運用に聞いておいた方がよさそう」と感じる どれにも当てはまらない案件では、運用影響は設計の段階では表に出にくく、後の工程で運用に詳しいメンバーが拾っていました。気づくのが遅いほど、取れる対応も限られます。設計の段階であればアプリ側で解消できたかもしれないものも、後の工程では、運用手順やインフラのジョブで吸収するほうがその時点では負担が小さい、という判断になることがありました。 また、気にした方がよいと感じていても、何を確認すればよいかの手がかりがないので、質問も具体的にしにくい状態でした。 段階1:Markdown化とMCPサーバ 普段の業務でClaude CodeやCodexを使う中で、「AIがこれだけちゃんとやってくれるなら、AIから引けるようにさえすればなんとかなるんじゃないか」と考えたのが出発点でした。 最初は、手元にあった運用手順やルール、参照表などの資料をClaude CodeでMarkdownに変換し、それを検索できるMCP(Model Context Protocol)サーバを社内に立てました。AIエージェントはMCPサーバを通して文書を検索し、その結果を読んで回答や作業に使います。いわゆるRAG(検索拡張生成)の構成です。 資料は、運用系のものをあまり選別せずにまとめて入れました。試しに聞いてみると関連する文書がきちんと当たり、これだけ当たるなら使えそうだと感じました。 正直に言うと、この時点ではそれ以上のことは考えていませんでした。長期的な計画があったわけではありません。 段階2:AIに先に引かせる案内文 引ける状態はできましたが、それだけでは足りないと考えるようになりました。 運用作業をしているメンバーには、日々の作業の中で「これはどうだったか」と気づくきっかけがあり、分からなければ調べたり聞いたりする発想にもなりやすいと思います。一方で、運用作業に触れる機会が少ない開発メンバーは、ツールが使える状態であっても、「ここで運用ナレッジを引こう」と判断するきっかけがありません。使うかどうかの判断を人に任せたままでは、知らない人には届かないと考えました。 そこで、人が判断しなくてもAIが先にナレッジを引きにいくように、MCPサーバがAIに渡す案内文を書き換えました。以下は実際の案内文を簡略化したものです(名称の一部を変えています)。 書き換え前: Search operations guides, rules, and references. Use search results to identify relevant documents, then read the matched document for executable procedures. 書き換え後: You are connected to the operations knowledge base — the authoritative source for operational procedures (guides), fixed rules, and reference tables. When a question touches any topic below, search here FIRST, then read the matched document, before answering from memory or local code/grep. Topics covered: - guides (procedures): release, rollback, recovery, migration, ... - rules (criteria & conditions): release, approval, security, oss, ... - references (tables & lookup): scheduled-job, maintenance, interface, ... まず、いつ、何より先に調べるかを書きました。書き換え前は検索の使い方を説明しているだけで、どんな話題のときに使うのか、手元の記憶やコード検索とどちらを先に使うのかは書いていませんでした。書き換え後は、目次にある話題に触れたら、記憶やコード検索で答える前にまずここを調べる、と順番まで指定しています。 あわせて、トピックの目次を文書のタグから自動生成して載せました。AIにとって「何が載っているか」が分からないと、引くべき場面を判断できません。目次は文書を追加するたびに自動で更新されるので、手で保守する必要がありません。 この案内文は、AIのセッションが始まるたびにコンテキストへ載ります。利用者が運用ナレッジの存在を知らなくても、関連しそうな話題ならAIの側から先に引きにいくように促せます。 インフラチームから相談を受けたときには、この仕組みが効いていると感じました。相談内容が書かれたスプレッドシートのリンクに「この件相談したい」とだけ添えてClaude Codeに渡したところ、指示していない運用ナレッジも自分から引き、まさに議論したかった論点を挙げてくれました。もっとも、もとの相談が具体的に書かれていたことも大きかったと思います。 段階3:概要設計の確認工程 よさそうだが、測りづらい 「知らなくても引ける」状態に近づき、定性的にはよい取り組みだと言えるようになりました。一方で、成果として示しにくいことに、私自身モヤモヤしていました。AIがタスクの途中で引く仕組みなので、利用者本人も「使った」という実感を持ちにくいのです。 そんなときに、周囲に相談していた中で「開発フローに組み込んではどうか」という話が出ました。使われないツールでは意味がないので、使われる場面が自然に生まれるのを待つのはやめて、確認する場面を工程として置く方向で検討を進めました。 概要設計で運用影響を確認するスキル そこで、概要設計の段階で設計内容と運用ナレッジを突き合わせ、運用影響を洗い出すClaude Codeのスキルを作りました。作る中でつまずいたのが、検索の当て方です。 最初は設計書の差分やDDLをそのまま検索にかけていましたが、当たるべき文書に当たらず「該当なし」になることがありました。設計書の言葉と、運用手順書に書かれている言葉が違うからです。そこで、変更点をいったん「何をしようとしているか」という自然文に起こし、運用文書に書かれていそうな言葉で検索するようにしました。 出力にも決まりを設けました。 該当がなかったときは「運用影響なし」ではなく「現時点で該当なし」と書く。ナレッジに載っている範囲との突き合わせであって、運用全体の網羅的な確認ではないため 出すのはあくまで提案で、採否は設計者が判断する 1か月の評価期間 いきなり必須にはせず、約1か月の評価期間を設けました。合格の基準は結果を見る前に決めて固定し、自分の案件だけでなく、チームメンバーが実際に書いた概要設計で試してもらいました。試用の中では、設計者が見落としていた運用の観点を拾えたケースもありました。 その結果を受けて、2026年9月下旬から、概要設計のチェックリストに「運用への影響を考慮したか」という項目を加えました。運用ナレッジとの突き合わせには、このスキルを使うよう添えています。 これから 今のチェックは、設計の「入口」での確認です。今後は、受入テストや結合テストといった「出口」のタイミングでも運用影響を確認し、その判断の結果を証跡として残せるようにしたいと考えています。 あわせて、運用側として「ここは運用レビューを必須にする」という線引きを定義することも次の課題です。この線が曖昧だと、結局は確認や相談が有識者に集まってしまいます。 おわりに 有識者への依存を減らしたいのは、お客様の業務を止めないための運用を、無理なく続けるためです。 同じように「運用のことはあの人に聞かないと」という状況にいる方は、まずは手元の運用資料をAIから引けるようにしてみてはいかがでしょうか。数本だと当たり外れが分かりにくいのですが、まとめて入れると「使えそうか」の手応えがつかみやすいと思います。 最後までお読みいただき、ありがとうございました。
目次 はじめに サマリ 人間はタスクを完全には並列処理できない 以前にも承認待ちの課題は存在していた 作った仕組みと設計上の工夫 issueの選定条件を明確にする 1回の実行で1 issueだけ扱う 複数のリポジトリを横断してコンテキストを集める まとめ 参考文献 はじめに AIにコードを書いてもらえるようになると、実装は一気に速くなりますが、実装そのものが速くなったからといって、開発全体が速くなるとは限りません。 AIに実装を依頼するには、対応するタスクを選び、必要な資料や前提を集め、実行結果を確認し、次の作業を起動する必要があります。これらの工程に人間の手作業や待ち時間が残っていると、実装速度が上がるほど、今度は実装以外の部分がボトルネックになります。 私自身、SkillsやRules、リポジトリ固有のコンテキストを整えることで、AIによる実装が少しずつ速くなっていることを感じていました。一方で、AIに任せたいタスクがあっても、人間がセッションを立ち上げて指示を出さなければ、作業は始まりません。実装以外の部分には、依然として人間による起動や確認が残っていました。 また、同期的に会話をしながら複数のタスクを切り替えることにも限界を感じていました。AIに任せられる範囲を広げるだけでなく、人間が見るべきものを絞る必要があると考えました。 そこで、Claude Codeのルーティンを使い、実装タスクを定期的に進める仕組みを設計しました。目的は、人間を完全に開発から外すことではなく、人間が判断すべき仕事に集中できるよう、繰り返し作業や待ち時間を減らすことにあります。 この記事では、対象となるissueをどのように選び、必要なコンテキストをどう集め、実装からドラフトPRの作成、レビュー、報告までをどのように自動化したのかを紹介します。 サマリ 今回の課題に対して、 Claude Codeのルーティン を使った仕組みを作りました。 このルーティンは1時間ごとに実行され、対応するissueの選定から、必要なコンテキストの収集、実装、セルフレビュー、ドラフトPRの作成、AIレビュー、実行結果の報告までを行います。1回の実行で扱うissueを1件に絞り、対応方針が明確なものだけを対象にすることで、無人で動かす範囲を限定しました。 *1 一方で、仕様やマージの判断などは人間に残しています。今回の自動化の目的は、人間を開発から外すことではなく、人間の判断が不要な箇所への介入を減らすことです。 人間はタスクを完全には並列処理できない ここでは、AIの実装速度が上がると、なぜ人間がボトルネックになりやすいのかを考えてみます。 人間は複数のタスクを同時に抱えることができます。しかし、それらを同じ瞬間に判断し、行動まで進めることは簡単ではありません。人間が一度に意識して扱える作業情報には限りがあります。一つのタスクを覚えるだけでも、目的、優先度、変更箇所、制約、現在の進捗など、複数の情報を保持する必要があります。複数のタスクを同時に抱えると、すぐに扱う情報が増えていきます。仮に複数のタスクを並列に進められたとしても、すべてのタスクの状況を同じ精度で保持し続けることは難しくなります。 そのため、タスクAに取り組んでいる間、タスクBやタスクCは待ちの状態になります。タスクAを一区切りつけてからタスクBへ移り、さらにタスクCへ移るというように、人間の注意や判断を切り替えながら作業を進めることになります。この状態を、時間の流れに沿って図にすると次のようになります。 タスク切り替えの図 タスクを切り替えるときは、単に別の画面を見るだけではなく、注意を向ける対象も切り替える必要があります。そのため、複数のタスクを並列に進めているように見えても、実際には人間がタスクを切り替えながら、一つずつ処理していることが多くあります。 以前にも承認待ちの課題は存在していた 承認待ちは今回初めて現れた問題ではありません。Auto Modeの登場以前、セッション中には人間の承認を待つ場面がありました。ファイル編集やコマンド実行など、Claude Codeが次のアクションへ進む前に許可を求めることがありました。人間が画面を確認して許可を出せば処理は進みますが、その間はAIも待ち状態になります。 承認待ちをなくすだけであれば、 --dangerously-skip-permissions を使う方法がありますが、このオプションは権限確認を省略し、Claude Codeにすべてのアクションを実行させるためのものです。この方法では安全性の問題が残るため、解決策にはなりません。公式ドキュメントでも、 --dangerously-skip-permissions はすべてのアクションを確認なしで実行するモードであり、隔離されたコンテナや仮想マシンで使うことが推奨されています。 現在のClaude Codeでは、Auto Modeがデフォルトになりました。Auto Modeでは、通常のようにすべてのアクションを人間に確認するのではなく、別のモデルで構成された分類器がツール呼び出しを確認します。危険な操作や環境外への操作などを検出した場合は、処理を止めたり、より安全な方法を選んだり、人間に確認を求めたりします。つまり、Auto Modeは確認をすべて無視するのではなく、AIによるチェックを挟みながら長く実行できるようにする仕組みです。 AIによる判断が安全なものか気になるかもしれませんが、 Anthropicが公開した検証 では、危険なコマンドを人間の手動確認とAuto Modeがどの程度検出できるかを比較し、人間の手動確認が危険なコマンドを検出できた割合は13.6%、Auto Modeは89%だったと報告されています。つまり、Auto Modeは人間の手動確認よりも高い割合で危険なコマンドを検出したとされています。 今回解決したい課題は、Auto Modeが扱っている問題と似ていると考えました。タスクの目的や実行してよい範囲が明確であれば、人間がすべての操作に介入しなくても、AIに作業を任せやすくなります。 そこで、同じ考え方を、セッションの外側にも広げられないかと考えました。どのissueを選び、必要なコンテキストを集め、セッションを起動するかという作業も、条件を定めたうえでAIに任せられるのではないか、という発想です。 作った仕組みと設計上の工夫 今回作った仕組みは、GitHubのissueを起点に、実装からドラフトPRの作成、レビュー、結果の報告までを定期的に進めるルーティンです。 全体の流れは次の図のようになります。 ルーティン全体像の図 issueの選定条件を明確にする 定期実行されるルーティンでは、issueの曖昧さをAIが勝手に補う可能性があります。 そこで、AssigneeやLabelなどの管理情報を、自動実行してよいissueを選ぶための手がかりとして使っています。issue本文の自然言語だけで判断させるのではなく、機械的に確認できる条件を先に置くことで、対象範囲を狭くしています。 1回の実行で1 issueだけ扱う 候補issueが複数あったとしても、1回の実行で着手するのは1件だけにしました。 複数のissueを同時に処理すれば、単純に処理量を増やせます。しかし、無人実行では、どこか一つの判断を誤ったときに複数の変更へ影響が広がります。また、失敗したissueと成功したissueが混ざると、後から原因を確認することも難しくなります。 1回1 issueに制限すると、処理量は減ります。その代わり、どのissueを処理したのか、どこで止まったのか、どの成果物が生成されたのかを追いやすくなります。 また、1回の実行で扱うissueの背景や関連資料などのコンテキストも抑えられるため、AIが参照すべき情報を絞りやすくなります。今回は処理量の最大化よりも、コンテキストを過度に広げず、失敗したときに戻しやすいことを優先しました。 複数のリポジトリを横断してコンテキストを集める issueの本文には、目的、対応範囲、完了条件が分かるように記載していますが、これだけでは実装に必要な情報が足りないことがあります。 現在担当している案件では、実装に必要な情報が複数のリポジトリに分散しています。参照できるリポジトリが限られるとコンテキストが足りず精度が落ちるため、各リポジトリの役割や参照先をまとめたリポジトリを用意し、コンテキスト収集の最初に参照させるようにしました。 まとめ 実際に運用してみると、人間がセッションを起動したり、作業の進捗を確認したりしなくても、手が離れている時間に実装タスクを進められるようになりました。実装を待つ時間や、次の作業を起動する手間が減り、人間は仕様の確認や成果物のレビューなど、判断が必要な作業に集中しやすくなりました。 これにより、仕様がお客様の業務に合っているか、画面が使いやすいかといった、お客様への価値に直結する確認に時間を充てやすくなりました。 今回の取り組みでは、実装にかかる時間が短くなったからこそ、次はその周辺に残っている作業や待ち時間を減らし、開発フロー全体を整えたいと考えました。AIにコードを書かせるだけでなく、AIが継続的に作業できるフローを設計することが重要になると考えています。 参考文献 Claude Code Docs「権限モードを選択する」 Claude by Anthropic「Auto mode is now the default in Claude Code」 Claude Code Docs「ルーティン」 *1 : ここでのセルフレビューは、実装を行ったClaude Codeのセッションが、自身の変更内容を見直す工程です。AIレビューは、ドラフトPRの作成後に別のAIがPRを確認する工程を指します。
■ 目次 はじめに このブログの概要 対象読者と前提知識 1. なぜ、そうなっていたのか? オンプレミスという前提 Kubernetes導入で得られたもの 残った4つの課題 「境界」と「粒度」 2. 境界をどう引き直したのか? Namespaceの割り当て先 Tenant境界の導入 セルフサービスでの環境発行 エコシステムのテナント分離 論理的な境界の積み重ね 3. リソースの粒度をどう変えたのか? k8sリソースの粒度の問題 マニフェスト抽象化OSSの選定 PlatformAppの記述例 拡張性とガードレールの両立 4. 今後の課題 まとめ はじめに こんにちは。SREの gumamon です! Platform Engineering という言葉をよく聞くようになりました。開発チームが、必要なインフラや開発環境を自分たちで利用できる「セルフサービス」の仕組みを提供する取り組みです。 パブリッククラウドには、そのためのAPIが豊富に用意されています。一方、私たちのKubernetes環境は主にオンプレミス上にあり、同じような仕組みを自分たちで用意する必要がありました。 そこで、社内向けのコンテナ・プラットフォームを開発することにしました。本記事では仮に Platform と呼びます。 オンプレミスという事情から始まったPlatformですが、設計を進める中で直面した課題の多くは、パブリッククラウドでも変わりません。本記事では、その中から特に重要だった設計判断を紹介します。 このブログの概要 この記事では、オンプレミスのKubernetesを複数のプロダクトで利用する社内プラットフォームを題材に、 「境界」と「粒度」をどう引き直したのか を紹介します。 具体的には、以下の内容を扱います。 複数プロダクトを安全に収容するためのテナント境界をどう設計したか 環境発行のセルフサービス化をどう実現したか リソースの抽象化により利用者の認知負荷を削減しつつ、拡張性とガードレールをどう両立したか 「Kubernetesは入れたものの、そこから先に進めない」という状態は、決して珍しくないと思います。私たちがどこに課題を見つけ、どのような考え方で設計を変えていったのかを、順を追って紹介します。 本記事では、Platformを利用するプロダクト(およびその開発チーム)を「テナント(Tenant)」と呼びます。 対象読者と前提知識 社内向けにKubernetes基盤を提供している方 Platform Engineering、特にマルチテナンシーの設計に関心がある方 Kubernetesを導入したものの、組織への横展開が進まないと感じている方 前提知識はNamespace / Deployment / GitOpsの概要が分かる程度で十分です。CapsuleやkroといったOSSについては本文中で都度説明します。 1. なぜ、そうなっていたのか? オンプレミスという前提 まず、Platformを作る前の状態からご紹介します。 Platform Engineeringの文脈でよく語られる「セルフサービス」は、パブリッククラウドを前提にしていることが多いです。AWSであれば、アカウントを1つ増やす、VPCを1つ切る、といった操作がサービスとして提供されています。開発チームは申請書を書くのではなく、APIを通じて必要な環境を手に入れられます。 一方、私たちのKubernetes環境は主にオンプレミス上にあります。従量課金を避けられるのは大きな利点ですが、「アカウントを増やす」に相当する仕組みは当然ながら存在しません。 それでも同じような体験に近づけたいと考え、一部の商材でKubernetesを導入し、そこから社内への横展開を進めていました。 Kubernetes導入で得られたもの Kubernetesの導入によって、得られたものは確かにありました。 コンテナ化 によって、アプリケーションとインフラが疎結合になった GitOps によって、インフラ構成の変更がGitのマージで完結するようになった 結果として、マイナーリリースは開発チーム主導で回せるようになり、開発速度も向上しました。 しかし、これを商材横断で広げようとすると、別の問題が見えてきました。 残った4つの課題 ① 認知負荷が高く、横展開が進まない Kubernetesそのものに加えて、Argo CD、Vault、Grafanaといったエコシステムの知識が必要になります。 1つのWebアプリを本番品質で動かすだけでも、Deployment、Service、HTTPRoute、HPA、PodDisruptionBudget、Secretなど、多数のリソースを組み合わせなければなりません。 新たに利用する開発チームに「まずこれを覚えてください」と言える分量ではありませんでした。 ② 環境発行がセルフサービスになっていない 開発チームが検証用の環境を必要とした場合、インフラチームへクラスタ構築を依頼する必要がありました。 そのため、環境を必要としてから実際に利用できるまで、数日から数週間のリードタイムが発生していました。 ③ クラスタが増え続ける 環境を増やす手段がクラスタを増やすことだったため、クラスタは「商材 × 環境」の数だけ増えていきました。 Kubernetesはクラスタごとに管理用のコンポーネント一式を必要とします。さらに、初期構築、可観測性のセットアップ、半年に一度のKubernetesアップデート、リソース不足に伴う作り直しなどもクラスタごとに発生します。 結果として、クラスタの増加に比例して運用コストも積み上がっていました。 ④ テナントの境界が曖昧 Kubernetesには、標準機能として明確な「テナント」の概念がありません。 各商材のKubernetesクラスタは分離されていた一方、Argo CD、Vault、Grafanaなどのエコシステムは複数商材で共同利用していました。 そのため商材間のシステム境界が曖昧で、あるチームの操作が他チームへ影響し得る状態でした。安全に権限を委譲することが難しく、インフラチームによる管理が必要となっていました。 「境界」と「粒度」 一見すると別々に見える4つの問題ですが、整理すると2つの問題に集約できました。 1つは、 「境界」 です。 商材や環境をどの単位で分離し、どこまでを開発チーム自身で管理できるのか。その境界が適切に設けられていなかったことが、環境発行やクラスタ増加、権限移譲の問題につながっていました。 もう1つは、 「粒度」 です。 Kubernetesでは、1つのアプリを動かすために多数のリソースを組み合わせる必要があります。この粒度の細かさが、利用者に求める知識や設定量を増やしていました。 そこで私たちは、Kubernetesそのものを置き換えるのではなく、この 「境界」と「粒度」を引き直す ことにしました。 まずは「境界」から見ていきます。 2. 境界をどう引き直したのか? Namespaceの割り当て先 最初に整理したのは、Kubernetes上の境界です。 私たちが必要としていた境界は、大きく3つありました。 Tenant :組織・プロダクトの境界 Env :Prod、Staging、Developなどの用途別の境界 App :Web、Backend、Batch、DBなどのアプリケーションの境界 従来、これらは次のように割り当てられていました。 従来 Tenant 仕組みなし(運用ルール依存) Env Kubernetesクラスタ(要インフラ作業) App Argo CD Application + Namespace 境界(Before) ここで着目したのが、 Namespaceの使い方 です。 従来は、Web用のNamespace、Batch用のNamespaceというように、NamespaceをAppの分離に使っていました。 一見すると自然な使い方ですが、この時点でNamespaceというKubernetesの論理的な分離単位をAppのために使っています。そのためEnvを増やそうとすると、残された手段はクラスタそのものを増やすことでした。 「環境発行に数週間かかる」「クラスタが増え続ける」という課題は、症状だけを見れば運用の問題です。しかし、その原因は 境界の割り当て にありました。 そこで私たちが下した判断は、以下のとおりです。 Appの分離からNamespaceを解放し、Envの境界に再割り当てする。 Appの分離はArgo CDのApplicationが担えるため、NamespaceはEnvに譲ります。 すると、残るのがTenantの境界です。 Tenant境界の導入 KubernetesにはTenantに相当する標準の境界がありません。そこで、この層を補うために Capsule を採用しました。 CapsuleはNamespaceを束ねて1つのTenantとして扱い、その管理をテナントオーナーに移譲できるKubernetesの拡張です。 Tenantの実装方式としては、他にvCluster、マルチクラスタ、Kubernetes標準のRBACのみ、という選択肢も検討しました。いずれもリソース消費や運用負荷、テナント識別の一元管理といった観点で課題があったため、追加のコントロールプレーンを持たないCapsuleを選んでいます。 Capsuleはadmission Webhookとして動作するため、テナント利用者は普段どおり kubectl を使うだけで済みます。 Tenantは以下のように定義します。 apiVersion : capsule.clastix.io/v1beta2 kind : Tenant metadata : name : product-a spec : # Namespace名が必ず "product-a-" で始まることを強制する forceTenantPrefix : true namespaceOptions : quota : 10 # このテナントが作れるNamespaceの上限 owners : - name : product-a kind : Group resourceQuotas : scope : Tenant # テナント全体でCPU/メモリ/ストレージの上限を持つ 結果として、境界は以下のように変わりました。 従来 Platform Tenant 仕組みなし Capsule (サービスとして払い出し) Env クラスタ単位(要インフラ作業) Namespace単位(セルフサービス可) App Argo CD Application + Namespace Argo CD Application 境界(After) forceTenantPrefix によってNamespace名が必ずテナント名で始まると保証されるため、監視の設定やネットワークの制御を、テナントがNamespaceを増やしても追記の要らない形で書けるようになりました。 命名規則を強制することが、後段の自動化の前提になっています。 セルフサービスでの環境発行 境界を引き直した結果、環境の発行はテナント側リポジトリの設定ファイルに1行追加するPull Requestになりました。 # settings/namespace/values/platform-dev-001.yaml namespaces : - namespace : product-a-dev-001 - namespace : product-a-dev-002 # ← この1行を追加するだけ GitHub Actionsのフォームから実行するとこのPull Requestが自動生成され、マージすればArgo CDがNamespaceを作成します。 数週間かかっていた環境発行が、数分で完了するようになりました。 テナントにはCPU・メモリ・ストレージの上限があり、その範囲内でやりくりする形になります。上限の緩和はプラットフォーム管理者側の設定変更で対応できます。 エコシステムのテナント分離 ここまでがKubernetes側の話です。 しかし実際に手を動かしてみると、 境界は1つ引いて終わりではありませんでした。 Capsuleが守ってくれるのは、Kubernetes APIに到達したあとの世界だけです。Argo CDの画面の中や、Vaultのシークレット一覧、Grafanaのダッシュボードには届きません。 KubernetesにTenantという境界を導入したのであれば、同じ境界を周辺のコンポーネントにも伝える必要があります。 結果として、レイヤーごとに分離の方式が異なる構成になりました。 レイヤー 分離の方式 GitOps (Argo CD) テナントごとのAppProject+GitHub TeamsによるRBAC Kubernetes Capsuleの Tenant (admission Webhook) 認証 テナント名を持つクライアント証明書 シークレット (Vault) テナントごとのSecret Engine ログ (Loki) テナントIDによる振り分け メトリクス テナントごとのアカウントID トレース (Tempo) テナントIDによる振り分け 外部公開 (Gateway) テナントごとのGateway ネットワーク NetworkPolicyによるテナント間通信の遮断 エコシステムのテナント分離設計 分離の方式がレイヤーごとに異なるのは、各プロダクトが持つマルチテナント機能の実装差がそのまま表れているためです。 すべてを同じ仕組みで分離することはできず、レイヤーごとに個別の設計が必要でした。 ただし、開発チームから見た場合、いずれのエコシステムの利用も一貫した体験となるよう工夫をしてあります。 ログインは全てGithubのOAuth認証 いずれのエコシステム(UI)にログインした場合も、自身の所属するプロダクトのリソース以外が見えない状態 1章で挙げた「テナントの境界が曖昧」という課題は、ここで解消しました。 論理的な境界の積み重ね ここまでの話を一言でまとめると、Platformの分離は物理的な分離ではなく、 論理的な境界をレイヤーごとに積み重ねたもの です。 クラスタは1つのまま、その上にCapsule、Argo CDのAppProject、VaultのSecret Engine、NetworkPolicyなどを重ねています。 当然ながら万能ではありません。 ハードウェアレベルで分けたい要件があるのであれば、素直にクラスタを分けるべきです。私たちも「複数商材を1クラスタに収めることは推奨するが、強制はしない」という立場を取っています。 分離の強さと運用効率のトレードオフは、要件に応じて評価する必要があります。 3. リソースの粒度をどう変えたのか? k8sリソースの粒度の問題 ここまでが「境界」の話です。 次は、もう1つの課題である「粒度」を見ていきます。1章で挙げた「認知負荷が高く、横展開が進まない」という課題に対する打ち手です。 Kubernetesのリソースは、レゴでいえば一番小さい基本ブロックに相当します。 自由度は極めて高い反面、AWSのECSタスク定義1つで済むことを表現するのに、Deployment、Service、HTTPRoute、PodDisruptionBudget、ServiceAccount、ConfigMap、Secretなど、多数のブロックを自分で組み合わせる必要があります。 Helm Chartにすると、テンプレートは十数個、YAMLは数百行という規模になり、その大半がプロダクト間でコピー&ペーストされていました。 これが「認知負荷が高く、横展開が進まない」という課題の正体でした。 Kubernetesの細かいリソースを毎回利用者が組み立てるのではなく、社内でよく使う標準構成を、より大きな単位のブロックとして提供することにしました。 リソースの抽象化(Before / After) マニフェスト抽象化OSSの選定 マニフェストを抽象化するOSSとして、 kro (kubernetes-sigs)と KubeVela (CNCF Incubating)を比較し、kroを採用しました。 決め手はテンプレートの記述方式です。 kroのテンプレートはYAMLで、中身はほぼ素のKubernetesマニフェストです。一方のKubeVelaはCUEという独自言語と、Component / Trait / Policy / Workflow という独自概念の習得が必要でした。 ほぼ素のマニフェストで書けるということは、 基盤を作る側にとっても使う側にとっても学習コストが低く、同時に将来別の方式へ移す際のコストも低い ということです。 v0.x系の若いOSSを基盤の中核に据える以上、後戻りできる構成であることを重視しました。 PlatformAppの記述例 こうして生まれたのが PlatformApp というカスタムリソースです。APIなど、常時起動が必要なアプリケーションを簡単にデプロイするために使います。 開発チームが書くのは、以下のような定義です。 image : tag : 1.0.0 platformApp : configMap : data : GREETING : "こんにちは" deployment : replicas : 1 container : resources : requests : { cpu : 10m, memory : 32Mi } limits : { cpu : 20m, memory : 64Mi } service : port : 8080 targetPort : 8080 httpRoute : enabled : true hostnames : - product-a-dev-001.example.internal rules : - matches : - path : { type : PathPrefix, value : / } これで生成されるのは、Deployment / Service / HTTPRoute / ServiceAccount / PodDisruptionBudget / ConfigMap / Secret(Vault連携)の 7種類 です。 Probeやセキュリティ設定などにはプラットフォーム側の既定値が入るため、必須項目はコンテナイメージの指定だけです。既定のままでよければ、定義は十数行に収まります。 また、単に記述量を減らすだけでなく、 Kubernetesに詳しくない利用者でも安全に使えること を重視しています。 たとえばPodの requests / limits は必須とし、未指定の場合は既定値を設定します。これにより BestEffort QoSのPodを作らせず、共有クラスタで他のワークロードに影響を与えにくい状態を既定にしています。 同時に、CPUやメモリを見積もることを標準的な運用として意識してもらう狙いもあります。 ほかにも、利用者が意識しなくても正しく動作するための仕組みをいくつか組み込んでいますが、長くなるため本記事では割愛します。 設定しなくても安全に、正しく動く状態を既定にする ことが、PlatformAppの重要な役割だと考えています。 拡張性とガードレールの両立 抽象化を設計するうえで意識したのが、 拡張性とガードレールを両立すること です。 PlatformApp は標準的なユースケースを簡単に扱うための抽象化ですが、プラットフォーム側がすべての要件を事前に想定することはできません。 そこで、アプリケーション設計における「 修正には閉じ、拡張には開く 」という考え方を参考に、標準構成を壊さずに利用者側で拡張できる構造にしました。 ① PlatformXxx自体に柔軟性を持たせる PlatformAppでは、内包する多くのリソースの設定値を固定値ではなく既定値で埋めています。 これにより、利用者は柔軟なリソース設定が可能となっています。 なお、ここまで説明をしてきた PlatformAppは、ユースケースの一つでしかありません。 DBのデプロイを担う PlatformPg があり、非同期JobWorkerとして機能する PlatformWorker を開発予定です。 ② PlatformAppの外にも拡張できる デプロイの仕組みであるArgo CDのApplicationSetは、リポジトリ配下のディレクトリをHelm Chartとしてデプロイしているだけです。 PlatformApp はそのChartで利用できる選択肢の1つに過ぎないため、要件に合わなければ独自のHelm Chartや素のDeploymentを利用できます。 ただし、何でも自由にデプロイできるわけではありません。たとえばCluster Scopeのリソースなど、Tenantに与えられた権限を超える操作はCapsuleによってブロックされます。 つまり、 抽象化の外には出られるが、プラットフォームのガードレールの外には出られない 構造です。 ③ 段階的に使いこなせる 利用者が必要に応じて一段ずつ深いレイヤーへ進めるよう、次のような段階を想定しています。 Level 1: PlatformApp の標準構成 Level 2: PlatformApp のカスタム構成 Level 3:独自のHelm Chart Level 4:改善をプラットフォーム側に還元する 抽象化によってKubernetesを知らなくても使える入口を作りつつ、必要になったときにその内側へ進める余地は残しています。 利用者を抽象化の中に閉じ込めるのではなく、 安全性を保ちながら段階的に拡張できること を重視しました。 学習コストの「崖」を「階段」に 4. 今後の課題 Platformはまだ道半ばです。例えば以下のような課題が残っています。 テナント数に比例する運用負荷 :テナントが増えれば、テナント単位で持つコンポーネントも増えます。テナントを増やす作業そのものの自動化が次の課題です。 初期の設計判断の修正 :ここまで「粒度」を再定義するためにkroを採用したとお話ししてきましたが、Helm Chartの提供でもできるのでは?という議論を行っています。kroによる抽象化ではPlatformにデプロイするまで展開されるリソースの構成が分からないため、手元で helm template できる方が利用しやすいのでは、と思案中です。 まとめ 今回は、オンプレミスのKubernetes上に社内向けプラットフォームを構築するにあたり、「境界」と「粒度」を引き直した設計を紹介しました。 境界 :NamespaceをEnvに割り当て、Capsuleを使ってTenantの境界を追加 粒度 :複数のKubernetesリソースを PlatformApp として抽象化 これにより、クラスタを増やさずに環境をセルフサービスで発行でき、開発チームが扱うKubernetesリソースも減らすことができるようになりました。 一方で、テナント追加時の運用負荷や、kroによる抽象化が適切かどうかなど、まだ改善すべき点も残っています。 この記事が、Kubernetes基盤を横展開していく際の設計を考える一例になれば幸いです。 以上、最後までお読み頂きありがとうございました!
今回は、楽楽勤怠に組み込まれたAIチャットボット機能の開発を担当した、楽楽勤怠開発課の黒田さんに話を聞きました。 黒田さんは新卒2年目。事業部・デザイナー・インフラ担当など多くの関係者を巻き込むこの開発を、ほぼ一人で任されています。 楽楽勤怠とは 楽楽勤怠のAIチャットボットとは何か なぜこの機能を作ったのか 開発の話:工夫した点、難しかった点 実装より大変だった、社内の情報連携 当初試していたRAGの課題と方針転換 回答精度のチューニングと、こだわった速さ 今後の展望 おわりに 楽楽勤怠とは 「楽楽勤怠」は勤怠管理・給与計算をラクにするクラウド型の勤怠管理システムです。 楽楽勤怠のAIチャットボットとは何か このAIチャットボットは、よくある質問(QA)に回答する機能です。実際によく寄せられる問い合わせをもとに作られたQAをデータとして持ち、たとえば「有給休暇の設定方法」といった、操作に関する質問にチャットで答えます。過去のやり取りを踏まえて会話を続ける形ではなく、都度の質問に対してその場でQAから最適な回答を探して返す、一問一答形式のシンプルな仕組みです。 なぜこの機能を作ったのか 開発の出発点にあったのは、お客様が楽楽勤怠の操作でわからないことに直面しても、サポートサイトだけでは自己解決できず、結局CSへ問い合わせて回答を待つことになってしまう、という状況でした。 チャットボットであれば、お客様はその場ですぐに回答を得られ、業務を止めずに済みます。この一見シンプルな狙いを形にするまでには、開発の現場でいくつもの工夫と苦労がありました。 開発の話:工夫した点、難しかった点 開発はほぼ一人で担当し、同じチームの先輩にサポートしてもらいながら進めました。期間は2026年4月から6月末のリリースまで、検証を含めておよそ3ヶ月でした。 Google Cloudの知識もゼロ、社内の関係者もまだ多くは知らない状態からのスタートでしたが、それでも今回のプロジェクトでは実装の中心を任せてもらいました。 実装より大変だった、社内の情報連携 正直、実装のタスク自体はそこまで多くありませんでした。それよりも、事業部やデザイナー、インフラ担当、AI開発課など色々な関係者と何度もやり取りをしながら情報を集め、調整していくことの方が大変でした。 チャットボットに投入するQAは事業部が主導して作成しています。サポートサイトに載っている内容をすべて移行したわけではなく、実際によく寄せられていた問い合わせとその回答をもとに、新しくQAのセットを作ってもらいました。私の役割は、そのQAをデータとして仕組みに投入していく部分です。QAの追加・更新はリリース後も続く運用で、事業部が内容を作成し、開発側で個人情報などが含まれていないかをレビューしたうえでインフラ担当が反映する、という体制で回しています。 事業部との連携では、開発者側にしか見えていない考慮点を自分から拾い上げる難しさもありました。チャットボット機能を使えるユーザーの範囲や、権限をどう制御するか、機能を停止する場合にどう対応するかといった仕様上の論点は、事業部側からは見えにくいものです。自分から議題に上げないと見過ごされてしまうので、そこを拾い上げて要件を詰めていくのが大変でした。 今回、事業部とのやり取りでは、スピード感を意識して進めました。他部署とのやり取りでは、きちんとしたドキュメントに書き起こしてから送ろうとしたり、次の定例のアジェンダに入れておけばいいかと連絡を持ち越したりしがちです。ただ、その進め方だと、一度運用が走り出してから認識のズレに気づくことになり、後から直そうとするほど手戻りが大きくなってしまいます。そこで私は、事業部との週1回の定例に加えて、気になった点が出てきたらその場でチャットに書き込み、「ここに書いておいたので」と都度共有するようにしていました。さらに、事業部側で実際に操作して確認できる検証環境もあわせて提供しました。その結果、次の定例まで抱え込むことなく、その都度細かくすり合わせができたので、大きな手戻りを防ぐことができました。 当初試していたRAGの課題と方針転換 チャットボットの基盤にはGoogle CloudのDialogflow CXを採用しています。 最初はGoogle CloudのVertex AI上で、自分たちでRAGの仕組みを実装しようとしたのですが、回答までのスピードが遅く、改善にも時間を要しました。方針転換のきっかけはAI開発課への相談でした。パフォーマンスを改善したいと相談したところ、「業務システム部が同じような仕組みをすでにGoogle Cloud上に構築している」と教えてもらい、その構成を参考にする方針に切り替えました。 Google Cloudの知識がまったくない状態からのスタートだったため、業務システム部に構成や設定を教わりながら、何度もミーティングやチャットでのやり取りを重ねて理解を進めていきました。 インフラチームには、そうして把握した内容をドキュメントにまとめたうえで、本番環境の構築を依頼しました。楽楽勤怠側で実装したのは、画面のスタイル調整と、チャットボット機能を使える権限の制御程度で、ロジックの大部分はGoogle Cloud側に構築し、楽楽勤怠にはそのUIを埋め込む構成になっています。 回答精度のチューニングと、こだわった速さ 精度を検証する中では、うまく回答が見つからないケースも出てきました。その対応として、QA同士に重みを設定したり、「退職者」と「元社員」のような表記ゆれを類義語として登録し、正しく紐づくようにするチューニングが可能な仕組みになっています。このチューニング自体は主に事業部が担当していて、私は設定を行う立場でした。 速さへのこだわりも、事業部からの指摘がきっかけでした。自前で構築していた当初は応答に20秒ほどかかっていましたが、気軽な操作の質問に対してそれだけ待たされるのは体験として良くない、という事業部からの声を受けて、大きく短縮する方針に変わりました。事業部とは今も週1回のミーティングを続けており、気になる点をその都度すり合わせているため、大きな認識のズレが生まれる前に軌道修正できています。 その結果、もともと20秒ほどかかっていた応答速度は、およそ5秒にまで大幅に短縮できました。検索に特化したマネージドサービスであるGoogle CloudのAI Applicationsを使う構成にしたことが、このパフォーマンスに寄与していると考えています。 今後の展望 直近では、AIチャットボットの機能拡充を考えています。 現状はQA情報のみを参照しているため、解決しない場合にお客様ご自身で仕様や操作方法を探す必要があり、認知負荷が高い状態となっています。そこで、サポートサイトに記載されている仕様や操作方法に基づく回答の提供や、該当画面へのリンク表示などを実現したいと考えています。これにより、回答可能な範囲の拡充とお客様の検索負荷の軽減を目指します。 おわりに 今回のAIチャットボットは、お客様がサポートサイトだけでは自己解決できず、CSに問い合わせて回答を待つことになってしまう、という地道な課題を解消するところから始まりました。 新卒2年目の黒田さんが、知らない技術・知らない部署を巻き込みながら形にしたこの一歩は、楽楽勤怠全体のAI機能拡充における最初の足がかりでもあります。基盤選定やデータ作成でも、既存の知見を積極的に取り入れながら、着実に形にしていくプロセスが印象的でした。効果測定など、まだこれからの部分も含めて、今後の展開に注目していきたい機能です。
楽楽メールマーケティング開発課では現在、「AI-HTMLメール生成機能」の開発に取り組んでいます。8月26日には一部のお客様向けにβ版を先行リリースし、12月には全てのお客様へβ版をリリースする予定です。 本記事では、開発を担当する垣内繁直さんに、取り組みの背景や工夫した点、開発を振り返って感じたことをお聞きしました。 楽楽メールマーケティングとは なぜこの機能を作ることになったのか AI-HTMLメール生成機能とは、どんな機能なのか 開発で難しかったことは何か スピードと品質は、どう両立させたのか 今後、どう進化させていきたいのか 楽楽メールマーケティングとは 「楽楽メールマーケティング」はメール作成から配信まで簡単にできるメルマガ配信サービスです。 なぜこの機能を作ることになったのか 楽楽メールマーケティングでは、メールマーケティングの効果を高めるために、月6回程度の配信を推奨しています。しかし実際には、既存顧客の約50%がこの推奨回数を満たせておらず、十分に配信できていない状態が続いていました。 原因を調査したところ、大きく2つの課題があるのではないかと考えました。 1つは配信のための担当者の稼働がそもそも取れないこと、もう1つはどんなメールがお客様に刺さるのかというノウハウが不足していることです。 この2つの課題を解決する手段として着目したのが、AIによるメールの自動生成です。 AIが自動生成することで、メール1通あたりの作成時間を大幅に削減し、稼働不足を解消します。 もう一つの狙いは、既存のノウハウをAIに引き継がせることです。楽楽メールマーケティングにはこれまで多くのお客様の配信を支援してきた実績があり、その中でどのような文章がメールの成果につながりやすいかというノウハウがすでに蓄積されています。このノウハウをAIのメール生成機能に組み込むことで、AI自身が質の高いメール文面を提案できるようにしました。これにより、メールマーケティングの専門知識を持たないお客様でも、成果につながりやすいメールを作成できるようになります。 時間をかけなくても、お客様に質の高いメールを届ける。質とスピードをどちらも向上させることがこの機能の目指すところです。 AI-HTMLメール生成機能とは、どんな機能なのか メールを作成する際は、まず自社の商品・サービスを登録します。ここでは、製品ページや自社サイトのURLを入力するか、PDFファイルを取り込むだけで、AIが情報を取得・分析し、製品情報を自動で作成します。 取り込んだ製品情報をもとに、配信するメールの方針を設定します。配信目的は、アポ獲得やウェビナー集客など、楽楽メールマーケティングがこれまで培ってきた成果実績にもとづくテンプレートから、用途に応じて選択する仕組みです。配信ターゲットはAIが自動で提案し、そのまま使うこともカスタマイズすることもできます。あわせて、メール本文に埋め込む誘導ボタン(CTA)やロゴの挿入位置、署名についても設定します。 方針が固まると、製品情報と方針をもとにAIがメール本文の案を複数生成します。ユーザーが選んだ案は楽楽メールマーケティングに従来から搭載されているリッチなHTMLエディターにそのまま展開され、デザインを追加で編集したうえで配信できる仕組みです。 すでに何社かのお客様が、この機能で作成したメールをそのまま配信できているほど、高い品質に達しています。そのうえで、さらに質の高いメールを届けられるよう、生成品質の向上にも継続して取り組んでいます。 開発で難しかったことは何か 開発で難しかった点は大きく2つあります。1つは開発期間の短さです。この案件は2ヶ月でβ版をリリースするという要望があり、事業部側からも早期リリースへの強い要望がありました。 もう1つは技術的な挑戦です。バックエンドをTypeScriptで実装したこと、AI機能をこのチームで実装するのは初めてだったことなど、実績のない技術への挑戦が続きました。 技術選定には明確な理由があります。AIのモデルにOpenAIのGPTを採用したところ、対応SDKの言語がTypeScriptやGoなどに限られていました。バックエンドチームはこれまでPHPしか扱ったことがありませんでしたが、PHP向けのSDKがなかったため、楽楽自動応対のAI-FAQ機能のバックエンドですでに採用実績のあったTypeScriptを選び、開発効率を重視しました。 開発期間が短い中で、実績のない新しい技術を使って開発することが、最大の難しさでした。 スピードと品質は、どう両立させたのか AI機能そのもの、特にプロンプトの調整や生成物の品質評価は、楽楽メールマーケティング開発課とは別部署のAI開発課が担当しました。楽楽メールマーケティング開発課は、それをアプリケーションに組み込む役割を担いました。この役割分担が、2ヶ月という短期間での開発を可能にした理由の一つです。 組み込みで特に工夫したのはプロンプト周りです。AI開発課が品質を担保したプロンプトを静的ファイルとして切り出し、そのまま使う仕組みにすることで、組み込み時に品質を損なわないようにしました。 開発の進め方自体にも工夫がありました。これまでチームではウォーターフォール的に要件を固めてから開発する進め方が中心でしたが、2ヶ月という期間ではそれが通用しません。要件が固まりきらないまま、開発と設計を同時に走らせました。 スピードを出すためにはAIを活用することが必須でしたが、単純に生成させるだけでは保守性の低いものができてしまいます。 そこでこだわったことが、AIの生成したコードに対する静的解析・リントなどのガードレールです。フックの仕組みを使い、AIがコードを実装するたびにガードレールが自動的に働き、指摘があればAI自身が修正するループを作ることで、人が介入しなくても一定の品質を保てるようにしました。 開発初期の1ヶ月ほどは、AIが出したコードをほぼ全て人間がレビューしていましたが、そこで挙がった指摘を静的解析やリントのルールに落とし込むことで、徐々にレビュー範囲を減らしていきました。この取り組みにより、後半は多くをAIに任せられる状態になりました。 品質を担保しながらAIに任せる範囲を広げていく仕組み作りこそが、今回の開発で最も工夫した点です。 今後、どう進化させていきたいのか 初段リリース以降は、β版利用時のお客様の声をもとに方向性を固めていく方針です。現時点で検討している方向性は、大きく3つあります。 1つ目は、応用的なメールへの対応です。自社テンプレートへの対応や、企業ごとのプロンプト追加に対応することで、これまで「ラクスの標準的な形」に合わせる必要があり対象外だったお客様も含め、より多くのお客様にこの機能を使ってもらえるようにしたいと考えています。自社のブランドガイドラインや既存の運用フローを崩さずに、AI生成のメリットを享受できる状態を目指します。 2つ目は、複数のメールコンテンツと配信セットの提案です。お客様が指定した配信内容に対して複数のメール案を作成・提案し、選ばれた案をそのまま配信セットまで組めるようにします。1通ずつ作成・配信していた業務をまとめて完結できるようにすることで、「次のメールを考える時間がない」という状況を解消し、配信頻度の維持・向上につなげたいと考えています。 3つ目は、過去のメール内容や配信結果を分析した、次に配信すべきコンテンツの自動提案です。配信結果画面と連動し、これまでの配信結果と自社の製品情報をもとに、次に配信すべきコンテンツをAIが提案し、メール作成まで行う機能を目指しています。単発のメール作成支援にとどまらず、配信結果を活かした改善サイクルを、ノウハウがなくても回せるようにすることが狙いです。 3つの方向性に共通するのは、より多くのお客様に、より少ない手間で、成果につながるメールを配信し続けてもらうという狙いです。稼働不足とノウハウ不足という2つの壁を取り除くことから始まったこの機能は、これからも進化を続けていきます。
こんにちは。ラクスのフロントエンド推進課の亀ノ上です。 Webアクセシビリティは、2022年のチームの課題棚卸しで私が挙げたテーマです。その後もR&Dの取り組みとして続けてきましたが、期日のある機能開発と並べると優先順位は後ろになり、着手には至っていませんでした。 今回、エンドユーザー向けの公開画面を持つ機能の開発で、Webアクセシビリティが要件になりました。対応を進める中で作ったのは、Webアクセシビリティを向上させる仕組みではありません。「どこが直せるのかを、プロダクトに手を入れずに知る」ためのレポート作成ツールでした。 この記事は、ツールの設計判断と、AIにどこまで任せられるのかが見えたところまでの記録です。同じようにWebアクセシビリティの向上に着手できずにいる方の判断材料になればと思います! アクセシビリティが後回しになる構造 取り組みが動き出したきっかけ プロダクトにlintを入れなかった理由 ツールの構成とAIの担当範囲 ルールの絞り込み基準 3リポジトリに回して分かった傾向 AIに改善を頼んで返ってきたコード AIが指摘を消す方向に向かう理由 次の課題はインプットの設計 今回の学びと、これから アクセシビリティが後回しになる構造 まずお伝えしたいこととして、社内で取り組みを提案してこなかったわけでも、提案が否定されたわけでもありません。工数を理由に断られるというより、やるのはいいけど機能開発が優先、となって結局稼働が取れず、未着手のままになる…というのが近い状況でした。 Webアクセシビリティは、「重要だが必須要件ではない」という位置に置かれがちです。期日のある機能開発と並べれば優先度は下がります。その判断自体は自然かもしれませんが、毎期同じ優先度となると、チームは着手しないまま次の期に入ってしまいます。 取り組みが動き出したきっかけ 要件になった機能( AI-FAQ機能 )は、エンドユーザー向けの公開画面を持っています。管理画面でコンテンツを作り、それを外部のエンドユーザーに公開します。ラクスのプロダクトの多くはバックオフィス業務を担う管理画面です。そこに、利用者を契約企業の担当者に限定しない公開画面が加わることになります。 Webアクセシビリティが要件になった理由は、どんな環境で使われるか分からない画面で、読み上げに対応していない、キーボードで操作できない、というような状態が、そのまま「使えない人がいる」ことにつながるからです。 要件になれば、最初にやることは現状の確認です。どの画面のどこが基準を満たしていないのかが分からなければ、直す範囲も、かかる工数も見積もれません。 注意すべき点として、Webアクセシビリティの確認はすべて自動チェックに任せられるわけではありません。自動チェックで検出できるのは一部で、残りは実際の画面を操作しながら確かめることになります。 自動チェックで分かる部分に関しては、プロダクトが違っても同じ調べ方が通用することがあります。今回の取り組みでは、その部分だけを切り出して、担当プロダクト専用にしない形で作りました。フロントエンド推進課としても、各プロダクトがWebアクセシビリティをどこまで満たしているのかを一覧で把握したいというニーズがあったためです。 作成するにあたって、プロダクトに導入するのではなく、シンプルに知るためのツールにしたい...そう考えました。プロダクトに組み込むのではなく、静的解析を社内で決めた基準に合わせて横断的に回せるようにすることで、他のプロダクトも現状を知る足がかりになります。 プロダクトにlintを入れなかった理由 Webアクセシビリティ関連のlintは、プロダクトのリポジトリに入れるのが素直なやり方かもしれませんが、今回はそうしませんでした。理由は2つあります。 ひとつは、エラーが出ても解消の仕方が分からず、負担になることです。lintを入れても、ルールの意味が伝わらなければ違反は残ります。 この懸念は、lintの置き場所を変えるだけでは解けません。外から回しても、理由が分からなければ同じことです。理由をどう伝えるかは、このあとに説明します。 もうひとつは、プロダクトのコードにライブラリを追加すること自体に判断が必要になる点です。どのルールを有効にするかの選定、ライブラリのアップデート対応、チームでの運用の取り決め。どれも必要な検討ですが、これを終えるまで着手できないとすると、また「機能開発が優先」となります。 そこで作ったのが、任意のディレクトリを指定して実行するとレポートが出力される、スタンドアロンのツールでした。ツールを落としてきて、パスを指定して回すだけです。プロダクトのコードには手を入れません。 lintはプロダクトに入れず、外から回す。この段階で優先したのは、着手のハードルを下げることでした。 ツールの構成とAIの担当範囲 処理は3つの段階に分かれています。AIが関わるのは②からです。 段階 やること AIの関与 ① 検出 Vue向けのアクセシビリティlint(eslint-plugin-vuejs-accessibility)で違反を洗い出す なし ② 説明 違反を一覧化し、なぜ引っかかったのかを書いたレポートに変換する あり ③ 改善 レポートを渡して、改善されたコードを出力させる あり(ここで詰まりました) lintの出力は「このルールに違反しています」までしか教えてくれません。なぜ違反なのかを知るには、ルールのドキュメントを都度見に行く必要があります。この確認の手間が、修正に取り掛かるまでの時間を延ばします。そこで、違反箇所とその理由を読めるレポートに変換する部分にAIを使いました。レポートにはサマリーと、ファイルごとの違反ルール・違反箇所が載っています。 ここまでは特に難しくありませんでした。ドキュメントを参照しながら書かせるだけだからです。 どのルールを対象にするかは、3つの条件で絞り込んでいます。 WCAG 2.2 適合レベルAの達成基準に対応する 静的解析で検出できる プロダクト固有の実装に依存しない 2つ目の条件が、このツールの守備範囲をそのまま決めています。フォーカスの移動順序が画面の見た目と合っているか、読み上げの順序として意味が通るか、操作に応じた状態の変化が支援技術に伝わるかは、Vueのテンプレートを構文解析するだけでは判定できません。実際のDOMとスタイルを解決したうえでの検査や、ブラウザでの操作確認が要る領域です。解析対象も <template> の中に限っていて、スクリプト側のロジックに起因する問題は見ていません。このツールで違反が検出されなくても、WCAG 2.2 の適合レベルAを満たしたことにはなりません。達成基準を満たせていないところの一部を静的解析で検出できる、という位置づけです。 ルールの絞り込み基準 採用・除外の判断は単純です。そのルールをWCAG 2.2 レベルAの達成基準と照らし合わせただけで、独自の重み付けはしていません。 基準に当てはめるだけでは決まらないルールが2つありました。 ひとつはラベルに関するルールです。ラベル要素で入力欄を囲む暗黙的な関連付けは、HTML仕様上は有効です。しかし、暗黙的な関連付けは、ブラウザと支援技術の組み合わせによっては対応されていない場合もあるので、明示的な関連付けをルールに入れています。 もうひとつは、フォーカスできる要素に role="presentation" が指定されていることを検出する no-role-presentation-on-focusable です。ARIAの仕様上、フォーカスできる要素では presentation の指定自体が無視されるため、指定しても効きません。こちらは、プラグインの推奨セットにも入っていないルールであることと、手動でのテストでカバーすることを理由に、初期の対象からは外しました。 3リポジトリに回して分かった傾向 現時点でツールを回したのは3つのリポジトリです。件数の集計はしていませんが、傾向は出ました。 違反が目立ったのは、プロダクト独自のUIコンポーネントでした。共通コンポーネント側で違反が少ないのは、そこがアクセシブルだからではなく、マークアップの実装がデザインシステム側にあって、このlintが見るプロダクトのテンプレートには現れないからです。デザインシステムを持っている組織なら、まずプロダクト独自のUIから見るのがよさそうです。 AIに改善を頼んで返ってきたコード レポートの出力までは問題なく動きました。 そのレポートをAIに渡して「アクセシビリティを改善して」と指示すると、lintのエラーが出なくなるコードが返ってきました。エラーは消えます。ただ、直してほしかった方向は違っていました。 具体例を2つ挙げます。いずれもVueのコードです。 例1: alt のない画像 < img : src = "logo" /> alt 属性がないため、スクリーンリーダーによってはファイル名などが読み上げられることがあります。AIが返してきたのは以下のコードです。 < img : src = "logo" alt = "" /> alt="" は「この画像は読み上げる必要がない」という意味を持つ書き方のひとつです。そのためlintは確かに通ります。 ただ、 alt に何を書くかは、その画像の用途と周りの文脈で決まります。ロゴのすぐ横に同じ内容のテキストが置かれているなら、二重に読み上げさせないために alt="" が適切な場合もあります。この例では、そうしたテキストがなく、画像だけが情報を担っているので、読み上げる必要があります。 < img : src = "logo" alt = "ラクス" /> 指摘を消すだけなら alt="" が最短です。ただそれを選ぶと、ロゴが伝えている情報は読み上げられなくなります。lintのエラーを消す方法は複数あり、どれを選ぶかで結果が変わります。 例2:クリックできる span 多かったのは、こちらのパターンです。元のコードはこうでした。 < span tabindex = "0" @click= "handleClick" > {{ text }} </ span > span はロールを持たない要素なので、支援技術に「操作できる要素」として伝わりません。キーボードイベントのリスナーもないため、EnterやSpaceで実行できない可能性があります。 AIが返してきたのは、次のコードです。 < span role = "button" tabindex = "0" @click= "handleClick" @keydown.enter.prevent= "handleClick" @keydown.space.prevent= "handleClick" > {{ text }} </ span > 指摘は消えます。ロールが付き、EnterとSpaceでも実行できるようになりました。支援技術からは操作できる状態ですが、以下のようなコードを期待していました。 < button type = "button" @click= "handleClick" > {{ text }} </ button > button を使えば、ロールもフォーカスもキーボード操作も標準で付いてきます。AIが出したコードは、 button が最初から持っているものを属性とイベントハンドラで組み立て直したものです。差が出るのは動く・動かないではなく、以後そのコードを触る人が同じ組み立てを維持できるかどうかです。 AIが提案したコードは、目視で確認して判定しています。多かったのは、セマンティックな要素を検討してほしい場面で、属性の追加で対応されてしまうパターンでした。 2つの例は性質が違います。例1では読み上げるべき情報が失われています。例2のほうは、主要な操作自体はできるようになっています。共通しているのは、lintのエラーを消す方法が複数あるなかで、元のコードを大きく変えない方法が選ばれたことです。指摘を消すことが目的になると、この選び方になるのだと思います。 AIが指摘を消す方向に向かう理由 原因は2つあると考えています。ひとつは検証のできない仮説ですが、もうひとつは今回の作りから直接たどれるものです。 仮説のほうは、AIが学習しているコードの側に原因があるのではないかと考えています。世の中にはアクセシブルではないコードが溢れていて、だからこそAIはそれらのコードをアウトプットとして出してくる。 span にロールを付けて操作できるようにしたコードは、実際のWebでも見かけます。ただ、モデルがそのコードを選んだ理由が学習データの偏りにあるのか、元のコードとの差分を小さくしようとした結果なのかは、外からは切り分けられません。 直接たどれるほうの原因は、こちらが渡している情報です。レポートに入っているのは、引っかかった箇所のコードと、その理由だけです。そのUIが何をするコンポーネントなのか、周りのコードとどう関係しているのかは入っていません。 alt の例がそのまま当てはまります。その画像がロゴなのか、本文の理解に必要な図なのか、単なる飾りなのかは、ファイル名とタグだけでは決まりません。文脈を見ないと決められない判断を、文脈なしで求めていました。代替テキストに何を書くかは、そのコンテンツを作った人が何を伝えたいかで決まります。そこはAIには判断できません。違反箇所のコードとlintの結果だけでは、その材料がありません。 これはWebアクセシビリティに限った話ではありません。静的解析の指摘をAIに直させるとき、渡しているのが「違反したルール」だけであれば、指摘を消すことが目的になります。検査が通ることと品質が上がることは別です。AIの出力がどちらに寄るかは、違反の条件だけを渡すのか、そのコードが何をするためのものかまで渡すのかで変わります。 次の課題はインプットの設計 ここから先は、まだ結果が出ていません。現時点の仮説は2つあります。 セマンティックな要素を使うことを優先させる WAI-ARIAの仕様を確認させる どちらも、属性で辻褄を合わせる方向に行かせないための指示です。ただ、指示文に書くだけで足りるのか、参照する資料まで渡す必要があるのかは、まだ検証していません。 ARIA Authoring Practices Guide(APG)のような、「このパターンはこうマークアップする」という指針が示されたガイドを参照させる案もありますが、これも着手前です。毎回ガイド全体を読ませるのは非効率なので、lintのルールに関連するAPGの箇所をリファレンスとして持たせる形も考えられそうです。 AIに任せられる範囲は、渡せる情報をどこまで設計できるかで決まります。今回の設計では、lintによる検出と、AIによる説明までは成立しました。改善まで任せようとすると、同じ情報だけでは足りませんでした。 今回の学びと、これから 今回の取り組みで得た学びのひとつは、AIによるWebアクセシビリティ向上の自動化は難しい、ということです。最終的に人間のレビューは必要で、だからこそ適切に判断できるように、Webアクセシビリティの知識をこれからもつけていきたいと考えています。 AIに任せる範囲を広げるほど、出てきたものを正しいと判断できる人が必要になります。Webアクセシビリティのように、ルールを通すことと、目的を果たすことがずれやすい領域では、その差が出やすくなります。 次は他プロダクトへの横展開ですが、その前にやることがあります。広げる前に、まず担当プロダクトのチームに展開して、誰でも対応できる運用にできるかを確かめます。ここが目の前のハードルです。 最後に、この記事の持ち帰りを4つに整理します。 Webアクセシビリティの向上に着手できていないなら、コードを直すところから始める必要はないかもしれません。まず「どこに問題がありそうかを知る」ところからなら、小さく始められます。 現状把握を始める段階なら、プロダクトにlintを組み込む判断を待たず、外から実行する方法も選べます。 デザインシステムを持っているなら、静的解析の指摘はプロダクト独自のUIに集まりやすくなります。探し始める場所の目安になるかもしれません。 検出はlintに、違反理由の説明はAIに任せられました。改善まで任せるなら、何を渡すかを設計する仕事が人間側に残ります。 直接コードの修正ができなくても、Webアクセシビリティを前に進めるアプローチはいろいろあると思います。思ったように取り組めずにいる方にとって、何かしらの参考になれば幸いです。
こんにちは。楽楽明細の開発をしている者です。 運用目線での顧客視点として、障害対応の話を書こうと思います。 障害が起きたとき、私が頭の中でどういう順番で何を判断しているのか。それを文章にしてみます。 はじめに 前提になる楽楽明細の事情 私の動き方 まず騒ぐ 何が起きているかをざっと把握する 顧客への影響を見極める 止血が要るかで動きを分ける 原因調査で意識していること そのケースがなぜ起きたかを追う 仮説を複数立ててから動く AI との分業 属人化させないために はじめに 開発の仕事は、機能を作りリリースしたら終わりではありません。ユーザーが日々何の問題もなく使用できるように安定した運用を保つところまでが開発の仕事です。 障害や不具合が起きると、程度の差はあれ、ユーザーが想定した通りに使えない時間が発生します。 システム開発においてもちろん理想は不具合を起こさないことが第一ですが、実際問題、あまり現実的ではありません。 Amazon の CTO である Werner Vogels 氏の言葉に "Everything fails all the time"(あらゆるものは、常に壊れる)というものがあります。AWS のような巨大なクラウド基盤でさえ、壊れないことを目指すのではなく、壊れても動き続けられることを前提に設計されています。 起こさない努力と同じくらい、起きたときにどう動くかが顧客への影響を左右します。この記事では、障害を起こさないための設計やテストの話はしません。起きてしまった後にどう動くと顧客の不利益を小さくできるか、という話だけを書きます。 前提になる楽楽明細の事情 動き方の前に、楽楽明細というプロダクトの性質を書いておきます。障害対応の優先度とデッドラインが、ここで決まるからです。 楽楽明細は、請求書や納品書などの帳票を発行して取引先に届けるクラウドサービスです。 Webでの公開やメール送付に加えて、郵送も扱っています。 ここで押さえておきたいのが、楽楽明細を契約しているのは帳票を発行する企業ですが、帳票を受け取るのはその先の取引先だという点です。 帳票が発行できない、届かない、という状態になると、契約企業だけでなく受取側にも影響が届きます。 受取側から見れば「請求書が来ない」「来たけど内容が違う」という出来事で、その問い合わせを受けるのは契約企業の担当者です。 一つの不具合が、契約企業の数だけでなく、その先の取引先の数に掛け算で広がっていってしまいます。 郵送の場合、時間の制約が加わります。郵送は外部の印刷・発送サービスと連携しており、その日のうちに発送するためのデータ送信には締め時刻があります。 郵送に絡む障害においては直せば済むでは終わらず、締め時刻までに直せなければ、その日の郵送が確実に遅れます。デッドラインが最初から決まっている障害対応です。 もう一つ、同じ障害でも機能によって温度感が違います。 管理画面の一覧の並び順が崩れる不具合と、帳票の生成が失敗する不具合では、対応の温度がまったく違います。 前者のような UI レベルの問題であれば、ユーザーには操作上の使いづらさなどは発生しているものの、運用が完全に停止してしまうところまではつながらないことが多く、次回リリースに載せて対応することでも大きな影響がない場合もあります。 後者の場合は、修正自体は容易だったとしても、その日のうちに直さないと運用自体が完全に停止してしまう大きなインシデントとなってしまいます。 対応の優先度は、コードの直しにくさではなく、誰にどこまで影響が届くかで決まります。 私の動き方 ここから本題です。異常に気づいてから原因調査に入るまで、私はだいたい次の順番で動いています。 まず騒ぐ 異常な状況を確認したら、原因が分かっていなくても、まず展開します。「○○の処理でエラーが出ています。原因はまだ不明です」くらいの一言で構いません。 最初にこれをやる理由は単純で、自分一人で抱えている時間が一番もったいないからです。 同じ事象を他の誰かが別の場所で見ているかもしれない。誰かが直前にリリースや設定変更をしているかもしれない。展開すればそういう情報が集まってきます。 空振りでも構いません。調べたら何でもなかった、で終わればそれでいい。「騒いだのに何もなかった」ことを気にして報告をためらう方が、後でずっと高くつきます。 何が起きているかをざっと把握する 次に事象を把握します。ここでは深追いしません。見るのは主に次の4点です。 どの機能で:エラー通知の発生元と、スタックトレースに出てくる処理の入り口 いつから:エラーログの初出時刻と、直前のリリースタイミングや本番環境での作業履歴 どのくらいの頻度で:同種エラーの件数の推移。単発か、増え続けているか どういうエラーか:例外の種類とメッセージ。データ起因か、接続などの環境起因かの当たりをつける ログとエラー通知を見て、5〜10分程度で全体像をつかむイメージです。 顧客への影響を見極める 事象がつかめたら、原因の前に影響を見ます。私が確認しているのは、次のような点です。 データは壊れないか。壊れているなら、今この瞬間も壊れ続けているか 影響は広がり続けるか。放っておくと対象のユーザーや件数が増えるか 特定の環境や条件でだけ起きているのか。全ユーザーか、特定の設定を使っている一部か この 3 点で、次に取る行動が決まります。 データが壊れ続けているなら、原因が分からなくても処理を止める判断が必要になります。 影響が広がらず、特定条件の一部ユーザーだけなら、止血よりも原因調査を急ぐ方が結果的に早く収束することもあります。 前の章で書いた温度感の話もここで効いてきます。郵送に絡む処理なら、影響範囲が小さくても締め時刻との距離を最初に見ます。 止血が要るかで動きを分ける 影響が見えたら動きを二つに分けます。 即時の止血が必要な場合 最初に考えるのは、そもそもフォールバックできないかです。 直前のリリースが怪しいなら切り戻す、新しい処理が原因なら元の処理に戻す。すでに動いていた状態に戻せるなら、それが一番速くて確実です。 フォールバックで逃げられない場合に、止血の方法を考えます。方法を決め、デッドラインを置き、妥当性を確かめる。この三つを済ませてから原因調査に入ります。 止血方法は、該当機能の一時停止、問題のあるデータの隔離、処理の手動実行への切り替えなど、状況によって変わります。 ここで大事にしているのは、止血そのものが新しい不具合を生まないか、あとで戻せるかを確認することです。急いで対応した結果、考慮不足や別の不具合につながってしまっては元も子もないからです。 デッドラインは、郵送なら締め時刻から逆算して置きます。「この時刻までに止血が終わらなければ、その日の郵送は諦めて関係部門に伝える」という線を先に引いておくと、判断がぶれません。 即時の止血が必要ない場合 暫定対処やユーザーへの案内まわりは他のメンバーに任せて、自分は原因調査に入ります。影響が限定的なら、中途半端な暫定対処を挟むより、原因を特定して正しく直す方が早いことが多いからです。 原因調査で意識していること そのケースがなぜ起きたかを追う スタックトレースを見れば、どの行で何のエラーが出たかは分かりますが、それは原因ではなく結果です。 たとえば NullPointerException が起きていた場合、null チェックを足せばエラーは消えます。 でも、なぜ null になるデータがそこに来たのかを追わないと、同じデータが別の処理で別のエラーを起こします。 データの発生源を追っていくと、行き着く先はだいたいこのあたりです。 直前の変更。リリース、設定変更、データメンテナンスなど 想定外の操作順や入力 別機能のバグで作られたデータ 特定の環境や設定でだけ成立する条件 エラーが出た理由より、そのケースが発生した理由を探さないと、同じことが当然再発します。 仮説を複数立ててから動く 事象を把握したら、調査に入る前に仮説を複数立てます。少なくとも二つ、できれば三つ。 前の節で挙げたようなパターンのうち、今回の事象はどれに当たりそうか、というところから組み立てていきます。 調査の軸がないと、ただソースやログとにらめっこしているだけの時間が発生してしまいます。 仮説を一つに絞って走り出した場合も同じで、その仮説がダメだったと確定した時点で手が止まり、次はどうしようかと考えなおす時間が発生します。状況によりますが、基本的に障害対応中は時間との戦いになるため、手を止めてしまう時間が発生するのは惜しいです。 複数仮説を立てておけば、一つダメでもすぐ次に移れる。仮説をつぶしていくことで、方向性を絞っていくこともできます。 仮説を立てたら、優先順位をつけて検証に入ります。検証で見るのは、主にエラーが発生したユーザーの操作の履歴と、実際のデータです。ログから操作の順番を組み立て、その時点のデータがどうなっていたかを見て、仮説と突き合わせる。合わなければ次の仮説へ、という繰り返しです。 AI との分業 最近の原因調査では、AIを活用している場面も増えてきています。 私がやっているのは、スタックトレースと自分が立てた仮説を Claude Code に渡して、ソースコードレベルの解析を任せるやり方です。渡すのはソースコードと例外情報の範囲までで、顧客データやログの実値は投入しません。 「この例外がこの行で出ている。仮説は A と B。それぞれの場合にコード上で何が起きるか確認してほしい」といった感じで指示を出し、呼び出し経路や条件分岐を追って、仮説ごとにコード上の裏付けを返してくれます。 その間に並行して、人間は本番のログや実データをもとに別観点で調査を進めることができます。 一方で、AI に投げる前の仮説の質は、結局こちらの責任です。仮説が的外れなら、AI は的外れな仮説をコード上で丁寧に裏付けてくれるだけです。前の節で書いた「複数の仮説を立てる」は、AI を使うようになってからむしろ重要になったと思っています。 属人化させないために 障害対応が特定の人に集まる理由は、調査スキルの差だと思われがちです。ただ、私が実際に効いていると感じているのは、対応の型が共有されているかどうかです。 障害は頻繁に起きるものではないので、経験の機会そのものが偏る。だからこそ、判断の順番を言語化して渡せるかが分かれ目になると考えています。 その順番がここまで書いてきたものです。私自身、毎回この通りに動けているわけではないですし、この通りやれば必ずうまくいくという話でもないのですが、迷ったときに立ち返る型としては役に立っていると思います。 ソースコードの解析は AI にかなり任せられるようになり、調査スキルの差を AI が埋めてくれる場面はこれからも増えていく一方で、この前段の判断は最後まで人の側に残ります。障害対応の重心はここにあると考えています。 繰り返しになってしまいますが、障害対応は起きた不具合を直すだけの仕事ではありません。楽楽明細では、影響は帳票を待つ取引先まで届きます。 その影響を見極めて、ユーザーの運用をいかに止めないか、早く再開できるようにするか。ここが一番大事なポイントです。
はじめまして。昨年新卒として株式会社ラクスに入社し、現在はHRソリューション開発部楽楽勤怠開発課でバックエンドエンジニアをしているmurosyoです。普段は楽楽勤怠の機能開発を担当しています。開発本部が掲げる 『顧客に価値を高速提供できるAIネイティブな開発組織への変革』 というビジョンのもと、ClaudeのSkillsやAgentsなどを整備・展開しています。 今回は、私がチームに導入を試みた 「Claude Codeを用いたIssueの自動解消」 の取り組みについて、構成の全貌や、実際にやってみて直面した「AIネイティブな開発ならではの壁」について、包み隠さずお話ししたいと思います。 はじめに 背景とゴール:「プログラムの不具合をいち早く修正し、お客様のユーザ体験を向上させたい」 Claude Codeを用いたIssue自動解消の全貌(実践編) フロー全体の解説と「Routines」の活用 今回の仕組みのメリット 導入で見えた「AIネイティブな開発」の壁 レビューの難しさ:コードの妥当性を測るための「深いドメイン理解」 AIとの協働をさらに進化させる:今後の展望 レビューコスト軽減への挑戦:意図を明確にするドキュメント化 Spec Driven Developmentへの拡大 おわりに はじめに 背景とゴール:「プログラムの不具合をいち早く修正し、お客様のユーザ体験を向上させたい」 自社で最も大切にしている価値観の一つが 「顧客志向」 です。お客様の業務課題を解決し、圧倒的に使いやすいサービスを提供し続けるためには、発生した不具合や細かな改善要望(Issue)に対して、いかに迅速にアプローチし、修正を届けるかが鍵となります。 しかし、日々の新規機能開発と並行してIssueを消化していくのは、どのチームにとってもリソース的に容易ではありません。「エンジニアの時間はより高度な設計やドメイン理解に使いたい。でも、目の前の不具合も一刻も早く直してユーザ体験を向上させたい」。 このジレンマを解消するためのゴールとして、 「Issueの調査からPR(Pull Request)作成までのフローをAIで半自動化し、開発効率を飛躍的に高めること」 を設定しました。 Claude Codeを用いたIssue自動解消の全貌(実践編) 試行錯誤の末、私は以下のようなフローでIssueの自動解消パイプラインを構築しました。 フロー全体の解説と「Routines」の活用 Claude Codeには、定型的なタスクを定義して実行できる「Routines」という機能があります。これを用いて、大きく2段階に分けたフローを構築しました。 ※下記に記載する内容はサンプルです。 Issueの起票 ユーザがリポジトリにIssueを起票します。 下記の内容を記載します。 発生している事象 再現手順 期待する挙動 修正対象のIssueにコード調査を依頼するラベルを付与します。 コード調査(1つ目のRoutine) コード調査の依頼が付与されているIssueを検索します。 見つかったIssueの内容を基に、Claude Codeがコードベースを検索・調査します。 ユーザへの確認事項の提示 コード調査の結果と、修正内容の実装にあたってClaudeが知りたい確認事項をIssue上にコメントとして記載します。 コード調査完了済みを示すラベルを付与します。 ユーザの回答 人間がそのコメントを確認し、確認事項に返信および修正方針が問題なければGOサインを、修正が必要ならフィードバックをIssueに返信します。 Issueに実装を依頼するラベルを付与します。 実装(2つ目のRoutine) コードの調査結果とユーザの回答結果を基に、Claude Codeが実際の実装(コードの変更)を行います。 AIレビューとテスト項目書の作成 実装後、Claude自身によるセルフレビューを実行し、さらに今回の修正に対するテスト項目書を自動作成します。 PRのDraft作成 以下の情報を記載したDraft PRを自動生成します。 実装内容のサマリー レビュー結果 テスト項目 対象のIssue番号 PRにはAIによって修正されたことがわかるラベルを付与します。 Issueには実装が完了し、PRの作成が行われたことを示すラベルを付与します。 ローカルでの動作検証と最終レビュー 最後に人間(ユーザ)が作成されたブランチをローカルに取り込み、動作検証を行ってPRをマージします。 今回の仕組みのメリット 今回の仕組みには多くのメリットがあります。 人間の稼働時間外にAIを働かせられる 例えば、夕方にIssueを起票し、夜間のうちに「コード調査」を実行しておきます。翌朝出社すると、Issueにはすでにコード調査の結果と実装方針、実装にあたっての確認事項が記載されており、人間はそれを読んで回答するだけです。これにより、日中の貴重な開発セッションのコンテキストスイッチを発生させることなく、並列で作業を進めることができるようになりました。 Issue上に全ての内容が記載されるため、Issueを確認するだけでどのような方針にしたかをいつでも振り返ることができる Issue上に当時の調査結果や修正案、修正方針がすべて残るため、後から見返したときに『どの調査結果を根拠にこの修正方針を選んだのか』を追うことができます。 ローカルPCを汚染しない 実装は全てクラウド環境(サンドボックス)で実施されているため、ローカルに余計なブランチが作成されることがなく、また、Claudeの修正がローカル環境に影響を与えるものであっても、修正内容を確認し、危険だと判断したら取り込まない選択ができるためローカルPCが汚染されません。 個人の環境に依存しないため、誰が操作しても再現性のある挙動を実現できる ローカルでIssueの調査と解消をしていたときは、実行環境が各自のPCに依存するため、ツールの起動条件や調査結果の出力内容が環境ごとに変わることがありましたが、クラウド環境(サンドボックス)で動作させることで、誰がやっても同じ環境・同じ設定で実行されるため、挙動が安定しました。 Human in the Loopを挟むことで段階的に進めることができる 最初のRoutineでコードの調査結果を基に実装方針を検討し、開発者に確認するというフローを挟むことでClaudeが勝手に設計・実装を行って、意図した内容と大きく異なる実装になってしまうということがないようになりました。 誤った実装で余計なトークンを使用しなくなったことにより、コスト的にも安価に済ませることができます。 導入で見えた「AIネイティブな開発」の壁 ここまで聞くと夢のような仕組みに思えるかもしれませんが、実際に運用してみると、想像以上に大変な課題に直面しました。 レビューの難しさ:コードの妥当性を測るための「深いドメイン理解」 最も大きな壁は、 「人間によるコードレビューの負荷」 でした。 Claude Codeが生成するコードは、文法的には正しく、テストも通るものが大半です。しかし、楽楽勤怠が持つ複雑なビジネスロジックや、特有のドメイン知識に本当に即しているかどうかは、パッと見ただけでは判断できません。 AIが「なぜこの実装アプローチをとったのか」という意図を正確に理解するためには、レビュワーである人間側が、結局のところ既存のコードベースを深く読み込み、AIの思考プロセスをリバースエンジニアリングして紐解く過程が必要になります。 この「AIの実装が本当に正しいか、コードを読んで理解する」という作業が思いのほか重く、AIによってコーディングの時間は削減されたものの、レビューの時間が長引いてしまい、結果として恩恵が一部相殺されてしまうというジレンマを感じました。 AIとの協働をさらに進化させる:今後の展望 これらの課題を踏まえ、私たちはこの仕組みをさらにブラッシュアップしていく予定です。 レビューコスト軽減への挑戦:意図を明確にするドキュメント化 レビューコストが高い問題については、「既存コードの書き方に合わせること」と「参照先や実装意図を明示すること」を、プロンプトやRoutineのルールとしてAIに徹底させるアプローチを試しています。 「〇〇のディレクトリにあるXXパターンの実装を踏襲しました」「理由は△△だからです」というサマリーがPRに明確に記載されていれば、レビュワーの認知的負荷は劇的に下がると考えています。 Spec Driven Developmentへの拡大 もう一つの展望は、この仕組みを 「Spec Driven Development(仕様駆動開発)」 に応用することです。 「仕様書(Spec)」をIssue上で管理し、合意が取れたSpecを基にAIが実装を行う。このサイクルを回すことで、ドメイン知識のズレを実装前に吸収し、より本質的な「顧客価値の最大化」にフォーカスした開発ができるのではないかと期待しています。 おわりに AIにコードを書かせることは簡単になりつつありますが、それを実運用に載せ、真に「ユーザ体験の向上」に繋げるためには、人間とAIの協働プロセスを泥臭くデザインしていく必要があります。 課題はまだまだ山積みですが、ラクスのカルチャーである「小さく試して大きく育てる」の精神で、これからもAIネイティブな開発組織への変革に挑戦していきたいと思います。 この記事が、同じようにAIツールのチーム導入を模索している皆さんの参考になれば幸いです!
前提:楽楽明細とは別のアプリとして作った 起きたこと:12機能を1本のプルリクにまとめた 原因:4層の名前までしか決めていなかった 対策:機械に判定させる範囲を広げ、人が見る範囲を絞る 実例:レビューで通せなかった箇所 次にやるなら:プルリクの切り方から変える チェックリスト:着手前に決めておく項目 編集後記:インタビューを終えて ラクス技術広報です。 開発本部では、各部署のAI活用の取り組みを技術広報がインタビューし、記事にしています。今回は電子請求書発行システム「楽楽明細」の新しいオプション機能を、AIにほぼ実装させて約2か月でリリースした事例です。 本記事は、AIを使って順調に機能開発が進んだ話だけでなく、うまくいかなかったこと・その対策をまとめています。 AIに任せる範囲を広げる前に、正しさを機械が判定できる状態を作る。 今回はこの状態を作らないまま進めました。その結果、機能ごとに実装の仕方がばらばらになり、1機能のレビューで入った指摘を他の機能に横展開できず、同じ指摘を機能の数だけ受けることになりました。 納期の都合で12機能を1本のプルリクエストにまとめたことも重なり、変更ファイルは700を超え、サーバーサイドのレビュー担当が全量を確認し終えるまでに5営業日かかっています。 新規プロダクトでAI駆動開発を始める方 AIが書いたコードのレビューが追いつかないと感じている方 に向けて、着手前に決めておく項目を記事の最後にチェックリストとして置きました。是非ご参考ください。 [図1:任せる範囲と、機械が判定できる範囲] 前提:楽楽明細とは別のアプリとして作った   楽楽明細は、請求書や支払明細などの帳票を電子発行するクラウドサービスです。帳票のもとになる売上データは、お客様が販売管理システムやExcelで管理しているものを取り込みます。 販売管理システムを使っていないお客様は、売上データをExcelで管理しています。 ・営業や拠点ごとにファイルが分かれ、どれが最新かわからなくなる ・転記のときにミスも起きる ここを解決するために作ったのが、今回の 売上登録オプション です。専用画面で売上データを入力すると、そのまま請求データとしてCSV出力できます。 仕様はプロダクトマネージャーが決めました。AI(Claude)でプロトタイプを作り、動くものをお客様に見せながら40社に話を聞いています。話を聞くうちに最小限の機能で導入いただけるとわかり、最初のプロトタイプから機能を約30%削って、CSV出力と税額計算に必要な設定に絞りました。 楽楽明細本体には手を入れず、別のアプリとして切り出しています。長く運用してきた本体にAIを入れると既存機能を壊す可能性があるため、影響範囲を限定してAIに任せる範囲を広げる判断です。 項目 内容 期間 開発決定4月7日 → リリース5月末(実質2か月未満) 体制 設計・実装は2026年1月入社の川島卓大さんがほぼ一人。 サーバーサイドとフロントエンドで各1名がレビュー。 技術 Java、Spring Boot、React、TypeScript、PostgreSQL AIの使い方 仕様の書き起こしはClaude Code、kiro(cc-sdd)でspec化してエージェントに読ませる。 実装の主軸はCodex。 git worktreeで機能ごとに作業を隔離し、複数セッションを同時に走らせる。 起きたこと:12機能を1本のプルリクにまとめた   実装に使える期間は実質1か月弱で、機能は12ありました。機能ごとにプルリクエスト(以下プルリク)を切ってレビューを待つ余裕がないため、まず全機能をつなげて動かし、そこから改善する方針を選びました。 項目 実績 変更ファイル数 700超 サーバーサイドのレビュー 機能単位で半日〜1日。 最初のプルリクを全量見切るまでに5営業日(期間で2週間弱)。 フロントエンドのレビュー 大型プルリクと、機能単位に分割された後続15件のフロント部分を合わせて2人日。 GitHub Copilotによるレビューも入れていましたが、人手で見きれる量を超えています。機能ごとに切り分けてレビューできたのは、パッケージ構成をfeature-firstで先に決めていたためです。 原因:4層の名前までしか決めていなかった   プロダクトマネージャーからの要求仕様書は、お客様の求めるものが整理された状態で渡されています。ただ、そのままAIに渡せる粒度ではなかったと川島さんは語ります。 「そのままでは渡せませんでした。特に受け入れ条件と例外系が足りませんでした。」 そこで要件を「WHEN 条件 THEN 結果」のEARS形式で1アクション単位に分解し、「IF 制約 THEN 拒否」の例外パスを正常系と並べて書いてからspecに落としました。 実装側で先に決めていたのは、feature-firstのパッケージ構成と、DDD(オニオンアーキテクチャ)の4層の名前までです。層の中で誰が何を担うのか、検証はどこでやるのか、副作用はどこに置くのかは決めていませんでした。 その状態で機能ごとに並列でエージェントを走らせると、1機能のレビューで入った指摘を他の機能に横展開できず、同じ指摘を機能の数だけ受けることになりました。 「仕様自体は要件通り作成できているものが多かったが、責務が分離できていないものが多く、レイヤー間の妥当性を見る時間が多かった。」 要求がテストできる形になっていても、実装方針が決まっていなければ、AIはそれぞれの解釈で書きます。 対策:機械に判定させる範囲を広げ、人が見る範囲を絞る   [図2:判定を3段に分ける] CIとpre-commitは最初から入れていました。ルールの書き出しとマージゲートの追加は、機能ごとに実装がばらばらになった反省から足したものです。 「一番効いているのは『できました』と言わせず証拠を出させることです。」 川島さんは、サブエージェントの「テストが通った」という報告も鵜呑みにせず、親のエージェントがdiffとテスト出力を自分で確認します。 レビューは一次をGitHub CopilotとClaude Codeのスキルで出し、人が二次で見ます。観点が複数あるときは同じエージェントに全部任せず、観点ごとにサブエージェントを分けて並列で走らせます。指摘にはmust、should、ask、imo、nitのラベルを付け、対応するかどうかを人が判断しやすくしています。 実例:レビューで通せなかった箇所   本機能にて、サーバーサイドとフロントエンドのレビューを担当した2人に「レビューで通せなかった箇所」についてお伺いしました。 領域 レビューで通せなかった箇所 サーバーサイド メール送信のように非同期で構わない処理が、トランザクションの中に入っていた。 初期のプルリクでは、メールは送信されたのにDBがロールバックされ、無効なパスワード初期化用URLがユーザーに届く実装になっていた(リリース前に修正)。 サーバーサイド 業務ロジックがユースケースやインフラの層に流れ出す責務違反。 サーバーサイド N+1が起きやすい構造。 明細行20行の売上データを取得するのに、最初はSQLが23本走っていた。 フロントエンド 方針はバックエンドで検証して送信時に表示することだったが、全画面にリアルタイムバリデーションが入っていた(全画面から削除)。 フロントエンド すでにある共通コンポーネントを使わず画面ごとに直書きし、ドラッグ・アンド・ドロップも複雑に自前実装していた(ライブラリを使う形に置き換え)。 フロントエンド テーブル内のテキストフィールドに1文字打つごとに、テーブル全体が再レンダリングされていた。 レビューを担当した2人が、共通して口にしたことがあります。 「『動く』のと『そのまま出せる』の間には距離がある」 また、これから同じ進め方を始めるチームへ、2人からのコメントです。 サーバーサイド レビュー担当者 「設計、実装の前にどうやってAIをハンドリングをしていくかという工程をちゃんと設けるべきではあった。期日までが短く急ぎ早で始めたものの手戻りも多く、事前準備をちゃんと設けていても間に合わせられていたのではと思う。 」 フロントエンド レビュー担当者 「レビューする側もAIを使っていいということ。作る速度が上がる分、見る側もAIで理解スピードを早めないとレビューが追いつかなくボトルネックになる。」 次にやるなら:プルリクの切り方から変える   [図3:プルリクの切り方] 切れ目を先に決めておけば、レビューは内側から外側へ積み上げる順に流れます。 一人でフルスタックに進めた体制では、フロントとバックエンドの間で調整が発生しないため、動くものを作る速度は出ました。一方で、一人にかかる負担は大きくなりました。API規約を先に確定させれば、フロントとバックエンドを分担できます。着手前にAIのハンドリングを詰める工程を置くことも、次の案件に向けた課題として残りました。 チェックリスト:着手前に決めておく項目   冒頭でもお伝えした通り、本取り組みから得た知見を基に着手前に決めておく項目をまとめました。 ご自身のプロジェクトに当ててみてください。 仕様と設計で決めておくこと (→ 原因の章 ) □ 受け入れ条件と例外系を、1アクション単位で書き出したか(EARS形式など) □ 各層で誰が何を担うか、検証はどこでやるか、副作用はどこに置くかを決めたか 機械に判定させる仕組み (→ 対策の章 ) □ CIで必須にする項目を並べたか(lint、format、型チェック、単体テスト、secret scanning、依存パッケージの実在チェック) □ テストを実データに近い環境で流せるか(Testcontainersなど) □ 機械では拾えない観点を、プロジェクト固有のレビュー観点として文字にしたか □ エージェントに、テスト出力とdiffを証拠として出させる運用にしたか 分割の単位 (→ 次にやるならの章 ) □ API規約(インターフェース)を、実装より先に確定させたか □ プルリクの切れ目を、レビューできる大きさで先に決めたか 最後に、川島さんからのメッセージです。 「AIに任せる範囲を広げる前に、正しさを機械が判定できる環境を先に作ることが大事だと思いました。最初の壁はコードが書けないことではなく、動いているように見えて設計方針から外れたコードが、レビューの追いつかない速度で積み上がることです。AI駆動開発で変わるのは、コードを書く仕事の比重です。良し悪しを定義し検証する仕事へ重心が移ります。ツールは半年で入れ替わりますが、この土台はどのツールに乗り換えても効き続けます。」 編集後記:インタビューを終えて   取材していて印象に残ったのは、川島さんもレビュー担当の2人も、うまくいった話より「次はこうする」を具体的に話してくれたことでした。700ファイルのプルリクは、社外に出すには気の重い話だと思います。それでも数字と経緯をそのまま出してくれたので、この記事が書けました。 開発本部では、うまくいったところとやり直したいところの両方を、これからも技術広報が聞いてご紹介していきます。
こんにちは、ラクス技術広報です。 開発本部では、各部署でのAI活用の取り組みを技術広報がインタビューし、記事としてお届けしています。今回お話を伺ったのは、楽楽請求開発部でバックエンド開発を担当する吉元和仁さんです。 楽楽請求のバックエンドチームは、昨年度の下期から仕様駆動開発(Spec-Driven Development、以下SDD)の導入を進めてきました。掲げた目標は「AIによる実装の完全自動化」です。 半年ほど回してみて、実装そのものは速くなりましたが、速くなったのは個人の作業で、チームとして再利用できる資産は積み上がっていませんでした。 この記事は成功事例の紹介ではありません。SDDを導入して4つの壁に当たり、一部のメンバーがClaude CodeのPlanモードでの開発に戻りはじめ、そこから打ち手を「SDDそのものの改善」から「SDDが回る環境の整備」へ切り替えるまでの、現在進行中の記録です。同じところで詰まっている方に、判断の材料として読んでいただければ幸いです! なぜ請求のチームが、実装の自動化を目指すのか cc-sddに加えた5つのカスタマイズ それでも残った、4つの壁 品質の再現性 レビューの肥大化 完了基準の不在 プロセスの重厚さ 「Planモードのほうが速い」という声 打ち手を「SDDの改善」から「SDDが回る環境の整備」に変えた レビュー指摘を、次に繰り返さない形に変える 出発点は「指摘がなかなか減らない」だった 生データから知識へ、知識からSKILLへ 「残す指摘」と「残さない指摘」を分けた SKILLへ昇格させる3つの条件 人間に残した仕事は「承認」と「マージ」だけ 配布はPlugin Marketplaceに乗せた 正直に言うと、まだ回しきれていない これから なぜ請求のチームが、実装の自動化を目指すのか 楽楽請求は、請求業務を効率化するクラウドサービスです。請求業務には毎月必ず締めがあり、制度改正への対応も期日が決まっています。顧客の業務が止められない以上、改善を早く届けられるかどうかがそのまま顧客への価値になります。 SDDに取り組み始めたきっかけは2つでした。社内の別チーム(楽楽明細・楽楽自動応対)で先行して成果が出ていると聞いていたこと、そして全社としてAI活用を進める方針が出ていたことです。 フレームワークにはcc-sddを選びました。その理由を吉元さんはこう説明します。 「既存の設計ドキュメントと開発プロセスを作り変えずに導入できること、そして自社の工程やレビュー観点を組み込めること。この2点を最優先に評価し、cc-sddを採用しました。」 一方のcc-sddは、既存のプロダクトコードを起点に整合性を検証する仕組みを持っています。現行のプロセスやドキュメントを大きく作り変えずに導入でき、独自の工程やレビュー観点もSKILLを追加するだけで組み込める。稼働中のサービスに、既存の開発プロセスを活かしたままSDDを入れたいという狙いに、いちばん合っていたといいます。 目標として「実装の完全自動化」を掲げたときのチームの反応を、吉元さんはこう振り返ります。 「反対意見はありませんでしたが、前のめりに聞いてくれるメンバーもいない、という状況でした」 吉元さん自身、AIの進化が伴わなければ達成は難しい目標だと認識していたそうです。それでも掲げたのは、具体的にイメージできる目標を示さなければ、チームが同じ方向を向いて動きにくいと考えたためでした。 cc-sddに加えた5つのカスタマイズ 標準構成のままでは、自社の開発プロセスに乗りませんでした。現在までに加えたカスタマイズは、大きく5つあります。 1. 設計書をレイヤーごとに分割した 標準では設計を1枚の design.md にまとめますが、これをDB設計、ドメイン設計、API設計、その他設計の4ファイルに分けました。レイヤーごとにレビュアーが異なるため、各自が担当領域だけをレビューでき、完成した設計書から順にレビュー依頼を出せます。特に影響範囲の大きいDB設計を早い段階でレビューできるようになったことが、リードタイムの短縮と手戻りコストの抑制につながりました。 2. 工程ごとにプロジェクト固有のルールを読み込ませた 標準はプロダクト概要、技術スタック、ディレクトリ構成の3ファイルのみを前提にしています。これだけでは、命名規則やマイグレーション手順といった自社の規約が設計に反映されません。そこで各工程に、DB設計規約、API設計規約、実装ガイド、テスト実装ガイド、用語集といったルール集を必ず読み込ませるステップを足しました。 3. 大きな機能を親子構成で分割できるようにした 1機能が数か月規模になるとタスクを管理しきれません。大きな機能を要件のまとまりごとに親子構成で分割できるようにして、タスク管理のしやすさと、分業によるリードタイム短縮を両立させました。 4. AI向けと人間向けで設計書を分けた design.md はAIエージェント向けの記述で、人間には読みにくいものです。しかも情報量が増えるとAIコーディングエージェントのコンテキストを圧迫し、生成物の品質が落ちます。そこで design.md はAIコーディングエージェント専用と位置づけ、人間向けにはHTML形式の設計書を別途生成する構成にしました。design.md はコンテキストを圧迫しない分量に抑える必要がありますが、人間しか読まないHTML設計書はその制約から外せます。図や表も使えるため、分量を割いて丁寧に書けます。 これは当初、詳細設計書の補助ツールという位置づけで入れたものでした。ところが開発者からのポジティブなフィードバックが多く、後述するとおり詳細設計レビューが一番のボトルネックになっていたこともあって、開発プロセス本体に組み込むことになりました。現在は詳細設計の担当者が、AIが生成した詳細設計書をレビューするタイミングで、HTML設計書を生成しています。 5. 独自スキルを追加した 仕様の分割、事前調査といった独自スキルを足していき、現在は43スキルを運用しています。 それでも残った、4つの壁 カスタマイズを重ねても、構造的に残る課題が4つありました。 品質の再現性 AIの生成物は確率的で、同じ指示でも実行のたびに違う結果が返ります。壊れているのにチェックが通ったり、通らなかったりする。 たとえばチームではAIによる自動コードレビューを導入していて、レビュー用のSKILLにコーディングルールやガイドラインを記述しています。ところがレビュー結果自体が確率的なため、1回のコードレビューですべての指摘を拾いきれない。ルールを書いたから守られる、という前提が成り立たないわけです。 レビューの肥大化 これは当初の想定と違っていた、と吉元さんは言います。レビューの総時間自体は、実は大きく変わっていませんでした。問題は別のところにありました。 AIが生成する詳細設計書には、コードの断片が埋め込まれることがあります。すると、レビュアーは詳細設計書のレビューに加えて、コードレビューまで同じタイミングで行うことになる。従来は詳細設計フェーズとコードレビュー(PR)フェーズに分かれていた作業が一箇所に集中し、レビューとフィードバックが直列につながってしまいます。結果としてリードタイムが長くなりました。 チーム内からは「これ全部見てたら、コードを見てレビューした方が早いんじゃないか」という声も出ました。 完了基準の不在 設計書の完了基準が決まっていない、という課題もありました。ここでチームは一度失敗しています。 人間による詳細設計書レビューの負担を下げようとして、「詳細設計書にコードを記述しない」「行数を500行に制限する」というルールを設けました。ところがその結果、設計判断に必要な情報が欠落したり、設計情報を聞き慣れない用語で圧縮したり、1行あたりの情報量が増えたりして、かえって認知負荷が高くなってしまったのです。 完了基準は「人がレビューしやすいか」と「AIハーネスとして機能するか」の両方から定義しないと決まりません。片方だけを見て基準を作ると、もう片方が壊れます。 プロセスの重厚さ SDDのプロセスは重いため、小規模なタスクでは個別のツールを直接叩いた方が速い場合があります。 「Planモードのほうが速い」という声 4つの課題が残るなかで、チームからは「Planモードのほうが実装は速い」という声が上がるようになりました。実際にPlanモードで開発しているメンバーもいました。 吉元さんは、これ自体を悪いこととは考えていません。個人の生産性には確かに寄与していたからです。 引っかかったのは別の点でした。 「Planモードは設計内容等のコンテキストがセッション内に閉じてしまうため、規模の大きい開発案件ではスケールしません」 個人単位では生産性が上がる一方で、その成果や進め方が組織全体に展開されず、チームとして再利用できる資産が蓄積されていかない。「組織としてのスケールメリットが得られていない」と判断した決め手はここでした。 チームが目指しているのは「実装を自動化し、人間が上流工程へシフトする」という姿です。そこから逆算すると、Planモードへの回帰による効果は限定的だと感じた、と吉元さんは振り返ります。 打ち手を「SDDの改善」から「SDDが回る環境の整備」に変えた そこで方針を切り替えます。SDDのプロセス自体をいじり続けるのをやめて、それが回るための環境を整える方向に戻る。取り組みは4つです。 取り組み やること 対応する課題 ナレッジ化 ハーネスと暗黙知を体系化し、レビュー負荷を軽減して品質を底上げする レビューの肥大化 出力の安定化 単一のAIに任せず、複数のエージェントが相互に評価し合う仕組みを整備する 品質の再現性 プロセス設計 SDDフレームワークを再定義し、タスクごとの適用基準と詳細設計基準を策定する 完了基準の不在、プロセスの重厚さ 基盤整備 ローカル依存から脱却し、AIエージェントが自律的に並列稼働できる実行基盤を作る 自動化の前提 レビュー指摘を、次に繰り返さない形に変える 出発点は「指摘がなかなか減らない」だった 背景にあったのは、暗黙知が多く、実装レビューでの指摘がなかなか減らないという問題でした。AIに実装やコードレビューを任せるうえでも、暗黙知を形式知にしてAIコーディングエージェントの品質の再現性を高める必要がありました。 取り組んだのが、PRのレビューコメントとIssueから繰り返し出ている指摘を集め、開発ガイドライン(Claude CodeのSKILL)に反映していくパイプラインです。社内リポジトリとして構築しています。 生データから知識へ、知識からSKILLへ 仕組みは3段階で、進むほど情報が絞り込まれます。 集める (fetch):PRのレビューコメント、Issue、Claude Codeのセッション情報を取得する パターン化して残す (ingest):繰り返し出ている指摘を、LLM用のWikiに蓄積する ガイドラインへ上げる (promote → 承認 → apply):条件を満たした指摘をSKILLに反映するPRを作る これを週次で回し、月次で lint をかけて点検しています。 ちなみに、「1.集める」「2.パターン化して残す」「lint」というアイデアは、 Andrej Karpathy氏が「 LLM Wiki 」と呼んでいるパターンを採用しています。 「残す指摘」と「残さない指摘」を分けた 知識層に残すのは、確定した方針やルールがある指摘だけです。却下された指摘、「後続PRで対応」と先送りされたもの、返信がないまま流れたもの、未マージPR上の指摘は残しません。判断に迷うものは、残さない側に倒します。 直した証拠も決めた方針もない指摘をページにすると、実際には守られていないルールを知識として登録してしまうからです。知識層はAIが読む前提の場所なので、守られていないルールが溜まるほど、AIの実装がチームの実態から離れていきます。 SKILLへ昇格させる3つの条件 知識層からSKILLへ上げるときの条件は次の3つです。 反復性 :同じ指摘が3回以上、かつ指摘者が2名以上 是正実績 :実際に修正コミットが発生していて、かつ2回以上 障害起因 :incident / postmortem ラベル付きIssueの再発防止策なら1回で候補 この条件を置いた理由を、吉元さんはこう語ります。 「上がってきた指摘をそのまま採用すると、内容が具体的すぎたり、個人の設計スタンスが反映されたりして、AIのコーディングルールが膨大化し、品質に影響します。複数の指摘があることで、ルール化しにくい暗黙知を抽象化できると考え、この条件を設定しました」 1人の指摘なら個人の好みかもしれない。2人以上から同じ指摘が出ているなら、チームの規範として扱える。ルールが増えすぎて誰も守らなくなる事態を、この線引きで避けようとしています。 人間に残した仕事は「承認」と「マージ」だけ 取得も、抽出も、執筆も、起票もAIが行います。人間に残したのは、承認とマージの2つだけです。 では、なぜ全自動にしなかったのか。 「AIが出力する内容が、まだ承認なしで採用できる品質には至っていないためです」 そう説明したうえで、吉元さんは「LLMの進化に期待」とも付け加えます。現時点では、AIが提案してPRを作るところまでを自動化し、直接pushや自動マージはしません。 配布はPlugin Marketplaceに乗せた 作ったスキルは、別の社内リポジトリをClaude CodeのPlugin Marketplaceとして機能させ、/plugin install で各開発者に配布しています。自動更新を有効にしておくと、セッション開始後にバックグラウンドで最新のスキルを取得し、次にClaude Codeを立ち上げた時点で反映されます。各開発者が手動で更新する必要はありません。 このリポジトリを用意したのは、AI活用の事例を個人に閉じさせず、試して改善効果が得られた内容を共有する文化を作りたかったからでした。ただし全員が共有を始めると、開発プロセスに組み込まれているものとそうでないものの区別がつきにくくなります。そこで、安定運用の tools と試験運用の labs に分けています。 正直に言うと、まだ回しきれていない ここまで紹介してきましたが、現状は道半ばです。 知識層のwikiには現在およそ700件が蓄積されています。一方、SKILLへの昇格は20件程度で、運用が十分に回っているとは言えない状態です。週1で回す設計にしているものの、そのサイクル自体をまだ回しきれていないといいます。 スキル修正提案のPRも大量に来ています。AIが投げたものと人が投げたものが混在した状態で、いまチームで手分けして選別しているところです。 工数削減については、詳細設計と実装の工程を対象に集計を始めており、段階的な削減を目標として置いています。手応えは出はじめているものの、継続して再現できるかはこれからの検証次第だと吉元さんは見ています。 他チームへの横展開にも課題があります。スキルの中にチーム固有のファイルパスやリポジトリパスが多く含まれているため、汎用的に使ってもらえる形にするにはもうひと段階のハードルがあります。 これから 基盤整備については、クラウド環境(Claude Code on the web)上での自動実装には対応済みです。ただし完全な並列実行には至っていません。実行環境の制約でビルドやテストの実行が難しいため、現状は「クラウド環境で実装してPRを作成する、CIでテストを実行する、結果を監視して修正する」という進め方を代替案として採っています。 最後に、同じところで悩んでいるエンジニアへのメッセージを吉元さんに伺いました。 「LLMの進化は速いため、それを見据えて、AI駆動開発の中長期的な戦略を立てるべきだと考えています」 目の前のプロセスを改善し続けても、半年後には前提が変わっているかもしれません。 品質の再現性、レビュー、完了基準、プロセスの重さ。楽楽請求のチームは、この4つを同時に潰す「環境」をいま整えている途中です。 開発本部では、他の部署でのAI活用の取り組みも順次記事にしてお届けしていく予定です。うまくいっていないことも含めて、また共有できればと思います。
こんにちは。『楽楽請求』でフロントエンドを担当しているtakenamiです。 『楽楽請求』では立ち上げ当初から、要件定義から画面仕様の作成までを設計チームが担い、開発チームがそれを実装するという分担で開発を進めてきました。2024年10月のリリースから約1年半が経った2026年4月、顧客への価値提供スピードをさらに高めるための部の方針として、 UI設計をフロントエンドが担う体制 へと移行しています。 実際に担ってみると、実装を担当していた頃には見えていなかった景色と、いくつもの壁にぶつかりました。この記事では、この体制に至った背景・進め方と、現時点で向き合っている課題をお伝えします。 1. 前提となる開発体制 2. なぜ踏み出す必要があったのか 設計フェーズに負荷が集中していた なぜフロントエンドだったのか プロトタイプを作るコストが下がった プロダクトのフェーズも変わってきた 3. まずは小さくUI設計を担う 立ち上げは小さく、定着は着実に Before → After 進め方 4. 担ってみて見えてきた、3つの課題 課題① 顧客・業務理解を深める 課題② UIパターンの引き出しを増やす 課題③ 設計意図を言語化する 5. 一歩踏み出した先に見えてきた、次の景色 おわりに 1. 前提となる開発体制 『楽楽請求』は、クラウド型請求書処理システム市場へ後発として参入したプロダクトです。初期フェーズでは、市場のニーズに迅速に応え、PMF(Product Market Fit)を達成することが最重要課題でした。初期メンバーによる徹底した現場視点と迅速な価値提供があったからこそ、現在の『楽楽請求』の成長につながっています。 当時の役割分担は次のとおりです。 製品企画チーム :どの機能を作るかの企画を担当 設計チーム :要件定義から概要設計まで。その一環として、FigmaでのUI設計までを担当 開発チーム(バックエンド・フロントエンド) :詳細設計・実装・テストを担当 この明確な分担は、開発効率を高めるうえで大きく機能してきました。設計チームは要件と画面仕様の検討に、開発チームは実装品質にそれぞれ集中できる。短期間で多くの機能を届けられてきたのは、この体制があったからだと思っています。 私が参画した当時、『楽楽請求』では楽楽シリーズ共通のUIの統一がすでに完了していました。統一された画面をベースにできるため、Figmaの画面仕様は設計チームが作成し、必要に応じてデザイナーに依頼する形で運用されています。 これから紹介するのは、この分担を否定する話ではありません。 共通基盤が整っているからこそ、UI設計を誰が担うのが最も速いかを、組織として問い直した 話です。 2. なぜ踏み出す必要があったのか 設計フェーズに負荷が集中していた 体制上の制約がありました。当時の設計チームは少人数で、事業部の製品企画と連携しながら、要件定義から画面仕様の作成までを一手に担っていたことです。 企画・要件・UI設計が直列でつながっているため、どれか一つが詰まれば後続がすべて待つ構造になります。開発チームは実装の準備ができていても、画面仕様が出てくるまで着手できない。顧客に価値を届けるスピードを高めるうえで、ここが構造的な制約になっていました。 問題 :要件定義からUI設計までが少人数の設計チームに集中し、設計フェーズが価値提供スピードの制約になっていた 課題 :UI設計を分担し、設計チームが要件の検討に集中できる状態をつくる その課題解決の案が、フロントエンドの役割の引き直しでした。 なぜフロントエンドだったのか 理由は大きく2つあると理解しています。 ひとつは、 UIを実際に動く形にできること です。フロントエンドがUI設計からプロトタイプ作成までを一気通貫で担えば、設計と検証の間の受け渡しがなくなります。 もうひとつは、 実装して初めて見えることがある という点です。実装フェーズに入り、実際に動く画面を触る中で、次のような気づきを得ることがありました。 この操作フローだと、ユーザーが迷う場面がありそうだ この情報配置だと、目的の項目にたどり着くまでに時間がかかりそうだ この入力体験は、もう少し工夫の余地がありそうだ ただ、その時点では開発プロセスもすでに後半で、操作体験を大きく変更することは難しい状態でした。 ここで起きているのは、誰かの検討が足りなかった、という話ではありません。Figmaの画面仕様は、情報設計やレイアウト、コンポーネントの選定といった判断を固めるうえで欠かせないものです。ただ、操作の連続性や入力のテンポといった「実際に動かしてみないと分からない情報」を、設計フェーズの時点で確かめる手段がありませんでした。 だとすれば、実装まで担うフロントエンドが設計段階から関わり、動く状態で確かめてしまえばいい。この2つが重なった結果としての体制変更だったと捉えています。 プロトタイプを作るコストが下がった もうひとつの後押しが、開発組織全体で進んでいる「AIを活用した開発スタイル」への転換です。 AIを活用することで、アイデアや仕様を素早く動くプロトタイプとして形にできるようになりました。これまでは「作ってから検証する」ことのコストが高く、現実的な選択肢になりにくかった。そのコストが下がったことで、設計フェーズで動かして確かめる進め方が、例外ではなく標準の選択肢になったと考えています。 プロダクトのフェーズも変わってきた 機能拡張は今も続いており、強化すべき領域は残っています。 一方で、ユーザーの声を聞く中で見えてきたのは、画面の見やすさ以上に、 日々大量の業務をどれだけストレスなく処理できるか という操作感そのものへの期待でした。 そのため、次のような観点で体験の質を磨き込むことの優先度が、以前より上がってきていると感じています。 直感性 :初めて触るユーザーでも迷わず操作できること 効率性 :無駄な画面遷移やステップを削ぎ落とし、大量の処理をスピーディーに行えること 信頼性 :誤操作や確認漏れを防ぎ、日々の業務で安心して使えること 3. まずは小さくUI設計を担う 立ち上げは小さく、定着は着実に 方針が決まったとはいえ、これまで実装を中心に担ってきた私たちが、いきなり全機能・全工程を引き受けるのは現実的ではありません。 そこで ラクスリーダーシッププリンシプル(RLP) の一つである「小さく試して大きく育てる」を意識し、今後リリース予定の新機能から着手することにしました。現時点で実践したのは2案件です。 小さく始めたのはあくまで立ち上げ方の話であり、単発の試行として終わらせるつもりはありません。この2案件で得た手応えと課題をもとに、今後の新機能開発の標準にしていくことを目指しています。 Before → After 体制のBefore→After 進め方 概要設計で整理された機能要件をもとに、フロントエンドがUIを設計し、実際のコードでプロトタイプまで作り込みます。画面遷移や入力操作を本物同様に試せる状態にするのがポイントです。 設計チームが概要設計(機能要件の整理) フロントエンドがUIを設計し、プロトタイプを作成 フロントエンドチーム内でレビュー 設計チームによるレビュー・仕様の確定 UIのブラッシュアップ 本実装 UI設計そのものはフロントエンドが担いますが、 仕様の確定は設計チームとの合意を経て行います 。要件の背景や事業判断を持っているのは設計チームであり、そこと接続されていないUIは成立しないためです。役割を引き取ったというより、UI設計の検討をフロントエンド側に前倒しし、二者で詰める形に変えた、という表現が近いと思います。 実際、プロトタイプを持ち込むことで、言葉や画面仕様だけではイメージを揃えにくかった操作感について、設計チームと早い段階で具体的な議論ができるようになりました。 4. 担ってみて見えてきた、3つの課題 始めて数か月が経ちました。設計フェーズの領域に踏み込んだからこそ、向き合うことになった課題が3つあります。 課題① 顧客・業務理解を深める 最も大きな壁が、ドメイン知識と業務フローの理解でした。 実装に必要な理解と、UIを設計するために必要な理解には、思っていた以上に差がありました。「ユーザーはどういう業務の文脈で、どのタイミングでその設定を変更したくなるのか」「前後の作業とどう繋がっているのか」。ここを押さえていないと、業務に馴染むUIにはなりません。 → 営業商談の録画視聴、設計チームとのディスカッション、経理業務の専門書などを通じて、インプットを継続しています。 課題② UIパターンの引き出しを増やす 顧客の業務が理解できても、それを直感的なUIへ落とし込むには別のスキルが必要でした。 情報量の多い設定画面において、「ポップアップで出すべきか、インラインで表示すべきか」「どのように視覚的なガイドを出せば迷わないか」。こうした選定を、経験則や感覚だけで判断してしまう場面がありました。 → UI/UXデザインや各種UIパターンを学び、既存画面に積み上げられてきた判断の意図を読み解きながら、選定の引き出しを増やしています。 課題③ 設計意図を言語化する 「なぜこのUIにしたのか」を言語化し、関係者に説明する力も新たなハードルでした。 プロトタイプを持ち込んでも、「使いやすそうだから」では議論になりません。「この操作フローならユーザーの思考を妨げない」「実装コストとのバランスが良い」といった理由を、ビジネス視点も含めて説明し、合意形成を図る必要があります。 → プロトタイプを軸にした早期のすり合わせを重ね、意図を説明する力を磨いています。 3つ並べて改めて思うのは、これらはいずれも、 少人数の設計チームが日常的に引き受けてきたことの一端 だということです。自分で担ってみて初めて、その難しさを実感しました。 5. 一歩踏み出した先に見えてきた、次の景色 運用面では、詰めるべき論点も残っています。プロトタイプと本実装の境界線をどこに引くか、UI仕様のドキュメントをどう管理するか。この進め方をチームの標準として定着させるうえで、避けて通れないテーマです。 そうした中で、直近では私自身が設計メンバーとして設計チームに加わることになりました。より事業や顧客に近い場所で、課題解決や設計判断に携わっていくことになります。 実装に閉じず、顧客視点でプロダクトづくりを主導できるエンジニアになる。そこに向けた、はじめの一歩だと思っています。 おわりに 今回紹介した取り組みは、正直に言えば、まだ「成功事例」と呼べる段階ではありません。課題のほうが山積みです。それでも、「より良いプロダクトを作りたい」という思いから踏み出した以上、ここから引き返すつもりはありません。 この記事が、「もっとプロダクトの意思決定に関わりたい」と考えているフロントエンドエンジニアの方にとって、何かのヒントになれば幸いです。 設計チームの一員として見えてくる景色や、そこでの気づき・失敗についても、機会を見てまたお伝えできればと思います。
目次 はじめに 前提:私たちのチームの開発の進め方 Working Backwardsに着目した理由 「機能リリース概要」という形にアレンジした 課題は、文章を書く手間 AIで上流工程を効率化する まとめ はじめに 楽楽勤怠の給与計算オプションのプロダクトマネジメント / プロダクトオーナーをしている @k0First です。 機能の仕様を決める際、事業部との認識合わせに何度もやり取りが発生したり、開発に渡した後で仕様の意図を確認されたりすることがあります。原因を振り返ると、多くの場合、最初に作成するドキュメントで伝えるべき情報が伝えきれていないことに行き着きます。 この記事では、Amazonの「Working Backwards」という考え方を参考に、自分たちの開発体制に合わせてドキュメントの作り方を見直し、AIを使って作成を効率化した取り組みを紹介します。 前提:私たちのチームの開発の進め方 会社によって開発の進め方は異なるため、先に前提を整理しておきます。 給与計算オプションでは、機能のロードマップを事前に企画課と協議して決めています。そのうえで、各機能の仕様についてはプロダクトオーナーがドキュメントを作成し、事業部と協議しながら確定させていく流れです。 デザイナーはこのドキュメントをもとにデザインを作成し、バックエンド・フロントエンドのエンジニアは、できあがったデザインとドキュメントをもとに開発を進めます。 つまり、プロダクトオーナーが最初に作成するドキュメントが、事業部との認識合わせの土台になると同時に、デザインや開発の起点にもなります。このドキュメントの内容が不十分だと、その影響は後工程にそのまま伝わることになります。 Working Backwardsに着目した理由 Working Backwardsは、Amazonが新しいサービスや機能を企画する際に用いている手法です。開発に着手する前に、その機能が完成した後を想定した顧客向けのプレスリリースをまず書き、あわせてQ&A(FAQ)をまとめます。この一式はPRFAQ(Press Release and Frequently Asked Questions)と呼ばれています。 開発企画は、放っておくと「今の仕組みや技術でできること」を起点に積み上げがちです。その積み上げ方だと、できあがってから「これは誰の、どんな課題を解決しているのか」が曖昧なまま進んでしまうことが起こり得ます。Working Backwardsは、完成後の顧客向け発表文を先に書かせることで、企画の起点を強制的に顧客の課題や体験に戻す仕組みだと理解しています。プレスリリースという体裁上、専門用語や社内事情に頼った説明ができず、平易な言葉で価値を言い切る必要がある点も、考えを整理するうえで機能しているようです。 この考え方は、私たちが抱えていた課題とも重なる部分がありました。事業部との認識合わせに時間がかかるのも、開発から仕様確認が入るのも、突き詰めると「その機能が何を解決するのか」「仕様の意図は何か」が、最初のドキュメントの時点で言い切れていないことが原因だったためです。 ただし、そのままの形式を持ち込むことはできませんでした。Amazonのプレスリリースは顧客向けの発表文であるのに対し、私たちが作成するドキュメントの読者は事業部や開発メンバーだからです。 そこで、「価値と仕様を先に言語化する」という発想だけを取り入れ、形式は自分たちの読者に合わせて作り直すことにしました。 ※Working Backwardsについては、こちらを参考にしてください。 🔗 参考リンク アマゾンの最強の働き方――Working Backwards (コリン・ブライアー、ビル・カー著) プレスリリース先行で企画を作るAmazon流のやり方【企画の道具箱 #7】 「機能リリース概要」という形にアレンジした 作成したのは、「機能リリース概要」というドキュメントです。 顧客向けのプレスリリースではなく、事業部向けのプレスリリースに近い形式にしました。前半には「どのような機能を出すのか」「その機能が顧客のどのような課題を解決するのか」を記載し、後半には事業部・開発メンバー向けに詳細な仕様を記載します。 さらに、このドキュメントを読んだ事業部や開発メンバーから想定される質問を、Q&A形式でまとめました。1機能につき1ドキュメントとして、機能概要とQ&Aをセットで扱う運用にしています。 この形式にしたことで、事業部との協議は、ゼロから説明するものではなく、すでに言語化された内容をもとに認識をすり合わせるものに変わりました。 課題は、文章を書く手間 一方で、この機能リリース概要には作成コストの課題がありました。 1機能1ドキュメントで、機能概要・詳細仕様・Q&Aまでを揃えるとなると、書く文章量は少なくありません。事業部や開発メンバーに伝わる内容にするには、言葉の選び方にも配慮が必要です。 その結果、仕様の検討そのものよりも、それを文章に落とし込む作業に時間がかかる状態になっていました。上流工程の進め方を変えても、この部分がボトルネックになっては意味がありません。 AIで上流工程を効率化する この課題に対して、次のような流れを取り入れました。 機能リリース概要のテンプレートを、あらかじめ作成しておく テンプレートに沿って、ドラフトを作成する あらかじめ定義したブラッシュアップの観点(Skill)をもとに、AIでブラッシュアップする 完成した機能リリース概要をもとに、Q&AをAIで自動作成する ポイントは、最初のドラフトは自分で書くことです。給与計算オプションは法令や計算ロジックが絡み、仕様の正確性が求められる領域のため、何を書くべきかという判断はプロダクトオーナーが担い、AIには文章を伝わりやすく整える役割を任せています。 ドラフトの作り方自体は、特別なことはしていません。テンプレートの各項目を、まず箇条書きでとりあえず埋めていきます。伝えたい内容がすでに固まっている項目については、箇条書きを飛ばして最初から文章で書いてしまうこともあります。AIに読み込ませることを意識した書き方の工夫は、特にしていません。箇条書きでも文章でも、その時点で自分が把握している情報をテンプレートの構造に沿って書き出しておく、というだけです。 ただし、入力値や出力値があらかじめ決まっている項目については、箇条書きの段階で書き切るようにしています。たとえば給与業務であれば、給与振込FBデータのように対外的に出力する項目の内容は決まっているので、ドラフトの段階で該当する値をすべて列挙しておきます。ここを曖昧にしたまま先に進めると、後工程で認識のズレが起きやすい部分だからです。構造さえテンプレートに沿っていれば、その後のブラッシュアップはSkill側の指示でカバーできるようになっています。 社内には、仕様が固まりきらない案件で、 最初からAIに書かせて書き直させるという進め方をしたチームの事例 もあります。書き直しが前提の、失敗コストが低い領域だからこそ成立する進め方だと考えています。給与計算オプションのように正確性が優先される領域では、人が骨格を作り、AIには磨きを任せる方が適していると判断しました。 ブラッシュアップについては、都度チャットで指示を出すのではなく、どのような観点で直すかをあらかじめSkillとして定義しています。「事業部が読んでもわかる粒度になっているか」「前半と後半で情報の重複や矛盾がないか」といった観点をSkill側に持たせておき、実際の作業ではGoogleドキュメントのリンクを貼り付けるだけで、その観点に沿ったブラッシュアップが行われる形にしています。毎回同じ指示を書き直す手間がなくなり、ブラッシュアップの精度も安定するようになりました。 機能リリース概要が完成した後は、その内容をもとにQ&Aの作成もAIに任せます。ドキュメントを読み込ませたうえで、事業部や開発メンバーが疑問に思いそうな点を洗い出してもらう形です。自分だけで質問を想定すると視点が偏りやすいため、この工程は特に効果を感じています。 この仕組みは、完成後の修正でも活きています。開発中に仕様変更が発生した場合、該当箇所を書き換えたうえで同じブラッシュアップのSkillを呼び出せば、テンプレートの構造や表現ルールに沿った形にすぐ整え直せます。ドキュメントの体裁を保つための調整を都度自分でやり直す必要がなく、仕様変更への対応スピードにもつながっています。 参考までに、ブラッシュアップのSkillに定義している指示の一部を抜粋します。実際にはもっと長い指示書ですが、骨子は次のようなものです。 あなたは、勤怠管理・給与計算システムの「機能リリース概要」をブラッシュアップする編集アシスタントです。 読者は、事業部(営業・カスタマーサクセス・サポート・導入支援)と開発部(バックエンド・フロントエンド・デザイナー・QA・保守運用)を想定します。 # 最重要ルール - 「機能要件(Must / Better)」は、必ず機能単位でテンプレート構造(概要・入力・出力・処理・業務ルール・エラー・備考)を維持する - テンプレート構造を独自変更したり、機能をまとめたりしない # 基本方針 - 社内仕様書として自然な敬体で記載する - 冗長な説明は避ける - 元資料の内容を尊重する - 指定範囲外を大きく変更しない - 不明点は断定しない - 読みやすさよりテンプレート準拠を優先する # 出力形式 - Markdownで出力し、Googleドキュメントに貼りやすい形にする - 「本文タブ用」「Q&Aタブ用」の順にコードブロックで出力する 読者の想定、テンプレート構造の維持、出力形式まで指示に落とし込んでおくことで、Googleドキュメントのリンクを貼るだけでも、毎回一定の品質でブラッシュアップされるようにしています。 この進め方に変えてから、ドキュメント作成にかかる時間は短くなりました。事業部との協議でも、機能の概要説明に使っていた時間を、認識のすり合わせそのものに使えるようになっています。 一方で、AIに任せられない部分もあります。何を書くべきか、どこまでを今回のスコープとするかという判断は、ドメイン知識をもとに人が行う必要があります。AIに任せるのは、内容を伝わる形に整える工程と、そこから疑問点を洗い出す工程で、判断そのものは自分たちで行う。この役割分担が、現時点では最も機能しています。 まとめ Working Backwardsをそのまま自分たちの開発に当てはめることは難しいと感じました。読者もドメインも異なるためです。 一方で、「価値と仕様を、開発に着手する前に言語化しておく」という考え方自体には、取り入れる価値がありました。形式は自分たちの読者に合わせて作り直し、「機能リリース概要」というドキュメントに落とし込みました。 そのドキュメント作成にかかる手間は、AIを活用することで軽減できました。ここでも、AIに何を任せ、何を自分たちで行うかの線引きは、扱っているドメインの特性に合わせて考える必要がありました。 Working Backwardsも、AIの活用も、そのまま取り入れるのではなく、自分たちの体制やドメインに合わせて調整していく。今回の取り組みを通じて、そのことを改めて確認できました。
はじめに LLMのAPIを叩いて何かを作ること自体は、ずいぶん手軽になりました。プロンプトを書いて実行すれば、それらしい出力が返ってきます。 ただ、「手元で動くもの」と「お客様に提供できる機能」の間には、かなりの距離があります。手元では良い感じの出力が出ていたのに、いざ幅広いデータで試すと精度が安定しない。精度は出たけれど処理が遅すぎる、あるいはコストが見合わない。本番のコードに載せ替えたら、なぜか検証時と結果が変わってしまう。このあたりで足踏みした経験のある方も多いのではないでしょうか。 そこで本記事では、LLMを使った機能開発を進める際の「何から手をつけて、どういう順番で進めるべきか」という進め方について、4つのステップに分けて整理してみます。 特定のフレームワークやサービスの使い方の話ではなく、AI機能を開発する際の「型」の話です。これから機能開発に着手する方や、一度作ってみたものの本番化で足踏みしている方の参考になれば幸いです。 はじめに 開発フローの全体像 1. 見極めと評価準備 AIで解けるタスクかの見極め 精度評価方法の構築 2. 評価と改善 現状把握と目標ラインの設定 評価結果の分析と改善策の実施 目標ラインに達するまで反復する ── そして深追いしない 3. FIXと本番実装 モデル・プロンプト・処理フローのFIX 本番実装用コードの仮作成と再検証 本番実装の完成 4. リリース後の運用と継続的改善 実データで弱点を見つけ、ベンチマークを育てる 改善はリリース前と同じ手順で適用する モデル更新とコストに追従する おわりに 開発フローの全体像 まずは全体像です。次の4ステップで進めるのが良いと考えています。 見極めと評価準備 :AIで解けるタスクかを確かめ、精度を評価する仕組みを作る 評価と改善 :目標ラインを設定し、達するまで評価と改善を繰り返す FIXと本番実装 :構成を凍結し、本番用コードに載せ替えて再検証する リリース後の運用と継続的改善 :実データで弱点を見つけ、ステップ2のサイクルに戻る 1〜3はリリースまでの一本道ですが、4だけは性質が違います。リリース後に実データを使ってステップ2の評価と改善に戻ってくる、大きなループになっています。 以降で、それぞれのステップを順に見ていきます。 1. 見極めと評価準備 AIで解けるタスクかの見極め 最初にやるべきは、解決したいタスクがそもそもAIで解けるものなのかを確認することです。前提として、そのタスクが「人間なら解決可能で、人間が解決手順を整理して説明できること」を満たしているかを考えます。人間が説明できない仕事は、AIにも任せられません。 そのうえで、利用可能な中で最も性能の良いモデルで、タスクが解決できるかを試します(動かすための最低限のコードとプロンプトは用意しておきます)。 最高性能のモデルでも解けない場合は、タスクそのものを見直します。AIに任せられそうな作業だけを切り出す、作業を細かく単純なものに分割してそれぞれをAIに解かせる、といったアプローチが有効です 解けた場合は、性能の劣るモデルでも解けるかを試して使えるモデル性能の下限を探り、予算やパフォーマンスの要求仕様に合うモデルの目星をつけておきます ※この時点では、少量のケースで「だいたい解けそうか」を人手で確認する程度で十分です。プロンプトの作り込みもまだしません。幅広いケースで解けるかどうかは、後のステップで検証します。 精度評価方法の構築 AIで解けそうだと確認できたら、より多くのデータで定量的に性能を評価する方法を用意します。必要なのは次の3つです。 ベンチマークデータ :実際に扱うことになるデータのパターンを、できるだけ網羅するように幅広く選びます 正解の回答例 :そのデータが入力されたとき、どんな出力であれば正解なのかの例を用意します スコア算出方法 :AIの出力と回答例を突き合わせてスコアを出す仕組みです。データ読取のように正解が明確に決まるタスクなら正解率/適合率/再現率、文章生成のように出力が正解と一致するとは限らないタスクなら、ベクトル化とコサイン類似度や、LLMによる一致度評価が候補になります。「XXXが書かれていること」のような基準を予め設定し、出力が基準を満たすかをLLMに判定させる方法もあり、この場合は正解例がなくても評価できます 評価の仕組みが整ったら実際にスコアを算出してみて、 そのスコアがAIの出力に対する人間の印象と一致するか を確認します。特に文章生成のようなクリエイティブ要素のあるタスクでは乖離が起こりやすく、例えば人間が「80点くらいかな」と感じる出力に評価スコアが50点しかつかないなら、評価基準が厳しすぎると考えて基準を緩めることを検討します。 2. 評価と改善 現状把握と目標ラインの設定 評価方法ができたら、まず最低限の実装の状態で評価を行い、現状を把握します。このとき精度だけでなく、処理速度、エラーの発生率、コストも併せて把握しておきます。 そのうえで、目標ラインを設定します。精度については、現状の実装の精度やタスクの難易度、モデルの性能を総合的にみた現実的な水準で、かつプロダクトとして必要とされる水準を満たすラインを引きます。処理速度やコストにも目標を設けます。精度だけを追求しても、処理速度が遅すぎる・コストが高すぎるのでは意味がありません。 ※ LLMの出力は実行のたびに変化します( temperature=0 や top_p=0.1 のように確定的になる設定にしても変動します)。同じ条件で複数回評価を実行して平均を取ると、信頼できる結果になりやすいと思います。 評価結果の分析と改善策の実施 精度が目標に届かない場合は、原因の分析から入ります。精度が低かったデータについて、正解例や正解基準と照らし合わせて、出力のどこがどのようにできていないのかを人手で確認します。より高性能なモデルなら良い品質の出力ができるのであれば、モデル性能にも一因があると言えます。複数の工程からなるタスクを1つのプロンプトで実行している場合は、プロンプトを分割して実行し、どの工程に原因があるかを切り分けます。 原因が見えてきたら、改善策を実施します。 できていなかった部分の是正案をプロンプトに盛り込み、同じ間違いを繰り返さないようにする より高性能なモデルに切り替える プロンプトを工程ごとに分割し、AIが行う1つ1つのタスクを単純化する ※ 高性能モデルへの変更やプロンプトの分割実行は、コスト増の原因になります。逆に「1つのモデルで精度が出たからOK」でもなく、より低コストのモデルで同等の性能が出せないかも確認し、コストと精度のトレードオフを常に意識することをおすすめします。 目標ラインに達するまで反復する ── そして深追いしない 改善策を実施したら再度評価を行い、効果が出ているかを確認します。効果が不十分なら分析からやり直し、目標ラインに達するまでこの評価と改善のサイクルを繰り返します。 ここで意識したいのは、 目標ラインに達したら、それ以上数字を深追いしない ことです。あらゆる入力に対して完璧な出力を返すようにモデルやプロンプトをチューニングするのは、そもそも困難です。リリース前に数字を追い込むよりも、そこそこの精度のあるものを早期にリリースし、ユーザーからのリアルなフィードバックに基づいて改善したほうが、得られる価値は大きいと思います。 3. FIXと本番実装 モデル・プロンプト・処理フローのFIX 目標に達したら、その結果を出した構成をそのまま凍結します。後の工程で精度が落ちたときに、原因が実装側にあるのか構成変更にあるのかを切り分けられるようにするためです。 固定する対象は、モデル名(できればエイリアスではなく、日付等が記載された特定のスナップショットを指定します)、推論パラメータ(temperature、top_p、max_tokens、seed など)、プロンプト全文、入出力のスキーマ、前後処理のロジックです。 併せて、FIX時点の評価スコア(以降のすべての比較の基準値になります)、その構成に至った理由と試したが不採用にした案、ベンチマークデータと評価スクリプト一式も残しておきます。評価一式は、機能の追加・修正の際に精度劣化していないかを確認する回帰テストとして、そのまま使い回します。 ※ プロンプトはコードに直書きせず、バージョン管理できる形で外出ししておくと、後の改善サイクルが回しやすくなります。 本番実装用コードの仮作成と再検証 検証用コードと本番用コードでは、求められるものが違います。検証段階では1回動けばよいコードでも、本番では失敗すること前提の作りが必要になります。具体的には、エラーハンドリングとリトライ(タイムアウトやレート制限に対する指数バックオフ)、出力フォーマットのバリデーションと崩れていた場合の再実行、規定回数失敗したときの縮退動作、入力・出力・トークン数・処理時間のログ記録、レート制限と折り合いをつけた並列化、認証情報の管理とコスト集計の仕組みなどです。 まずは作り込みすぎず、通しで動くものを仮に作ります。次にその仮の実装をステップ1で用意した評価手法で評価し、 検証時の結果が再現するか を確認します。見る観点は、精度がFIX時点のスコアと同水準か、処理速度(平均だけでなく遅い側も見ます)、並列実行時のレート制限への到達具合とエラー率、1件あたりと想定件数での月次コスト、異常系の入力(空、極端に長い、想定外の文字種)で落ちずに処理できるか、です。 ※ 検証時と本番では、プロンプトへのデータの入り方(エスケープ、改行の扱い、文字数上限による切り詰め)が変わりやすく、これが精度劣化の典型的な原因になります。精度が再現しない場合は、モデルやプロンプトを疑う前に、まず実装の差分を潰します。 本番実装の完成 再検証で見つかった問題を修正し、運用に耐える状態に仕上げます。このとき、機能として動くことに加えて、 リリース後に改善サイクルを回せる状態になっていること が完成条件になります。 監視とアラート :エラー率、処理時間、コストの急増を検知できるようにする 入出力ログの蓄積 :どの入力で品質が悪かったかを後から追跡し、ベンチマークデータに追加できるようにする ユーザーからのフィードバック導線 :出力に対する評価や修正内容を回収できるようにする 安全面の対処 :個人情報のマスキング、プロンプトインジェクションへの対策、出力をそのまま外部に出す場合のフィルタ 段階的リリースの仕組みと運用手順の文書化 :一部ユーザーへの先行公開や問題時に切り戻せる導線、障害時の対応やモデル更新時の再評価手順 ステップ2の最後に書いたとおり、リリース前に完璧を目指すよりも、そこそこの精度で早く出してユーザーの反応をもとに改善するほうが価値があります。そのための「早く出せる仕組み」と「改善を回せる仕組み」を、この工程で用意しておくイメージです。 4. リリース後の運用と継続的改善 リリースは検証の終わりではなく、実データでの検証の始まりです。 開発中のベンチマークデータは、あくまで自分たちが想定した入力パターンの集合でしかありません。実際のユーザーが入れてくるデータは想定を外れることが多く、リリース後に初めて分かる弱点があります。ステップ3で用意したログとフィードバック導線を使って、ステップ2の評価と改善のサイクルを本番データで回し続けます。 実データで弱点を見つけ、ベンチマークを育てる まず、精度が低かったケース(ユーザーがやり直した、大幅に手直しした、フィードバックで低評価がついた入力)や、開発時のベンチマークに無かった想定外の入力パターンを、実データから拾い上げます。「精度が悪い」という報告だけでは改善できません。 どの入力に対して、どんな出力が返り、期待されていた出力は何だったのか 。この3点が揃う形で、ログとフィードバックを回収できるようにしておきます。 見つかった失敗ケースはベンチマークデータに追加し、評価セットを育てていきます。追加直後はスコアが下がりますが、これは評価が実態に近づいたということです。再評価の際は追加分だけでなく既存分も必ず一緒に評価します。特定ケースの対策で他が壊れる(デグレする)ことは頻繁に起こります。 ※ ベンチマークデータが実データを反映して充実していくほど、評価の信頼性が上がり、改善のスピードも上がります。ここへの投資が、長期的には一番効いてくると感じています。 改善はリリース前と同じ手順で適用する プロンプトを修正したら、リリース前と同じ回帰テストを通してから反映します。変更は一度にまとめず効果を切り分けられる単位で入れ、可能なら一部ユーザーで先に試してから全体に広げ、変更内容と前後のスコアを記録に残します。プロンプトの修正は1行の変更でも挙動が大きく変わるため、コード変更と同じ扱いで、レビューとテストを経て反映する運用にしておくのがよいと思います。 モデル更新とコストに追従する LLMは提供側の都合でモデルが更新・提供終了されるため、追従は避けられないものとして手順化しておきます。新モデルが出たら、既存のベンチマークで旧モデルと精度・速度・コストを比較評価します。上位モデルだけでなく、より低コストのモデルで同等の精度が出ないかも都度確認します。モデルの価格性能比は継続的に改善されているため、リリース時点の最適解が半年後も最適とは限りません。使用中モデルの提供終了期限を把握し、期限前に移行検証の時間を確保しておくことも必要です。 ※ モデルを差し替えると、旧モデル向けにチューニングしたプロンプトが最適でなくなることがあります。モデル変更時は、プロンプトの見直しもセットで考えます。 コストについても、実際の利用量に基づく月次コストを定点観測し、想定より高い場合はプロンプトの短縮、キャッシュの活用、モデルのダウングレード、処理の分割方法の見直しなどを検討します。 おわりに 4つのステップを並べてきましたが、通してみると、特別なことは何もしていません。「目標を決め、評価し、改善する」という当たり前のサイクルを、AI機能開発の文脈に置き直しただけとも言えます。 しかしLLMを使った開発では、この当たり前が思いのほか難しいこともあります。 出力が実行のたびに変わるため「(一時的な)良くなった気がする」で判断しがちですし、手元では動いてしまうぶん、評価の仕組みを作る前に作り込みを始めてしまいがちです。だからこそ、 作り込む前に評価する仕組みを用意しておくこと が、堅実に開発を進めるために重要になってきます。 もう1つの難しさは、やめ時が分かりにくいことです。あらゆる入力に対して完璧な出力を返すようにチューニングすることは、そもそもできません。一方で、リリースすればユーザーのフィードバックという社内の検証では得られない貴重なデータを得られます。完璧を目指して社内で磨き続けるより、 目標に達したら深追いせず早く出し 、ユーザーのフィードバックに応えていくほうが、結果的に良いものになるはずです。 これから機能開発に着手する方や、本番化の手前で足踏みしている方にとって、進め方を考えるきっかけになれば幸いです。
【目次】 AIが入っていない場所を探したら、上流工程が残った なぜ「概要設計書」を選んだのか 「書き直させる」前提で、最初からAIに書かせた つまずいたのは、スライドのデザインとUIのデザインの混在 ツール選定に、20分以上かけない 体感で2〜4倍。ただし数値化はこれから 生まれたバッファは、顧客の声を拾う時間へ まとめ こんにちは、ラクス技術広報です。 開発本部では、各部署でのAI活用の取り組みを技術広報がインタビューし、記事としてお届けしています。今回お話を伺ったのは、経費・請求・販売管理などのクラウドサービスを展開するラクスで、販売管理クラウドサービス「楽楽販売」の開発を担う 楽楽販売開発1課の前田啓佑さん です。 前田さんが取り組んでいたのは、コーディングでもテストでもありません。 「概要設計書をAIに書かせる」 ——つまり、開発の上流工程そのものでした。 「AIでコーディングを行い、テストを行うのは当たり前になりつつある。じゃあ今、AIの導入が遅れている場所はどこか。そう考えていくと、上流工程が残るんです」 この記事はこのような方におすすめです。 コーディングやテストのAI活用は進んだが、その先の伸びしろが見えなくなっている方 仕様が固まりきらない案件で、設計ドキュメントの書き直しに疲弊している方 AIツールの選定・比較検討に時間をかけすぎていると感じている方 速くすること自体が目的ではありません。空いた時間を何に使うのか?ぜひ考えるきっかけになると幸いです。 AIが入っていない場所を探したら、上流工程が残った 前田さんが所属する楽楽販売の開発チームでも、コーディングやテストコード生成でのAI活用はすでに日常の一部になっています。 課題として浮かび上がったのは、 開発プロセス全体で見たときのボトルネックの位置 でした。 「上流工程が遅延すると、結局、開発タスクが下に降りてこないんですよ。下流だけをどれだけ速くしても、そこは詰まったままになる。ボトルネックは上流工程にあると感じました」 コーディングが2倍速くなっても、その前段の設計に時間がかかっていれば、リードタイム全体はほとんど変わりません。AIが入っていない場所こそ、一番効きやすい場所だった、ということです。 ここが今回の取り組みの出発点になりました。 なぜ「概要設計書」を選んだのか 上流工程といっても範囲は広い。その中で前田さんが最初の対象に選んだのが、概要設計書でした。楽楽販売の概要設計書には、少し特殊な事情があります。 「楽楽販売の概要設計書は、事業部向けの説明資料も兼ねているんです。なので、普段はGoogleスライドで作成しています」 読み手が開発者だけではないため、ドキュメントには内容の正しさに加えて「説明資料としての体裁」が求められます。テキストベースの設計書に比べて、作成にも修正にも手間がかかりやすい構造です。 そして、今回対象にした案件は、 顧客の声から生まれた案件 でした。 顧客起点で始まった案件には、ひとつの特徴があります。解決すべき課題ははっきりしている一方で、それを どういう外部仕様で実現するかは、始まった時点では固まっていない ということです。 「具体的な外部仕様はハッキリとはしておらず、概要設計を何度も書き直すことになるのは明白でした」 書き直しは「起きるかもしれない」ではなく「明白だった」。この見通しが、次の判断につながります。 「書き直させる」前提で、最初からAIに書かせた 普通の順序であれば、まず人間が叩き台を作り、AIには補助的に手伝ってもらう、という発想になりそうなところです。前田さんは、その逆でした。 「最初からAIを使って書き、AIを使って書き直させる。そういう固い意思で概要設計を作り始めました」 使ったのは、Anthropicが2026年4月に公開した「 Claude Design 」です。テキストでの指示や対話を通じて、スライド資料やプロトタイプ、LPなどを作成できるツールで、執筆時点ではリサーチプレビューとして提供されています。前田さんはこれを使って、設計書のスライドそのものを生成しました。 前田さんの言葉で印象的だったのは、 「思いの外、精度が高いものが作れることに驚いた」 という点です。当初から成功を確信していたわけではなく、書き直し前提だからこそ試せた、という順序でした。 さらに効果が大きかったのは、修正フェーズだったといいます。 「『こういう修正をお願い』と言うと、全部のページに目を通して、修正すべき箇所を洗い出して修正してくれるんです。漏れなくやってくれる」 これは、スライド形式の設計書につきまとう典型的な問題に効いています。ページ数が増えるほど、一箇所の仕様変更が他ページに波及していることを見落としやすくなる。 「人間がやると、矛盾した記載が残ったりします。この辺はAIの方が優秀でした」 「速く書ける」だけでなく、 「書き直しても整合性が壊れない」 こと。書き直しが前提の案件においては、こちらの価値のほうが大きかったと言えそうです。 つまずいたのは、スライドのデザインとUIのデザインの混在 もちろん、すべてがうまくいったわけではありません。前田さんが最も苦労したポイントは、 スライドのデザインと、画面UIのデザインが、AIの中で混ざってしまう ということでした。 概要設計書では、新機能の画面イメージを説明する必要があります。つまり1枚のスライドの中に、 資料としてのレイアウト(見出し、余白、図解の配置) 説明対象であるプロダクトのUIデザイン という、性質の異なる2種類のデザイン情報が同居することになります。AIから見ると、この2つは区別しづらい。 結果として、UIの説明図がスライドの装飾に引きずられたり、その逆が起きたりします。 前田さんが出した結論は、 分業させる ことでした。 「UIのデザイン案は、別で作らせた方が早くて綺麗なものができそうです」 ただし、前田さんはこれを「常に分けるべき」とは言いません。 「ただ、まだまだ修正が入るフェーズなら、叩き台としてこれで良い、と妥協するのも必要だと思います。効率を考えて使い分けるべきですね」 ここは、AI活用の実務でかなり効く判断だと感じました。 「AIの出力品質をどこまで上げるか」ではなく「今このフェーズで、どこまで上げる必要があるか」から逆算する。 仕様が動く前提の段階で見た目を磨き込んでも、その労力の多くは次の書き直しで消えてしまいます。 ツール選定に、20分以上かけない 「なぜこの方法を選んだのか。他の選択肢と比較検討はしましたか?」 この質問への答えが、今回のインタビューで印象に残った部分でした。 「正直、こだわりはなかったです」 比較検討をしなかった、という話ではありません。前田さんが問題視していたのは、 比較検討そのものにかかる時間 でした。 「今はどんどん新しいツールが出るし、料金プランの変更も1ヶ月単位で発生し続けています。悩んでいる時間が、開発速度を鈍化させる」 半年かけて選定した最適解が、選び終わった頃には最適ではなくなっている。変化の速度が意思決定の速度を上回っている領域では、慎重な比較検討がそのままコストになる、という指摘です。 「闇雲にやれば良いとは言いません。ただ、例えば20分調べて良さそうなツールを見繕って、その中から自分が良いと思うものを選んで、実際にトライアンドエラーを始める。その方が効率的じゃないかと思います。今のラクスに求められているスピードは、そういうことだと思っています」 ラクスの行動指針には「小さく試して大きく育てる」という項目がありますが、この判断はまさにそれを地でいくものだと感じました。 机上で最適解を探すより、手を動かして得られる情報のほうが速くて確かだ という割り切りです。 なお、これは「検討を放棄してよい」という話ではないはずです。今回のケースでは、書き直し前提のドキュメント作成という 失敗コストの低い領域 から始めているという前提があります。試す場所の選び方とセットで受け取るのが実態に近そうです。 体感で2〜4倍。ただし数値化はこれから では、実際どれくらい速くなったのか。 「まだ概要設計は完了していませんが、速度も品質も段違いであることは明らかです。体感ですが、2倍〜4倍は早く仕上がります。数値化できていなくて申し訳ないですが……」 ここは、記事としてもそのまま正直に書いておきたい部分です。 現時点で計測された数値ではなく、進行中の案件における作業者本人の体感値 です。今後、案件が完了した段階で改めて振り返る余地が残っています。 一方で、前田さんが強調していたのは倍率そのものよりも、その手前にある事実でした。 「これまでAIが入っていなかった場所にAIが導入されるというのは、測れないくらいに改善効果が大きいと再確認しました」 すでにAIが入っているところをさらに磨いても、上がり幅はだんだん小さくなっていきます。一方で、ゼロだったところに入れたときの差は桁が違います。 伸びしろは、まだAIを使っていない場所にある。 これが今回の取り組みから得られた、最も再現性の高い学びだと感じました。 生まれたバッファは、顧客の声を拾う時間へ 最後に、他チームにも共有したいことを尋ねました。 「AIの進化で開発の現場が劇的に変化している昨今ですが、我々が求められている開発速度はこんなもんじゃない、と思っています。固定概念に囚われずに、もっと遥か高みを目指してほしいです」 そのために日々持ち続けたい問いとして、前田さんは2つを挙げてくれました。 手でやっている作業は、AIで代えられないか? そもそも、やる意味がある作業か? 後者が併記されているのが重要なところだと思います。AIで速くすることと、そもそもやめることは、別の打ち手です。前者だけを追いかけると、不要な作業を高速に生産し続けることになりかねません。速くした先に何を置くかも、はっきりしていました。 「無駄を省くことで生まれたバッファーは、顧客の声を拾う時間などに有効活用して、より良い、求められるものを作り出していきたいです」 今回の取り組みの対象になった案件そのものが、顧客の声から生まれたものでした。 顧客の声を聞く → 作る → その時間を捻出するために速くする → さらに顧客の声を聞く。 AI活用を、開発効率の話で終わらせず、顧客志向のサイクルを回す原資として位置づける。ここに、ラクスの開発組織がAIに向き合う理由が表れているように感じます。 まとめ 今回の取り組みから持ち帰れるポイントを、3つに整理します。 AI活用の伸びしろは、まだAIが入っていない工程にある。 導入済みのところを磨くより、AIが入っていない場所を探すほうが伸びしろは大きい 書き直しが確定している成果物は、AIとの相性が良い。 速さだけでなく「修正しても整合性が壊れない」ことの価値が効いてくる フェーズに応じて、品質の妥協ラインを決める。 仕様が動く段階で作り込んでも、その労力は次の書き直しで消える ラクスの開発本部では、「顧客に価値を高速提供できるAIネイティブな開発組織へ」という方針のもと、こうした現場発の試行錯誤を各チームで進めています。今回のように、まだAIが入っていない領域に踏み込む取り組みも、これから増えていくはずです。 最後までお読みいただきありがとうございました!
こんにちは。2026年4月にラクスに入社し、楽楽精算開発部に配属された木村です。 この記事では、入社してから実務に入るまでの約4ヶ月間に受けた研修の内容と、配属後の研修中に学んだことを書きます。ラクスのエンジニア職に興味がある方のご参考になれば幸いです。 研修の内容は年次によって変わる可能性があるため、ご注意ください。 なぜラクスを選んだか 入社から実務に入るまでの流れ 新入社員合同研修 技術研修 配属後研修(楽楽精算) 配属後研修で得た気付き おわりに なぜラクスを選んだか ラクスを選んだ理由の1つは、若手にも挑戦の機会がある環境だと判断したからです。 就職活動では、若手にも挑戦の機会があるかを重視していました。やったことのない仕事に挑戦することで、できることを増やしていきたいと考えていました。選考の際、面接の逆質問を通して若手の挑戦機会について直接確認できたことが、入社を決める後押しとなりました。 入社後に社員の方とお話しする中で、実際に成果を出した若手が新しい役割やプロジェクトを任された事例を本人や周囲の方からお聞きしました。年次に関係なく成果を出していれば挑戦の機会を与えてもらえる環境なのだと改めて実感しました。 入社から実務に入るまでの流れ 入社から実務に入るまでのスケジュールは以下の通りです。 期間 内容 4/1 - 4/10 新入社員合同研修 4/13 - 6/30 技術研修 7/1 - 9/11 配属後研修 配属後研修の期間は目安です。配属時の経験や知識によって、研修期間は前後します。 以降でそれぞれの研修について説明していきます。 新入社員合同研修 ビジネスマナーなど社会人としての基礎に加え、就業規則や人事制度といった社内の制度、クラウドサービスのビジネスモデルや各プロダクトについて学びます。 今年は生成 AI 活用研修がありました。生成 AI の特徴と社内で利用できる AI の説明から始まり、 Gemini とNotebookLM(現Gemini Notebook)のハンズオンがありました。最後に Gemini の Canvas 機能を使ってアプリを作るハッカソンがありました。Gemini は学生のときから使っていましたが、Canvas 機能でアプリを作れることまでは知りませんでした。 技術研修 約2ヶ月半、エンジニア職の新卒全員で受ける研修です。Webアプリケーションの設計から運用保守までの一連の開発プロセスを実践できるようになることを目指した内容になっています。具体的な学習内容は以下の通りです。 カテゴリ 内容 IT基礎 ハードウェア基礎、ネットワーク基礎 Java プログラミング入門、Collection API、ラムダ式、Stream API、例外処理 オブジェクト指向 クラス、継承、委譲、カプセル化、インターフェース、ポリモーフィズム、SOLID 原則 データベース RDBMS、SQL、JDBC、Entity と DAO パターン Webフレームワーク Spring Boot、Thymeleaf、DI コンテナ、Spring JDBC フロントエンド HTML/CSS、JavaScript、jQuery、Ajax による非同期処理、React テスト ソフトウェアテスト入門、JUnit、TDD バージョン管理 Git AI駆動開発 プロンプト、Design Doc、ADR セキュリティ SQL インジェクション、XSS 運用保守 パフォーマンスチューニング、ロギング インフラ Linux、シェルスクリプト、Docker、Apache & Tomcat 連携、デプロイ AI 駆動開発は今年から追加された内容です。Claude Code のようなコーディングエージェントを使う研修ではなく、コンテキストエンジニアリングの講義でした。仕様と意図を Design Doc、ADR、Javadoc として書き出し、それらをプロンプトとともに Gemini へ渡してコードを生成させるという内容でした。実装しながら設計や仕様を固めていくスタイルに慣れていたので、先に仕様を文書化してから生成させる進め方には苦戦しました。AI を使いこなすためには、開発スタイルを変えていく必要があると感じました。 これらの学習と並行して、朝の時間に技術発表か小テストがありました。技術発表とは、担当者が特定のテーマについて勉強したことを発表する取り組みです。1周目は『リーダブルコード』、2周目は技術や用語の説明でした。 研修の最後にはチームで EC サイトを開発しました。商材はいくつか用意されていましたが、今年は全チームが独自の商材を扱う EC サイトを開発しました。私たちのチームは編み物のキットを商材に選びました。ただ、チームに編み物の経験者がいなかったため、機能のアイデアは出せるものの、それが実際に使われるものなのか判断できませんでした。そこで、編み物の経験がある同期や、編み物の専門店で働いている方にインタビューを行い、曲がりなりにも根拠を持って仕様を決めていくことができました。 これは実際のプロダクト開発でも同じではないかと思います。顧客への解像度が低いまま作った機能は価値として届きません。根拠がないまま議論を続けても結論は出ず、リリースも遅れます。ラクスが顧客志向を重要視する理由が少し分かりました。 配属後研修(楽楽精算) 楽楽精算の開発に必要な技術やドメイン知識を学ぶ研修です。主に以下のことを学びます。 楽楽精算の機能 楽楽精算で利用されている技術 楽楽精算のシステム構成 最後に楽楽精算に機能を追加する課題に取り組みます。学習メニューの詳細は2022年の記事でも紹介されているので、こちらをご覧ください。 tech-blog.rakus.co.jp 変わった点としては、資格の取得が任意になったこと、サポートサイト課題の負担が減ったことがあります。楽楽精算のサポートサイトには「フムフム」という AI チャットボットが導入されています。以前はサポートサイトのほぼ全ページを読む必要があったようですが、チャットボットのおかげで知りたい情報をピンポイントで入手できるようになりました。 配属後研修で得た気付き ここでは、楽楽精算に機能を追加する課題で学んだことを書きます。 同期のプルリクエストに LGTM(Looks Good To Me)を返した後、メンターの方から以下のようなコメントを頂きました。 “ LGTMと判断したレビュー観点をリストアップして貰えますか? ” 1行消して1行足すだけのプルリクエストだから、そんなに時間はかからないだろうと思い、レビューの観点を書き出すと、思いの外、手が止まりました。同期が書いた値の意味は理解していましたが、なぜその値にするのかまで説明できませんでした。その値がどこでどう使われているのかを調べ直すことになり、返信までに20分以上かかりました。 自分も同じ課題をやったはずなのに、なぜ理由を説明できなかったのか。自分なりに考えた結果、実装時に自ら判断する機会を作らなかったからだという結論に至りました。 自分で実装する場合、何を書くかを自分で選ぶ必要があります。選ぶ以上、なぜその値にしたのかという理由が自分の中に残ります。一方、AI に実装を任せると、すでに選ばれた状態のコードが出てきます。出力を読んで確認はしますが、なぜ他ではなくその値なのかを考えなくても先に進めてしまいます。今回の課題でも、なぜその値にするのかまで踏み込めていなかったため、理由を説明できませんでした。 AI を活用するのが当たり前となった現代において、すべてを自分で実装するのは現実的ではありません。AI に実装させる前提で、なぜその実装にしたのか自分で判断する機会を意図的に設ける必要があることを学びました。 おわりに 約4ヶ月の研修を通じて、技術面はもちろん、プロダクト開発における顧客志向の重要性や、AI を活用した実装において自ら判断を下す必要性など、実務に通じる気付きを得ることができました。 判断する機会の必要性について、現時点で明確な解決策を持っているわけではありません。これから実務が始まるので、日々の業務の中で試行錯誤しながら、実装の理由を見失わない進め方を見つけていきたいです。 この記事が、ラクスのエンジニア職に興味がある方のご参考になれば幸いです。