OpenAI Responses Starter App

repository·main·Indexed 21 days ago

https://github.com/openai/openai-responses-starter-app

A NextJS starter application (v0.1.0) demonstrating the OpenAI Responses API. It features multi-turn conversations, streaming, and tool integration, including built-in tools like Web Search, File Search, and Code Interpreter. The app supports custom function definitions, Model Context Protocol (MCP) server configuration, and first-party Google connectors for Calendar and Gmail via OAuth 2.0.

Tokens
4.1K
Snippets
13
Records
21
Agent score
75%

What's inside openai-responses-starter-app

  1. Configure built-in tools (Web Search, File Search, Code Interpreter)

    main

    The starter app implements several built-in tools that can be configured directly from the UI:

    • Web search: Allows the model to search the internet.
    • File search: Allows the model to access files within a vector store.
    • Code interpreter: Allows the model to run Python code to solve problems.

    To use File search, you must create a new vector store and upload your files (e.g., PDFs) via the UI before enabling the tool.

  2. Set up Google integration (Calendar & Gmail)

    main

    The app uses first-party (1P) connectors to integrate with Google Calendar and Gmail via an OAuth 2.0 flow.

    1. Google Cloud Setup

    • Create an OAuth 2.0 client ID for a Web application in the Google Cloud Console.
    • Set the Redirect URI to: http://localhost:3000/api/google/callback.
    • Enable the Google Calendar API and Gmail API in your project.
    • Configure the following Scopes in the Google Auth Platform:
      • openid
      • email
      • profile
      • https://www.googleapis.com/auth/calendar.events
      • https://www.googleapis.com/auth/gmail.modify

    2. Environment Configuration

    Create a .env.local file at the project root and add your credentials:

    GOOGLE_CLIENT_ID="your-google-client-id"
    GOOGLE_CLIENT_SECRET="your-google-client-secret"
    GOOGLE_REDIRECT_URI="http://localhost:3000/api/google/callback"

    3. Usage

    Click "Connect Google Integration" in the UI. Once connected, the app attaches the Google connectors to the Responses API tools list using your access token.

    # .env.local configuration
    GOOGLE_CLIENT_ID="your-google-client-id"
    GOOGLE_CLIENT_SECRET="your-google-client-secret"
    GOOGLE_REDIRECT_URI="http://localhost:3000/api/google/callback"
  3. Configure MCP servers

    main

    The UI allows you to configure a public Model Context Protocol (MCP) server to use with the Responses API.

    Note on Authentication: If your MCP server requires authentication, you must manually update lib/tools/tools.ts to implement the necessary logic. You can refer to the Google connector integration in the codebase as a pattern for handling access tokens.

  4. Install and run the Responses starter app

    main

    Follow these steps to set up the local development environment for the starter app:

    1. Set up OpenAI API Key: Create a .env file at the project root and add your key:
      OPENAI_API_KEY=<your_api_key>
    2. Clone the repository:
      git clone https://github.com/openai/openai-responses-starter-app.git
    3. Install dependencies:
      npm install
    4. Run the development server:
      npm run dev

    The app will be available at http://localhost:3000.

    # Install dependencies
    npm install
    
    # Run the app
    npm run dev
  5. Manage Google OAuth sessions

    main

    The application stores Google OAuth tokens per session in cookies.

    • To invalidate the session: Clear the app cookies in your browser (e.g., via Chrome DevTools > Application > Storage > Cookies).
    • Token Refresh: If you only clear the gc_access_token cookie, the app will attempt to use the gc_refresh_token to re-authenticate without requiring a full user login flow.
  6. Configure Google Authentication environment variables

    main

    To use Google connectors, you must provide the following environment variables in your project configuration:

    • GOOGLE_CLIENT_ID: Your Google OAuth 2.0 Client ID.
    • GOOGLE_CLIENT_SECRET: Your Google OAuth 2.0 Client Secret.
    • GOOGLE_REDIRECT_URI: The URI where Google will redirect users after authentication. If not provided, it defaults to http://localhost:3000/api/google/callback.
  7. Process and sync conversation state with processMessages()

    main

    processMessages is the primary high-level function for driving the conversation. It orchestrates the handleTurn logic and manages the synchronization between the incoming stream and the application's state stores (useConversationStore and useToolsStore).

    It handles several complex event types to update the UI:

    • Text Streaming: Updates assistantMessageContent and modifies the last MessageItem in real-time using response.output_text.delta.
    • Tool Call Lifecycle:
      • response.output_item.added: Detects when a tool (function, web search, file search, MCP, or code interpreter) is invoked.
      • response.function_call_arguments.delta/done: Streams and parses JSON arguments for function calls.
      • response.mcp_call_arguments.delta/done: Streams and parses JSON arguments for MCP calls.
      • response.code_interpreter_call_code.delta/done: Streams the actual code being executed in the code interpreter.
      • response.output_item.done: Finalizes the tool call status and, for function_call, triggers the local execution via handleTool and initiates a new turn.
    • MCP Specifics: Handles mcp_list_tools and mcp_approval_request when the response is completed.
    • Search Completion: Updates tool status when web_search_call.completed or file_search_call.completed events are received.
  8. Execute a conversation turn with handleTurn()

    main

    handleTurn is a low-level function that performs a POST request to /api/turn_response and processes the streaming response. It handles the SSE (Server-Sent Events) protocol, parsing data: prefixed lines and handling the [DONE] signal.

    Parameters:

    • messages: The current array of conversation items.
    • toolsState: The current state of available tools.
    • onMessage: A callback function invoked for every parsed data chunk received from the stream.

    Note: This function expects the API to return data in a format where each line starts with data: and contains a JSON string.

    await handleTurn(
      allConversationItems,
      toolsState,
      async ({ event, data }) => {
        // Handle specific event types like 'response.output_text.delta'
      }
    );
  9. Handle session IDs with getOrCreateSessionId

    main

    The getOrCreateSessionId function manages the user's session identifier via an HTTP-only cookie named responses_starter_session_id.

    When called:

    1. It checks for an existing session cookie.
    2. If found, it returns the existing ID.
    3. If not found, it generates a new 16-byte random hex string, sets it as an httpOnly, sameSite: 'lax' cookie, and returns it.

    In production environments (NODE_ENV === 'production'), the cookie is automatically marked as secure.

    import { getOrCreateSessionId } from './lib/session';
    
    // This will either return the existing session ID from cookies 
    // or create a new one and set the cookie.
    const sessionId = await getOrCreateSessionId();
  10. Manage OAuth tokens with saveTokenSet and getTokenSet

    main

    The session management system uses an in-memory sessionStore to associate OAuthTokens with a specific sessionId.

    Note: The current implementation uses a Map for in-memory storage, which is intended for demonstration purposes only. For production environments, you must replace this with a persistent session store (e.g., Redis or a database).

    Use saveTokenSet to store tokens for a session and getTokenSet to retrieve them using the session ID.

    import { saveTokenSet, getTokenSet } from './lib/session';
    
    const myTokens = {
      access_token: 'abc-123',
      refresh_token: 'def-456',
      expires_at: 1735689600000
    };
    
    // Save tokens to the session
    saveTokenSet('some-session-id', myTokens);
    
    // Retrieve tokens later
    const tokens = getTokenSet('some-session-id');
    console.log(tokens?.access_token);