// The one string that has to be identical in three places at once, so it lives // in exactly one. // // The in-call memory tool works only if the name the ElevenLabs AGENT CONFIG // references (written by the admin registration card) is byte-identical to the // name the CLIENT passes at session start. A mismatch does not fail loudly: EL // substitutes nothing, our endpoint sees an empty bearer, 401s, and the model // speaks a polite "I can't recall that" — a working-looking call with memory // silently off. That failure mode is why this is a shared constant and not a // literal repeated at each site. /** The ElevenLabs dynamic variable carrying the call-scoped credential the * memory webhook tool presents back to us. * * The `secret__` prefix is load-bearing rather than a naming convention: EL * treats that class as header-only and NEVER sends it to the LLM, which is the * property that lets a credential ride a live conversation without ever * entering a prompt. Renaming it without re-running the registration card * breaks recall on every agent already configured. */ export const VOICE_TOOL_VARIABLE = 'secret__pouchy_voice_token'; /** The SAME credential under a NON-secret variable name, passed alongside the * one above and read from an `X-Pouchy-Voice-Token` header. * * WHY A TWIN, 2026-08-12, from four field readings. ElevenLabs invoked the * tool and the Authorization header arrived carrying the literal * `{{secret__pouchy_voice_token}}` — 30 characters, unsubstituted — even * though the client sent the variable in `conversation_initiation_client_data` * and the agent carried a placeholder default. The most economical * explanation is that the `secret__` class exists precisely to stop a CLIENT * from setting it: a browser able to inject arbitrary `secret__*` values would * make the class worthless, so EL ignores client-supplied ones. Our design was * doing the exact thing that class is built to prevent. * * Sending both makes the next call decide it: if the plain twin arrives and * the secret one does not, the hypothesis is confirmed AND recall works in the * same deploy; if neither arrives, the hypothesis is refuted and the prefix was * never the issue. The endpoint records WHICH one authenticated. * * The security delta is small and worth stating plainly: the browser already * holds this credential (it is what passes it), it is call-scoped, read-only, * TTL-bounded and rate-limited per call, and it is referenced ONLY in a tool * header — never in the prompt — so it does not enter the model's context * either way. What `secret__` would have bought is protection against a prompt * reference we do not make. */ export const VOICE_TOOL_VARIABLE_PLAIN = 'pouchy_voice_token'; /** The header the plain twin rides in. Not `Authorization`: two variables in * one header would make "which one substituted" unanswerable, which is the * entire point of sending two. */ export const VOICE_TOOL_HEADER_PLAIN = 'X-Pouchy-Voice-Token'; /** The request-BODY property ElevenLabs fills from the dynamic variable, and * the channel that actually works. * * Two field readings settled it: both variable names reached EL intact (391 * chars, `pvt_`) and BOTH request HEADERS still arrived carrying literals — 30 * and 22 characters of `{{…}}`. EL does not interpolate client-supplied * dynamic variables into webhook request headers under any name. It does fill * a body property whose schema names a `dynamic_variable`, which is its own * documented mechanism and was visible in the tool document all along. * * NOT exported from the package index on purpose. This is server-to-EL * configuration; an integrator never sets it, and adding it to the public * surface would mean a version bump and a CDN rebuild for a string no consumer * can use. It lives here because this file is where the strings that must * match across the client, the endpoint and the tool registration live. */ export const VOICE_TOOL_BODY_FIELD = 'pouchy_voice_token';