Skip to content

Add onFunctionCall callback for client-side function calling #11

@davidrmcgee

Description

@davidrmcgee

Feature Request

Add an onFunctionCall callback prop to the DeepgramVoiceInteraction component to handle client-side function calls in a more React-friendly way.

Problem

Currently, to handle client-side function calls (when client_side: true is set in function definitions), developers must intercept WebSocket messages manually:

// Current workaround - intercepting WebSocket messages
window.WebSocket = class extends WebSocket {
  constructor(url: string | URL, protocols?: string | string[]) {
    super(url, protocols);
    this.addEventListener('message', (event) => {
      const message = JSON.parse(event.data);
      if (message.type === 'FunctionCallRequest') {
        // Handle function call manually
      }
    });
  }
};

This approach:

  • Requires wrapping the WebSocket class
  • Is error-prone and fragile
  • Doesn't align with React's declarative patterns
  • Makes testing more difficult

Proposed Solution

Add an onFunctionCall callback prop that mirrors the pattern of existing callbacks like onAgentUtterance, onUserMessage, etc.

interface DeepgramVoiceInteractionProps {
  // ... existing props
  onFunctionCall?: (request: FunctionCallRequest) => Promise<FunctionCallResponse> | FunctionCallResponse;
}

interface FunctionCallRequest {
  id: string;
  name: string;
  arguments: string | object; // JSON string or parsed object
}

interface FunctionCallResponse {
  id: string;
  name: string;
  content: string; // JSON stringified result
}

Use Case

When a function is defined with client_side: true, Deepgram sends a FunctionCallRequest message. The component should:

  1. Call onFunctionCall with the request
  2. Wait for the promise to resolve (or use the synchronous return)
  3. Send a FunctionCallResponse back to Deepgram automatically

Example usage:

<DeepgramVoiceInteraction
  apiKey={apiKey}
  agentOptions={{
    functions: [{
      name: 'search_products',
      client_side: true,
      // ... function definition
    }]
  }}
  onFunctionCall={async (request) => {
    if (request.name === 'search_products') {
      const params = typeof request.arguments === 'string' 
        ? JSON.parse(request.arguments) 
        : request.arguments;
      
      const result = await searchProducts(params);
      
      return {
        id: request.id,
        name: request.name,
        content: JSON.stringify(result)
      };
    }
  }}
/>

Benefits

  • React-friendly: Follows the same pattern as other component callbacks
  • Type-safe: Can be properly typed with TypeScript
  • Testable: Easy to mock in tests
  • Cleaner code: No need to intercept WebSocket messages
  • Consistent API: Matches the design of onAgentUtterance, onUserMessage, etc.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions