{
  "_comments": {
    "llm.provider": "LLM provider: openclaw (default) or openai-compatible.",
    "llm.model": "Provider model ID; keep openclaw for the default provider, or set the proxy model ID for openai-compatible.",
    "llm.temperature": "LLM sampling temperature; default 0.5.",
    "llm.maxTokens": "Maximum response tokens; default 300.",
    "llm.historyMaxTurns": "Local conversation turns retained for standalone providers; default 12. Set 0 when the upstream gateway owns session history.",
    "llm.systemPrompt": "Standalone provider persona; leave empty to use the built-in persona template.",
    "llm.openaiCompatible.baseUrl": "OpenAI-compatible proxy base URL; required when llm.provider is openai-compatible.",
    "llm.openaiCompatible.emptyResponseRetry": "Retry one empty streaming response once (default true). Set false for stateful gateways where replaying the same turn is unsafe.",
    "llm.openaiCompatible.trustedAgentTools": "Send X-Caty-Agent-Trust: trusted (default false). Enable only for a trusted local tool-capable gateway in a trusted meeting.",
    "llm.openaiCompatible.sessionHeader": "Optional per-meeting session header name (default empty/off). Set to X-Hermes-Session-Id only for a Hermes Agent api_server.",
    "prompts.voiceEmotionLine": "Line inserted into the voice system addendum when agent.emotionTags is true.",
    "prompts.voiceSystemAddendumTemplate": "Voice-mode system addendum template; supports {emotionLine}, {openclawSlackRule}, and {openclawRules} placeholders.",
    "prompts.voiceSystemAddendum": "Optional full voice system addendum override; leave empty to use the template.",
    "prompts.summary": "Prompt prefix used when generating meeting summaries.",
    "prompts.gatewayBriefingSystem": "System prompt used by Gateway warm-up when a briefing is supplied.",
    "prompts.gatewayWarmupUser": "User prompt used by Gateway warm-up when no briefing is supplied.",
    "prompts.timeoutHandoffGateway": "User prompt template for timeout handoff in Gateway events mode; {request} is the user request.",
    "prompts.timeoutHandoffSlack": "User prompt template for timeout handoff in legacy Slack mode; {request} is the user request.",
    "prompts.timeoutHandoffGatewaySystem": "System prompt for timeout handoff in Gateway events mode.",
    "prompts.timeoutHandoffSlackSystem": "System prompt for timeout handoff in legacy Slack mode.",
    "agent.messages.ackVariants": "Immediate acknowledgement lines spoken after addressed turns.",
    "agent.messages.progressPings": "Progress ping lines spoken during long turns.",
    "agent.messages.timeoutFallback": "Spoken line for normal LLM response timeout.",
    "agent.messages.forcedDelegationFallback": "Spoken line when forced delegation fires in legacy Slack mode.",
    "agent.messages.handoffSuccess": "Spoken follow-up when legacy timeout handoff succeeds.",
    "agent.messages.handoffFailure": "Spoken follow-up when timeout handoff fails.",
    "agent.messages.forcedDelegationFallbackMeet": "Spoken line when forced delegation fires in Gateway events mode.",
    "agent.messages.handoffUnconfirmedMeet": "Spoken follow-up when Gateway events handoff is dispatched but unconfirmed.",
    "agent.messages.handoffBusyMeet": "Spoken follow-up when Gateway events handoff is blocked by the queue/cap.",
    "agent.messages.reportPostUnknown": "Spoken line when a delegation result is ready but chat posting is unavailable.",
    "agent.messages.circuitBreakerRecoveryNotice": "Spoken line when the timeout circuit breaker opens.",
    "agent.messages.exitFarewell": "Default farewell line for voice exit.",
    "agent.messages.completionVoiceTemplate": "Spoken delegation completion template; {label} is the delegation label.",
    "agent.messages.staleCompletionVoicePrefix": "Prefix added to stale delegation completion voice lines.",
    "agent.messages.errorVoice": "Spoken generic error line.",
    "regex.cancelPattern": "Cancel intent regular expression pattern.",
    "regex.cancelFlags": "Flags for regex.cancelPattern.",
    "regex.immediateAckPattern": "Japanese request-like utterance pattern retained for immediate ack classification.",
    "regex.immediateAckFlags": "Flags for regex.immediateAckPattern.",
    "regex.immediateAckEnglishPattern": "English request-like utterance pattern retained for immediate ack classification.",
    "regex.immediateAckEnglishFlags": "Flags for regex.immediateAckEnglishPattern.",
    "regex.immediateAckTaskPattern": "Pattern used to prefer task-oriented ack variants.",
    "regex.immediateAckTaskFlags": "Flags for regex.immediateAckTaskPattern.",
    "regex.immediateAckTaskVariantPattern": "Pattern used to find a task-oriented ack variant.",
    "regex.immediateAckTaskVariantFlags": "Flags for regex.immediateAckTaskVariantPattern.",
    "regex.shortUtterancePingPatterns": "Patterns that classify short utterances as ping/health checks.",
    "regex.shortUtterancePingFlags": "Flags applied to every regex.shortUtterancePingPatterns entry.",
    "delegation.statusComplete": "Slack/report status label for completed delegation tasks.",
    "delegation.statusIncomplete": "Slack/report status label for incomplete delegation tasks.",
    "delegation.sectionHeading": "Slack/report heading for delegation result sections.",
    "delegation.defaultLabel": "Fallback delegation task label.",
    "delegation.emptyResult": "Fallback text when a result section has no body.",
    "delegation.missingResult": "Fallback text when a completion result body is missing.",
    "delegation.chatPrefix": "Prefix for delegation completion chat messages.",
    "exit.commands": "Voice commands that request bot exit when no agent-specific commands are set.",
    "slack.labels.stateEmoji": "Slack status labels by lifecycle state.",
    "slack.labels.transportLabel": "Slack transport labels by meeting platform.",
    "slack.labels.statusCompleteSuffix": "Suffix for completed Slack status headings.",
    "slack.labels.statusSuffix": "Suffix for non-terminal Slack status headings.",
    "slack.labels.separator": "Separator line used in Slack messages.",
    "slack.labels.agentLinePrefix": "Slack status field label for agent names.",
    "slack.labels.meetingLinePrefix": "Slack status field label for meeting URL/target.",
    "slack.labels.stateLinePrefix": "Slack status field label for lifecycle state.",
    "slack.labels.durationLinePrefix": "Slack field label for completed meeting duration.",
    "slack.labels.elapsedLinePrefix": "Slack field label for in-progress elapsed time.",
    "slack.labels.emptyValue": "Slack placeholder for missing values.",
    "slack.labels.summaryTitlePrefix": "Slack summary title prefix.",
    "slack.labels.summaryTitleSuffix": "Slack summary title suffix.",
    "slack.labels.summarySection": "Slack summary section heading.",
    "slack.labels.decisionsSection": "Slack decisions section heading.",
    "slack.labels.todosSection": "Slack TODO section heading.",
    "slack.labels.utteranceStatsPrefix": "Slack utterance statistics label.",
    "slack.labels.userLabel": "Slack utterance statistics user label.",
    "slack.labels.defaultAgentLabel": "Slack fallback agent label.",
    "gateway.displayName": "Gateway events client display name.",
    "soniox.smokeDefaultKeyterms": "Default keyterms for scripts/soniox-smoke.js when WAKE_WORDS is unset.",
    "avatar.faceAudioDefault": "Page-audio default for face-package joins: empty (WebSocket, default) or page. Applies only with self-hosted Attendee, an explicit face-package join and no floor hub; an explicit join field wins.",
    "attendee.host": "Bot host: attendee-cloud (default) or attendee-self-hosted. Leave it out to keep the pre-#260 behaviour; set it from the settings UI (applies from the next join).",
    "attendee.selfHosted.url": "Self-hosted Attendee endpoint: https://host[:port][/base]; http:// only to a private-network address. Used only when attendee.host is attendee-self-hosted. No env alias.",
    "attendee.selfHosted.apiKey": "Self-hosted Attendee API key (class-1, masked in the UI). Never sent to the Attendee cloud endpoint. No env alias.",
    "avatar.faceTimelineOffsetMsSelfHosted": "Lip-sync offset in ms (-3000..3000, default 300) used when the self-hosted Attendee is selected; avatar.faceTimelineOffsetMs is the Attendee cloud value.",
    "server.remoteSettingsAccess": "Remote settings access through Tailscale Serve (default false, applies live). Turn it on only on the server (local settings page or this file); server.publicOrigin must be the Serve https://<name>.ts.net address and Serve (HTTP mode, tailnet only) must be the only forwarder to the port. No env alias, never exported.",
    "server.remoteSettingsLogin": "Optional login pin for remote settings access (default empty = any identity Tailscale Serve vouches for). When set, the Tailscale login must match it, case-insensitively. Set or clear it only on the server. No env alias, never exported."
  },
  "prompts": {
    "voiceSystemAddendum": "",
    "summary": "以下の音声通話/会議の会話ログから、簡潔なサマリーをJSON形式で生成してください。\n\n出力フォーマット（必ずこのJSONのみ出力すること）:\n{\n  \"summary\": [\"要約1\", \"要約2\", \"要約3\"],\n  \"decisions\": [\"決定事項1\"],\n  \"todos\": [\"TODO1\"]\n}\n\nルール:\n- summaryは最大3項目の箇条書き\n- decisionsは決定事項があれば記載（なければ空配列）\n- todosはTODOがあれば記載（なければ空配列）\n- JSONのみ出力。説明やマークダウンは不要\n\n会話ログ:\n",
    "gatewayWarmupUser": "セッション準備中。次のメッセージから音声通話が始まります。",
    "timeoutHandoffGateway": "ユーザーの音声通話中に依頼処理がタイムアウトしました。\n必ず sessions_spawn を使って作業を委譲してください。\nまずユーザー依頼を短く要約し、実行計画を立ててからサブエージェントを起動してください。\nサブエージェントの結果を最終回答としてそのまま返してください。会議への報告は音声ハーネス側が行います。\n\nユーザー依頼: {request}",
    "timeoutHandoffSlack": "ユーザーの音声通話中に依頼処理がタイムアウトしました。\n必ず sessions_spawn を使って作業を委譲し、結果をSlackに投稿してください。\nまずユーザー依頼を短く要約し、実行計画を立ててからサブエージェントを起動してください。\n\nユーザー依頼: {request}",
    "timeoutHandoffGatewaySystem": "あなたは音声タイムアウト時の自動委譲ハンドラーです。必ず sessions_spawn に委譲し、結果を最終回答として返してください。",
    "timeoutHandoffSlackSystem": "あなたは音声タイムアウト時の自動委譲ハンドラーです。結果は必ずSlackに共有してください。"
  },
  "agent": {
    "id": "your-agent-id",
    "name": "YourAgent",
    "displayName": "エージェント名",
    "language": "ja",
    "greeting": "[warm] こんにちは！よろしくお願いします！",
    "emotionTags": true,
    "wakeWords": ["エージェント名", "your-agent"],
    "replyTrigger": "wake",
    "replyJudge": { "addressedMin": 0.75, "finishedMin": 0.75, "continuationWaitMs": 3000, "timeoutMs": 800, "contextLines": 6 },
    "keyterms": ["エージェント名", "YourAgent"],
    "sttWakeVariants": [],
    "ackVariants": ["[soft voice] 了解、すぐ取りかかるね。"],
    "exitFarewell": "[warm] お疲れ様でした。また何かあったら呼んでね！",
    "cancelAck": "[soft voice] 了解、キャンセルしたよ。",
    "progressPings": ["[soft voice] 少々お待ちください…", "[soft voice] もう少しで…"],
    "timeoutFallback": "[empathetic, unhurried] ごめんね、ちょっと時間がかかっちゃって…",
    "avatarUrl": "",
    "messages": {
      "ackVariants": ["[soft voice] 了解、すぐ取りかかるね。", "[soft voice] 了解です。ちょっと待ってね。", "[soft voice] はい、今確認するね。"],
      "progressPings": ["[soft voice] いま処理中だよ、もう少し待ってね。", "[soft voice] 進めてるよ、あと少しで返せそう。", "[soft voice] ごめん、もう少しだけ待ってね。"],
      "timeoutFallback": "[empathetic, unhurried] ごめん、ちょっと時間がかかってるね。少し待ってもらえるかな？",
      "forcedDelegationFallback": "ちょっと時間がかかってるから、詳細はあとでSlackで共有するね。",
      "handoffSuccess": "[soft voice] 続きはSlackに共有しておくね。",
      "handoffFailure": "[soft voice] ごめん、うまく繋げられなかったみたい。あとでもう一回試してね。",
      "forcedDelegationFallbackMeet": "ちょっと時間がかかってるから、裏でまとめておくね。",
      "handoffUnconfirmedMeet": "[soft voice] 続きは裏に回したよ。まとまったらチャットに貼るね。",
      "handoffBusyMeet": "[soft voice] ごめんね、いま立て込んでるから少し待ってね。",
      "reportPostUnknown": "結果まとまったよ、あとでログにも残すね。",
      "circuitBreakerRecoveryNotice": "[soft voice] ごめんね、ちょっと立て直し中。急ぎはそのまま話しかけてね。",
      "exitFarewell": "[warm] 了解です！退出しますね。お疲れさまでした！",
      "completionVoiceTemplate": "さっきの「{label}」、まとまったよ。チャットに貼ったね。",
      "staleCompletionVoicePrefix": "(遅くなってごめんね) ",
      "errorVoice": "すみません、ちょっとエラーが起きちゃいました。"
    }
  },
  "llm": {
    "provider": "openclaw",
    "model": "openclaw",
    "temperature": 0.5,
    "maxTokens": 300,
    "historyMaxTurns": 12,
    "systemPrompt": "",
    "openaiCompatible": {
      "baseUrl": "",
      "emptyResponseRetry": true,
      "trustedAgentTools": false,
      "sessionHeader": ""
    }
  },
  "gateway": {
    "warmupTimeoutMs": 8000,
    "displayName": "AI MeetServer"
  },
  "regex": {
    "cancelPattern": "^[\\s\\u3000]*(キャンセル|やめて|もういい|中止|ストップ|stop|cancel)[\\s\\u3000。！!]*$",
    "cancelFlags": "i",
    "immediateAckPattern": "お願い|やって|して|調べ|確認|探し|実装|作業|対応|予約|連絡|電話|送って|まとめ",
    "immediateAckFlags": "i",
    "immediateAckEnglishPattern": "can you|please|check|find|implement|do this|call|book|summarize",
    "immediateAckEnglishFlags": "i",
    "immediateAckTaskPattern": "調べ|確認|探し|予約|連絡|call|check|find|book",
    "immediateAckTaskFlags": "i",
    "immediateAckTaskVariantPattern": "確認|調べ|check",
    "immediateAckTaskVariantFlags": "i",
    "shortUtterancePingPatterns": ["話せる", "大丈夫", "聞こえ", "おーい", "元気", "どう[?？]?$", "テスト"],
    "shortUtterancePingFlags": "u"
  },
  "delegation": {
    "statusComplete": "完了",
    "statusIncomplete": "未完",
    "sectionHeading": "## 委譲タスク結果",
    "defaultLabel": "委譲タスク",
    "emptyResult": "結果本文なし",
    "missingResult": "結果本文を取得できませんでした。",
    "chatPrefix": "委譲タスク結果"
  },
  "exit": {
    "commands": ["退出して", "退出していいよ", "退出", "退出して大丈夫", "退室して", "退室していいよ", "退室", "退室して大丈夫", "退室してもらって"]
  },
  "tts": {
    "provider": "fish-audio",
    "apiKey": "",
    "voiceId": "",
    "model": "s2-pro",
    "speed": 1,
    "latency": "balanced",
    "sampleRate": 24000,
    "cache": {
      "enabled": true,
      "prewarm": true
    }
  },
  "stt": {
    "provider": "soniox",
    "sonioxApiKey": "",
    "apiKey": "",
    "endpointingMs": 400,
    "utteranceEndMs": 1200,
    "soniox": {
      "model": "stt-rt-v5",
      "wsUrl": "wss://stt-rt.soniox.com/transcribe-websocket",
      "endpointSensitivity": null,
      "maxEndpointDelayMs": null,
      "endpointLatencyLevel": null
    }
  },
  "slack": {
    "botToken": "",
    "notifications": {
      "enabled": true,
      "target": "dm",
      "dmUserId": ""
    },
    "notifyChannel": "",
    "summaryChannel": "",
    "statusChannel": "",
    "labels": {
      "stateEmoji": {
        "idle": "⬜ 待機",
        "initiating": "⏳ 受付",
        "ringing": "🔔 発信中",
        "in-progress": "🟢 通話中",
        "ending": "🔄 終了処理中",
        "completed": "✅ 完了",
        "failed": "❌ 失敗"
      },
      "transportLabel": {
        "meet": "🎥 Google Meet",
        "zoom": "🎥 Zoom Meeting"
      },
      "statusCompleteSuffix": "完了",
      "statusSuffix": "ステータス",
      "separator": "━━━━━━━━━━━━━━━",
      "agentLinePrefix": "🤖 エージェント",
      "meetingLinePrefix": "🔗 ミーティング",
      "stateLinePrefix": "📊 状態",
      "durationLinePrefix": "⏱️ 会議時間",
      "elapsedLinePrefix": "⏱️ 経過",
      "emptyValue": "—",
      "summaryTitlePrefix": "📋",
      "summaryTitleSuffix": "サマリー",
      "summarySection": "📝 要約",
      "decisionsSection": "✅ 決定事項",
      "todosSection": "📌 TODO",
      "utteranceStatsPrefix": "💬 発話数",
      "userLabel": "ユーザー",
      "defaultAgentLabel": "AI"
    }
  },
  "soniox": {
    "smokeDefaultKeyterms": "AIエージェント"
  },
  "attendee": {
    "apiKey": "",
    "baseUrl": "app.attendee.dev",
    "selfHosted": {
      "url": "",
      "apiKey": ""
    }
  },
  "discord": {
    "botToken": "your_discord_bot_token",
    "guildAllowlist": [],
    "lcmIngestEnabled": false
  },
  "server": {
    "port": 5005,
    "ngrokDomain": "",
    "publicOrigin": "",
    "remoteSettingsAccess": false,
    "remoteSettingsLogin": ""
  },
  "summary": {
    "enabled": true
  },
  "features": {
    "taskExtractionEnabled": true,
    "streamingEquivalentEnabled": true
  },
  "avatar": {
    "experiment": "",
    "emotionJudge": "off",
    "faceListenReactions": false,
    "faceTimelineOffsetMs": 300,
    "faceAudioDefault": "",
    "faceTimelineOffsetMsSelfHosted": 300
  }
}
