はじめに
プロダクトに AI を組み込むとき、「AI にすべてを任せる」のは正しいアプローチではないと考えています。
私が開発しているフリーランス向け依頼管理ツール Wakulier に AI 支援機能を追加したとき、目指したのは「AI がユーザーの代わりに考える」ではなく、「AI がユーザーの思考を補助する」機能でした。具体的には、クライアントからの依頼内容を AI が解析し、見積もり前に確認すべき項目を提案する機能です。
一見シンプルに聞こえるかもしれません。しかし、実装してみると「AI に何をどう聞かせるか」というプロンプト設計に最も時間がかかりました。この記事では、Gemini API を使った AI 支援機能の実装で経験した3段階のプロンプト設計の試行錯誤と、実運用を見据えたフォールバック処理やレスポンス検証のパターンを共有します。
なぜ「確認リクエスト」を AI で支援するのか
Wakulier はフリーランスがクライアントからの仕事の依頼を管理するツールです。依頼が届いたら、内容を確認して見積もりを出し、作業に着手する。その流れの中で、最も手戻りが発生しやすいのが「見積もり前の認識合わせ」のフェーズです。
クライアントからの依頼は、しばしば曖昧です。「いつものやつお願いします」「前と同じ感じで」「ロゴを作ってほしい」。こうした依頼をそのまま受けて見積もりを出すと、後から「思っていたのと違う」となりかねません。
2026年1月28日の開発日記にはこう書いています:
AI支援確認リクエスト: 見積り前の認識合わせで手戻りを防止するため。クライアントからの依頼は曖昧なことが多く、「何がわからないか」を整理する手間がかかる。AIに解析させて確認項目を提案
PM として考えたのは、「確認すべきことは経験豊富なフリーランスなら直感的にわかるが、経験が浅い人はそれが難しい」ということでした。そこを AI で補助すれば、経験値に関係なく適切な確認ができるようになるはずだ、と。
この機能を Phase 6 として位置づけ、Phase 6.1 で AI 解析基盤(Gemini API クライアントとプロンプト設計)、Phase 6.2 で確認リクエスト機能(DB 設計、API、UI)を実装しました。
プロンプト設計の3段階の試行錯誤
AI 支援機能の開発で最も時間をかけたのが、プロンプト設計です。「何を聞くか」ではなく「どう聞くか」で AI の出力品質が大きく変わることを実感しました。
ここからは、3回の試行錯誤を追体験していただきたいと思います。
第1段階:「確認項目を列挙して」
最初のアプローチは素朴なものでした。依頼内容を Gemini API に渡し、「この依頼について確認すべき項目を列挙してください」と指示する。これだけです。
開発日記にはこう記録しています:
最初は「確認すべき項目を列挙して」だけ → 的外れな質問が多い
「的外れ」というのは、たとえば「ロゴデザインの依頼」に対して「プロジェクトのスケジュールは?」「チームの規模は?」「予算の上限は?」のような、一般的なプロジェクト管理の質問が並んでしまうということです。
間違ってはいないかもしれません。しかし、フリーランスがクライアントに送る確認リクエストとしてはピントがずれている。「このロゴをどこで使うのか」「カラーの指定はあるか」「データ形式は AI か PSD か」といった、作業内容に踏み込んだ質問が欲しいのです。
AI は与えられた情報から最も「それらしい」回答を生成しますが、文脈が足りないと一般論に落ちてしまう。これが最初の学びでした。
第2段階:「サービス提供者の視点で」
第1段階の反省を踏まえ、プロンプトに「サービス提供者の視点で」という指示を加えました。「あなたはフリーランスのサービス提供者です。クライアントから以下の依頼を受けました。見積もりを出す前に確認すべき項目を挙げてください」という形です。
あなたはフリーランスのサービス提供者です。
クライアントから以下の依頼を受けました。
見積もりを出す前に確認すべき項目を挙げてください。
依頼内容: {依頼テキスト}
改善はありました。「予算は?」のような漠然とした質問は減り、依頼内容に関連した質問が増えた。しかし、まだ「一般的すぎる」という問題が残っていました。
たとえばロゴデザインの依頼に対して「色の希望はありますか?」「サイズはどれくらいですか?」「納期はいつですか?」のような質問が並ぶ。これでは「視点」は合っていても「粒度」が足りていません。実際にフリーランスが確認したいのは、もっと具体的な項目です。
第3段階:具体的なカテゴリ指定
3回目の改善で大きく結果が変わりました。「何を確認すべきか」の方向性を、具体的なカテゴリとして指定したのです。
開発日記の記録:
具体的なカテゴリ(納品形式、範囲、技術要件など)を指定 → 実用的な結果に
プロンプトに「以下のカテゴリに沿って確認項目を提案してください」と加え、カテゴリとして「納品形式」「作業範囲」「技術要件」「修正回数・対応範囲」「素材の提供」などを列挙しました。
以下のカテゴリに沿って確認項目を提案してください:
- 納品形式(ファイル形式、解像度、データ形式)
- 作業範囲(含まれるもの、含まれないもの)
- 技術要件(使用ツール、対応環境)
- 修正回数・対応範囲
- 素材の提供(クライアントから提供されるもの)
すると、ロゴデザインの依頼に対して「AI/EPS/PNG のどの形式で納品しますか?」「Web 用とプリント用の両方が必要ですか?」「ラフ案の提出は何案ですか?」のように、フリーランスが実際に確認したい具体的な項目が出てくるようになりました。
この経験から得た教訓は明確です。AI に「考えて」と丸投げするのではなく、「この観点で考えて」と枠組みを示す。これだけで出力品質が劇的に変わります。AI タグ付けの記事でも書きましたが、AI プロンプト設計の要諦は「自由度を適切に制約する」ことにあると改めて感じました。
最終的なプロンプト構造
3段階の試行錯誤を経て、最終的に採用したプロンプトはシステムプロンプトとユーザープロンプトの2層構造になりました。
システムプロンプトでは、AI の「役割」と「出力フォーマット」を明確に定義しています。
const systemPrompt = `あなたはフリーランスの案件管理を支援するAIです。
依頼内容を分析し、確認すべき項目をJSON形式で返してください。
出力フォーマット:
{
"summary": "依頼内容の要約(1-2文)",
"clarifications": [
{
"category": "カテゴリ名",
"question": "具体的な確認質問"
}
]
}`;
ユーザープロンプトには、依頼内容に加えて案件タイプと過去の類似依頼パターンを含めています。
const userPrompt = `
依頼内容: ${request.title} - ${request.description}
案件タイプ: ${request.jobType}
過去の類似依頼パターン: ${pastPatterns}
上記の依頼について、サービス提供者が見積もり前に
確認すべき項目を提案してください。
カテゴリ: 納品形式、作業範囲、技術要件、
修正対応、素材提供
`;
ここでのポイントは「過去の類似依頼パターン」を渡していることです。同じクライアントから以前にも似た依頼があった場合、その情報を AI に与えることで、より的確な確認項目を生成できるようになりました。
Vercel AI SDK + Gemini の記事でもモデル選定について書きましたが、Wakulier では Gemini の日本語対応力とコストパフォーマンスを評価して採用しています。
フォールバック処理の設計
AI を組み込んだ機能で見落としがちなのが、「AI が使えないケース」への対応です。
開発日記にはこう記録しています:
短い依頼(「いつもの」など)では AIが有効な解析結果を返せない。APIコスト削減と応答速度向上のためスキップ
実際に起こりうるケースを洗い出してみると、いくつかのパターンがあります。
- 入力が短すぎる: 「いつものお願いします」「前回と同じで」
- API がダウンしている: 外部サービスの障害
- レスポンスが不正: AI が期待するフォーマットで返さない
- タイムアウト: 応答に時間がかかりすぎる
これらすべてに対応するため、まず「入力テキストが30文字未満の場合は AI 解析をスキップし、汎用的な確認チェックリストを返す」というルールを設けました。
function analyzeRequest(title: string, description: string) {
const inputText = `${title} ${description}`.trim();
if (inputText.length < 30) {
// AI解析をスキップ、汎用チェックリストを返却
return getGenericChecklist();
}
// Gemini API で解析
return callGeminiApi(inputText);
}
30文字という閾値は、実際の依頼データを見ながら決めました。「いつものお願いします」が12文字、「前回のロゴと同じ感じでバナー作成お願いします」が22文字。こうした短文に対して AI に解析させても、有用な確認項目は生成されません。むしろ、汎用的なチェックリスト(「納期はいつですか?」「予算の目安は?」「修正回数の上限は?」)を即座に返す方がユーザー体験として優れています。
API のエラーや不正レスポンスに対しても同じ汎用チェックリストにフォールバックする設計にしました。AI はあくまで「あれば便利」な補助機能であり、AI が使えなくてもコア機能は動き続けるべきだという考えです。
Zod によるレスポンス検証
AI のレスポンスは構造化されているとは限りません。JSON 形式で返すよう指示しても、たまに余計なテキストが混じったり、期待するフィールドが欠落したりします。
そこで Zod スキーマによるバリデーションを挟みました。
import { z } from "zod";
const ClarificationSchema = z.object({
category: z.string(),
question: z.string(),
});
const AnalysisResponseSchema = z.object({
summary: z.string(),
clarifications: z.array(ClarificationSchema).min(1),
});
// レスポンス検証
function validateResponse(raw: unknown) {
const result = AnalysisResponseSchema.safeParse(raw);
if (!result.success) {
return getGenericChecklist(); // フォールバック
}
return result.data;
}
safeParse を使うことで、バリデーション失敗時にエラーを投げるのではなく、フォールバックに切り替えられます。これは先ほどのフォールバック設計と一貫した方針です。AI の出力は「信頼するが検証する」(trust but verify)。この姿勢が、プロダクションで AI を使う際の基本だと考えています。
AI フレームワーク分析の記事でも JSON 出力の工夫について触れましたが、Zod との組み合わせはさらに一歩進んだ安全策です。
DB スキーマの考慮点
AI 支援機能の実装では、データベース側にも変更が必要でした。確認リクエストの送信と回答を管理するため、依頼のステータスに clarification_requested(確認リクエスト送信済み)と clarification_answered(回答済み)を追加しました。
ここで一つハマったのが、PostgreSQL の ENUM 型の更新です。
開発日記にはこう書いています:
PostgreSQLのENUM型に新しいステータスを追加し忘れてエラー。マイグレーションファイルでALTER TYPEを使ってENUM値を追加。
Supabase で PostgreSQL を使っている場合、ENUM 型に新しい値を追加するには ALTER TYPE ... ADD VALUE 構文が必要です。
ALTER TYPE request_status ADD VALUE 'clarification_requested';
ALTER TYPE request_status ADD VALUE 'clarification_answered';
通常のカラム追加やテーブル変更と違い、ENUM の更新は専用の構文が必要という点は見落としやすいポイントです。マイグレーションファイルを作る際に忘れてしまい、アプリケーション側で新しいステータスを使おうとしたタイミングでエラーが発生しました。
ステータス遷移も複雑になりました。もともとは「新規 → 見積もり中 → 作業中 → 完了」というシンプルな流れだったところに、「新規 → 確認リクエスト送信済み → 回答済み → 見積もり中 → ...」という分岐が加わります。UI 側のプログレスインジケーターの表示ロジックも合わせて調整が必要でした。
こうした「AI 機能を追加することで、既存のデータモデルやワークフローにどんな影響が出るか」を事前に洗い出しておくことが重要です。AI の実装そのものよりも、既存システムとの統合の方が工数がかかるケースは少なくありません。
この実装から学んだこと
Gemini API を使った AI 支援機能の実装を通じて、いくつかの教訓を得ました。
1. プロンプトは「具体的なカテゴリ指定」が効果的
3段階の試行錯誤で最も効果があったのは、第3段階の「カテゴリ指定」でした。AI に対して「考えて」と丸投げするのではなく、「この枠組みの中で考えて」と制約を与える。これはプロンプト設計の基本原則と言えるかもしれません。
自由度が高すぎると AI は一般論に流れ、制約が厳しすぎると柔軟性がなくなる。この間のバランスを見つけるのがプロンプト設計の醍醐味であり、難しさでもあります。
2. フォールバック処理は必須
AI を組み込んだ機能では、「AI が使えない場合」を必ず想定すべきです。今回は入力テキストの長さチェック、API エラー、レスポンスのバリデーション失敗、すべてに対してフォールバックを用意しました。
ユーザーから見れば、AI が動いていようがフォールバックが動いていようが、「確認項目の提案が表示される」という体験に変わりはありません。この「透明なフォールバック」が、AI 機能の信頼性を支える土台になります。
3. AI の出力は必ず検証する
Zod スキーマによるバリデーションは、AI 出力の信頼性を担保するための重要な仕組みです。AI は確率的に出力を生成するため、100% 正しいフォーマットが返ってくる保証はありません。safeParse でバリデーションし、失敗時にはフォールバックに切り替える。このパターンは AI 連携全般で使える汎用的な設計です。
4. AI 機能追加は既存システムへの影響も大きい
今回の実装では、AI のプロンプト設計よりも DB スキーマの変更やステータス遷移の調整に予想以上の工数がかかりました。新しい AI 機能を企画するとき、AI 側の実装だけでなく、既存のデータモデル、ワークフロー、UI への影響を事前に見積もることが大切です。
まとめ
プロダクトに AI を組み込むのは、「API を叩く」だけの話ではありません。プロンプト設計の試行錯誤、フォールバック処理の設計、レスポンスの検証、既存システムとの統合。これらすべてを含めて「AI 機能の実装」です。
特にプロンプト設計については、「曖昧な指示 → 一般的な回答」「具体的な制約 → 実用的な回答」という関係を体験できたことが大きな収穫でした。これから AI 支援機能を自分のプロダクトに組み込もうとしている方にとって、この3段階の試行錯誤が参考になれば幸いです。
AI は万能ではありませんが、適切に設計すればユーザーの強力な味方になります。大事なのは、AI が使えないときにもプロダクトが壊れない設計を最初から組み込むこと。フォールバックを後から追加するのではなく、設計の初期段階から「AI なしでも動く」を前提にする。この考え方が、AI ネイティブなプロダクト開発の基本姿勢だと考えています。
Zeronova(ゼロノバ)
Product Manager / AI-Native Builder
Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。