fix(voice-call): include intro message in AI context for outbound calls

Fixes #3256

When initiating an outbound call with an intro message (e.g., "Henrik asked
me to call about your mother"), the AI now receives this as explicit context
in its system prompt under "Purpose of this call".

Previously, the intro was played via TTS but the AI didn't understand the
call's objective, leading to generic follow-up questions instead of staying
on topic.

Changes:
- manager.ts: Store callPurpose in metadata at call creation time
- response-generator.ts: Accept callPurpose param and include in system prompt
- webhook.ts: Pass callPurpose to generateVoiceResponse

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
chenglun.hu 2026-01-29 13:17:13 +08:00
parent 34291321b4
commit 1feff5b2b6
No known key found for this signature in database
GPG Key ID: 11ECC6E33B83267C
3 changed files with 24 additions and 3 deletions

View File

@ -132,6 +132,9 @@ export class CallManager {
processedEventIds: [],
metadata: {
...(initialMessage && { initialMessage }),
// Store callPurpose immediately so it's available for AI context
// before speakInitialMessage runs (avoids race with early user speech)
...(initialMessage && { callPurpose: initialMessage }),
mode,
},
};

View File

@ -22,6 +22,8 @@ export type VoiceResponseParams = {
transcript: Array<{ speaker: "user" | "bot"; text: string }>;
/** Latest user message */
userMessage: string;
/** Optional: Purpose of this call (from intro message for outbound calls) */
callPurpose?: string;
};
export type VoiceResponseResult = {
@ -41,8 +43,15 @@ type SessionEntry = {
export async function generateVoiceResponse(
params: VoiceResponseParams,
): Promise<VoiceResponseResult> {
const { voiceConfig, callId, from, transcript, userMessage, coreConfig } =
params;
const {
voiceConfig,
callId,
from,
transcript,
userMessage,
coreConfig,
callPurpose,
} = params;
if (!coreConfig) {
return { text: null, error: "Core config unavailable for voice response" };
@ -116,6 +125,14 @@ export async function generateVoiceResponse(
`You are ${agentName}, a helpful voice assistant on a phone call. Keep responses brief and conversational (1-2 sentences max). Be natural and friendly. The caller's phone number is ${from}. You have access to tools - use them when helpful.`;
let extraSystemPrompt = basePrompt;
// If we have an explicit call purpose (from outbound intro message),
// include it so the AI knows the objective of this call
if (callPurpose) {
extraSystemPrompt += `\n\nPurpose of this call: ${callPurpose}`;
extraSystemPrompt += `\nYou started the call with this message. Stay focused on this topic.`;
}
if (transcript.length > 0) {
const history = transcript
.map(
@ -123,7 +140,7 @@ export async function generateVoiceResponse(
`${entry.speaker === "bot" ? "You" : "Caller"}: ${entry.text}`,
)
.join("\n");
extraSystemPrompt = `${basePrompt}\n\nConversation so far:\n${history}`;
extraSystemPrompt += `\n\nConversation so far:\n${history}`;
}
// Resolve timeout

View File

@ -341,6 +341,7 @@ export class VoiceCallWebhookServer {
from: call.from,
transcript: call.transcript,
userMessage,
callPurpose: call.metadata?.callPurpose as string | undefined,
});
if (result.error) {