Files
vocero-client/docs/client/context-injection.md
T
alvaro dfed03ac7c chore(vocero): remove the legacy ApiPilot integration (#3)
Vocero now retrieves AquaPortal content through authenticated MCP. This removes the obsolete ApiPilot integration from the API and browser while preserving the separately deployed speech pipeline.

Release notes:

- Removed ApiPilot endpoints, configuration, credential overrides, and HTTP/realtime tool execution.
- Removed browser ApiPilot catalog loading and prompt generation while retaining authenticated MCP discovery.
- Updated regression coverage and operating documentation for the retired routes and settings.

Reviewed-on: AquaPortal/s2s#3
2026-10-08 11:23:41 -04:00

7.7 KiB
Raw Blame History

Context injection

Context reaches the assistant through browser-built instructions, server-patched realtime session instructions, and HTTP reasoning context. The implementation is in the server's context services, realtime proxy, context.ts, and the WebSocket client.

Authenticated MCP context

When S2S_MCP_URL is configured, the browser submits the page's report_id and episode_id during conversation creation. The server resolves them through the authenticated MCP client and keeps compact verified references separately from the current conversational selection. No legacy profile or episode preload is used. TALKFIRST can mention the verified title after this preparation finishes. The link never restricts searches or access to other permitted content.

See tool calling for selection, authorization, timeout, and missing-content behavior. The controls and public episode fetch below describe the legacy path used when MCP is disabled.

Independent controls

S2S_INJECT_PROFILE defaults to false and gates server loading of caller, episode, report and prior-conversation context. It also controls whether the browser appends caller profile text to its realtime instructions.

It is not a master switch for every context source. Operator-supplied RAG text and authenticated MCP orchestration work independently. S2S_INJECT_TODAY defaults to true; date and voice-output guards are built on paths that invoke instruction augmentation or HTTP context assembly. A WebSocket session with no profile/episode/report/summary block skips non-MCP proxy augmentation. Direct browser connections bypass server-side WebSocket injection entirely.

Setting Default Effect
S2S_INJECT_PROFILE false Enable server-resolved caller, episode and history context
S2S_INJECT_REPORTS false Allow scheduled-report fetch/injection; also requires the profile gate
S2S_REPORTS_INJECT_MODE minimal minimal: labels/dates; full: scripts; off/none: no report prompt block
S2S_REPORTS_QUICK_HINT_MAX 5 Keep at most this many newest reports, clamped to 1–50
S2S_INJECT_TODAY true Add the current server-local date guard when its context builder runs
S2S_DEBUG_PROMPT false Log complete prompt/context text instead of only summaries

Context sources

Block Trigger and source Size/behavior
Podcast episode episode_id page/query/body value and profile gate Up to 24,000 characters of serialized episode content
Caller profile phoneNumber and VOCERO_USER_PHONE_AUTH_URL Up to 1,600 serialized characters
Scheduled reports S2S_REPORT_LIST, profile gate and report gate Newest N labels/dates by default; full mode includes scripts with a 12,000-character block limit
Latest conversation S2S_LATEST_SUMMARY_TEXT, or S2S_LATEST_SUMMARY with a phone number Up to 1,600 characters; static text overrides HTTP fetch
Custom RAG Operator applies text through the RAG dialog Up to 12,000 characters; appended in browser instructions and HTTP user_context

Episode

The current episode fetch uses the deployment-specific URL:

https://aquachile.azurianlab.com/api/v1/podcast/episodes/{episode_id}

It follows redirects with a 15-second timeout, accepts JSON or plain text, unwraps a result field, and includes arbitrary episode fields. The prompt labels it as the primary reference for the user's current episode. The endpoint is hardcoded in the fetch helper rather than selected through an environment variable.

Caller profile and login

For caller-specific context, the proxy can first post {"phoneNumber":"+56912345678"} to S2S_LOGIN_BY_PHONE, extract a bearer token, and forward it to subsequent profile/history requests. Profile retrieval uses GET VOCERO_USER_PHONE_AUTH_URL?phoneNumber=... with a 10-second timeout and accepts an object, optionally wrapped in result.

Encode the leading plus sign in page links, for example ?phoneNumber=%2B56912345678. Caller information is also fetched through /api/user/phone for the UI. An available profile can update live browser instructions when profile injection is enabled.

Scheduled reports

S2S_INJECT_REPORTS=false skips report fetching and prompt content, including the table of contents. When enabled, the report endpoint may be called with or without a phone number. The resolver keeps dictionary entries, reads sourceScheduleLabel or sourceSchedule.label, reads date or sourceSchedule.date, and optionally keeps podcastScript in full mode.

Entries are sorted newest first using ISO/date/timestamp handling and an ISO-like string fallback. Empty/unparseable dates sort last. The newest-item limit applies before constructing the prompt block. minimal exposes only the labels and dates; full explicitly opts into script content.

Latest conversation summary

S2S_LATEST_SUMMARY_TEXT takes priority over S2S_LATEST_SUMMARY and needs no phone number or network request. Literal \n sequences in the environment value become newlines. Otherwise the proxy fetches S2S_LATEST_SUMMARY?phoneNumber=... and accepts text or JSON with an optional result wrapper. Both sources pass through the same cap and history wrapper.

Custom RAG

The operator can paste reference material and explicitly apply it to the session. The browser appends it to instructions even with profile injection disabled, includes it in HTTP user_context, and updates an open realtime session. This context does not require an external retrieval endpoint.

Application timing and order

At local WebSocket connect, the server resolves enabled context and stores it in session_ctx. Each client session.update then passes through _patch_client_session_update_with_profile(). Other client frame types are not modified by this helper. The non-MCP relay retains its general assistant-text filtering and forwards audio without a tool-execution pass.

The current augmentation function keeps base instructions first, then appends surviving voice-output guards, date context, episode, profile, reports, and summary blocks. If a block type is already present in the base, deduplication may omit its server candidate. This describes string assembly, not a guarantee of model attention or priority.

Every HTTP reasoning request rebuilds enabled context. Its user_context assembly orders voice guard, date, episode, profile, reports, summary, and browser-provided context, then deduplicates recognized types and strips internal markers. Server instruction augmentation remains separate, so avoid assuming the WebSocket and HTTP prompts have identical ordering.

Context markers support internal deduplication and diagnostics; ordinary profile/report/episode/history sentinels are stripped before final augmentation. MCP uses its separate conversation context and call-marker handling described above. Treat the source helpers as the reference for the exact final payload.

Failure behavior and inspection

Optional context-fetch errors are logged and the affected context is skipped. The speech conversation normally continues without that reference material. This does not mean all API calls ignore errors: missing reasoning configuration, invalid tool arguments and tool authorization can return explicit errors.

Inspect /api/config for active gates, the actual outbound session.update in browser DevTools, and [INJECT-*]/[DEBUG-PROMPT] server logs. Full prompt logging includes caller data and conversation text. See troubleshooting for a step-by-step diagnostic flow.