Authentication
Credentials travel in the first message, hello, and never in the connection URL, where proxies and logs would record them.
Client
Section titled “Client”connect(url, { auth: () => fetch('/api/voice-token').then((r) => r.text()), // called on every connect and reconnect context: { docId },});auth is a string or a function. A function is called again on each reconnect, so short-lived tokens rotate. If it throws, the connection fails with AUTH_FAILED. After UNAUTHORIZED from the server, a client with a fixed token stops reconnecting; one with a token function tries again with a fresh token.
Server
Section titled “Server”serve(agent, { authenticate: async ({ token, context, sessionId, headers }) => { const user = await verifyToken(token); // your own verification if (!user || !(await user.canEdit(context.docId))) return undefined; return { id: user.id, docId: context.docId }; }, configure: (principal, { context }) => ({ instructions: `You edit the document ${principal.docId} for ${principal.id}.`, }),});authenticateruns for everyhello, new or resuming. Return a principal (an object with anid) to accept the connection. Return nothing,false, or throw to refuse it: the client receivesUNAUTHORIZEDand the connection closes with code 4401. Withoutauthenticate, every connection is accepted.configurereturns a partial session config for new sessions, from the principal andhello.context: instructions, voice, turn detection, a recognition vocabulary.headersare those of the upgrade request, when the runtime has them, for cookies or the origin.
Using the principal
Section titled “Using the principal”The principal reaches your code wherever decisions are made:
const exportDocument = tool({ description: 'Export the open document as PDF.', parameters: { type: 'object' }, risk: 'medium', run: async (_args, { data: principal }) => exporter.exportFor(principal.id, principal.docId),});
hooks: { beforeToolCall: (call) => (call.data.readOnly && call.name !== 'read_document' ? { action: 'reject', message: 'Read-only access.' } : undefined),}Resuming
Section titled “Resuming”A session belongs to the principal that opened it. A resume by any other principal fails exactly like a resume of an unknown session (RESUME_FAILED), so the answer never reveals whether a session exists.