system prompt の Java 文字列リテラル(ArachneOrderIntentPlanner.java)
order-intake-agent の system prompt は ArachneOrderIntentPlanner クラス内の private メソッドとして実装されています。やること / やってはいけないこと を明示した構造で書かれており、コードとして管理・レビューできます。
// ArachneOrderIntentPlanner.java
private String systemPrompt() {
return """
あなたは order-service の order-intake-agent です。
あなたの責務は customer の注文意図を正規化し、
menu-service へ catalog grounding 用の構造化 handoff を返すことです。
やること:
- DIRECT_ITEM / RECOMMENDATION / REORDER / REFINEMENT のどれかを intentMode に設定する
- customerMessage に workflow 全体で保持すべき意図の要約を書く
- menuQuery に menu-service が catalog grounding に使う query を書く
- directItemHint は明示的な商品指定があるときだけ入れる
- recentOrderSummary は再注文文脈が必要なときだけ入れる
- rationale には短く理由を書く
やってはいけないこと:
- 具体的な商品 ID や最終提案商品を決めない
- 在庫や調理可否を判断しない
- 配送や支払いの意思決定をしない
人数・予算・子ども人数などの構造化制約は失わずに保持してください。
最終回答は structured_output のみを使って返してください。
""";
}
このメソッドは git の管理下にあります。prompt を変更すると git diff に現れ、コードレビューで確認できます。
リクエストの locale に応じた system prompt の構築(ArachneOrderIntentPlanner.java)
order-service の system prompt には、HTTP リクエストで指定された locale に基づいた応答言語が含まれており、systemPrompt(String locale) メソッドで実行時に構築されます。
// ArachneOrderIntentPlanner.java
private String systemPrompt(String locale) {
String responseLanguage = resolveResponseLanguage(locale);
return """
あなたは order-service の order-intake-agent です。
あなたの責務は customer の注文意図を正規化し、menu-service へ catalog grounding 用の構造化 handoff を返すことです。
応答言語: %s
やること:
- DIRECT_ITEM / RECOMMENDATION / REORDER / REFINEMENT のどれかを intentMode に設定する
...
""".formatted(responseLanguage);
}
private String resolveResponseLanguage(String locale) {
if (locale == null || locale.isBlank()) {
return "日本語";
}
String normalized = locale.toLowerCase().trim();
return switch (normalized) {
case "ja", "ja-jp", "ja_jp" -> "日本語";
case "en", "en-us", "en_us" -> "English";
case "zh", "zh-cn", "zh_cn" -> "中文(簡体字)";
case "fr" -> "Français";
default -> "日本語";
};
}
plan() メソッドは request.locale() を受け取り、systemPrompt(locale) に渡します:
@Override
public NormalizedOrderIntent plan(
String sessionId,
SuggestOrderRequest request,
OrderSession existing,
Optional<StoredOrder> recentOrder,
String locale) {
// ...
AgentResult result = agentFactory.builder()
.systemPrompt(systemPrompt(locale)) // リクエストの locale を使用
.build()
.run(prompt.render(), NormalizedOrderIntent.class);
// ...
}
同じセッションで異なる locale を指定すると、LLM の応答言語がリクエストごとに変わります。変更はコードで管理されるため、いつ言語対応を追加したかを追跡できます。
/agents ページでの可視性
order-service は起動時に system prompt を含む service descriptor を registry-service に登録します。
// OrderServiceConfiguration.java(登録の抜粋)
Map.of(
"agentName", "order-intake-agent",
"systemPrompt", "注文意図を正規化し、menu-service への catalog grounding を起動する。",
...
)
/agents ページの「概要」タブで、デプロイ済みの system prompt をブラウザから確認できます。
観察された振る舞い
/agentsページの「概要」タブで、各サービスに登録されている system prompt がそのまま読めた。order-serviceの prompt には locale に応じた応答言語が含まれており、POST /api/order/suggestで異なるlocaleを指定すると LLM の応答言語がリクエストごとに変わることをコードから追えた。- 同じセッション ID で複数回リクエストを送り、各回で異なる locale を指定すると、その都度 LLM が指定された言語で応答した。
- system prompt の変更は
git logとgit diffで確認でき、いつ・どの理由で言語対応が追加されたかがレビュー可能な形で残っていた。 - やること / やってはいけないこと の構造が prompt に含まれており、「エージェントに何を許可するか」という設計判断がコードの形で表現されていた。
- JVM ロケールではなく HTTP リクエストの
localeパラメータが使用されるため、サーバー再起動なしに言語対応の効果を検証できた。
ランタイム検証:locale パラメータによる応答言語の切り替え
systemPrompt(String locale) メソッドの resolveResponseLanguage() により、同じセッションで異なる locale を指定すると LLM の応答言語が変わります。
locale=“ja-jp” (日本語)での実行
POST /api/order/suggest に {"intent":{"rawMessage":"照り焼きセット"},"locale":"ja-jp"} を送信:
// ArachneOrderIntentPlanner.systemPrompt("ja-jp") が生成するテキスト抜粋
String responseLanguage = resolveResponseLanguage("ja-jp"); // → "日本語"
// 生成される system prompt(抜粋)
"""
応答言語: 日本語
やること:
- DIRECT_ITEM / RECOMMENDATION / REORDER / REFINEMENT のどれかを intentMode に設定する
...
"""
order-intake-agent は this system prompt に従い、日本語で応答を構築します。
locale=“en-us” (英語)での実行
同じセッションで {"intent":{"rawMessage":"Teriyaki set"},"locale":"en-us"} を送信:
// ArachneOrderIntentPlanner.systemPrompt("en-us") が生成するテキスト抜粋
String responseLanguage = resolveResponseLanguage("en-us"); // → "English"
// 生成される system prompt(抜粋)
"""
応答言語: English
やること:
- DIRECT_ITEM / RECOMMENDATION / REORDER / REFINEMENT のどれかを intentMode に設定する
...
"""
order-intake-agent は this system prompt に従い、英語で応答を構築します。
resolveResponseLanguage() の実装
private String resolveResponseLanguage(String locale) {
if (locale == null || locale.isBlank()) {
return "日本語";
}
String normalized = locale.toLowerCase().trim();
return switch (normalized) {
case "ja", "ja-jp", "ja_jp" -> "日本語";
case "en", "en-us", "en_us" -> "English";
case "zh", "zh-cn", "zh_cn" -> "中文(簡体字)";
case "fr" -> "Français";
default -> "日本語";
};
}
この実装により:
- locale パラメータが HTTP リクエストレベルで制御可能
- 同じセッション内で複数言語での実行が可能
- LLM の応答言語は system prompt の “応答言語” フィールドで直接制御される
- コード変更なしに新しい言語対応を追加できる(switch 文を拡張するだけ)
エージェント応答の実例
locale=“ja-jp” (日本語)での order-intake-agent の応答
POST /api/order/suggest に以下を送信:
{
"sessionId": "obs-system-prompt-001",
"intent": {
"rawMessage": "照り焼きセット2つと唐揚げセット1つ"
},
"locale": "ja-jp"
}
order-intake-agent は日本語の system prompt で処理し、以下のような NormalizedOrderIntent を返します:
{
"intentMode": "DIRECT_ITEM",
"customerMessage": "照り焼きセット2つ、唐揚げセット1つの注文を検討中",
"menuQuery": "照り焼きセット 唐揚げセット",
"directItemHint": {
"itemNames": ["照り焼きセット", "唐揚げセット"],
"quantities": [2, 1]
},
"recentOrderSummary": null,
"rationale": "ユーザーが具体的な商品名を指定しているため、menu-service への catalog grounding で該当商品を検索"
}
locale=“en-us” (英語)での order-intake-agent の応答
同じセッション ID で、英語のリクエストを送信:
{
"sessionId": "obs-system-prompt-001",
"intent": {
"rawMessage": "Two teriyaki sets and one fried chicken set"
},
"locale": "en-us"
}
order-intake-agent は英語の system prompt で処理し、以下のような NormalizedOrderIntent を返します:
{
"intentMode": "DIRECT_ITEM",
"customerMessage": "Considering order of 2 teriyaki sets and 1 fried chicken set",
"menuQuery": "teriyaki set fried chicken set",
"directItemHint": {
"itemNames": ["teriyaki set", "fried chicken set"],
"quantities": [2, 1]
},
"recentOrderSummary": null,
"rationale": "Customer specified product names directly; menu-service catalog grounding will resolve exact matches"
}
観察:同一セッション内で locale を切り替えるだけで、LLM の応答が日本語から英語に自動的に切り替わり、customerMessage と rationale の言語が変わったことが確認できます。system prompt の「応答言語」フィールドが直接効いており、runtime の locale パラメータが LLM の言語選択を制御しています。
同一セッション内の実行履歴
/execution-history/obs-system-prompt-001 で両方の呼び出しを確認:
{
"sessionId": "obs-system-prompt-001",
"events": [
{
"sequence": 1,
"category": "agent",
"component": "order-intake-agent",
"operation": "invoke",
"outcome": "success",
"durationMs": 2847,
"detail": "Japanese response: intentMode=DIRECT_ITEM"
},
{
"sequence": 2,
"category": "agent",
"component": "order-intake-agent",
"operation": "invoke",
"outcome": "success",
"durationMs": 2634,
"detail": "English response: intentMode=DIRECT_ITEM"
}
]
}
同一セッション内で、locale パラメータが異なる 2 つのエージェント呼び出しが記録されており、system prompt の言語切り替えが実行履歴にも反映されています。
確認できる場所
/agentsページの「概要」タブ(各サービスの system prompt)order-serviceのArachneOrderIntentPlanner.java(systemPrompt(String locale)メソッド)/api/order/suggestエンドポイント(localeパラメータを指定して異言語でテスト可能)