Back to Articles

Building RAG Chat with Exa's Web Search API and OpenAI o3-mini

[ View on GitHub ]

Building RAG Chat with Exa’s Web Search API and OpenAI o3-mini

Hook

Most RAG implementations throw everything at an LLM and hope for the best. This open-source template shows how deliberately separating search from reasoning—using Exa for retrieval and OpenAI’s o3-mini for generation—creates a cleaner approach to building search-augmented chat.

Context

The challenge with building conversational AI isn’t just getting a language model to respond—it’s ensuring those responses reflect current, accurate information from the web. Traditional chatbots are frozen in time, limited by their training data cutoffs. The retrieval-augmented generation (RAG) pattern emerged as the solution: retrieve relevant information first, then generate responses grounded in that context.

Exa & o3-mini Chat App is an open-source starter template from Exa Labs that demonstrates this pattern: it pairs Exa’s web search API (which the team describes as designed specifically for AI applications) with OpenAI’s o3-mini model. Rather than being yet another ChatGPT clone, this project serves as a reference implementation for developers who want to build search-augmented applications with modern Next.js architecture. With 43 GitHub stars, it provides a well-structured starting point for the increasingly common problem of giving LLMs access to current web information.

Technical Insight

The architecture follows Next.js 14’s App Router pattern, orchestrating two distinct API calls in sequence. When a user submits a query, the application first hits Exa’s search endpoint to retrieve relevant web content, then passes both the original query and the search results as context to OpenAI’s o3-mini model. The Vercel AI SDK handles the streaming response infrastructure, eliminating the boilerplate typically required for managing LLM interactions.

What makes this implementation interesting is the deliberate separation of concerns. Exa positions itself as a “web search API designed for AI,” meaning its API is built to provide search results optimized for LLM consumption. According to the README, Exa provides real-time web search capabilities and comprehensive results that integrate seamlessly with language models—fundamentally different from scraping traditional search engines or parsing HTML.

The frontend leverages the Vercel AI SDK’s useChat hook, which abstracts away the complexity of streaming responses and managing conversation state. Here’s the typical flow based on the Vercel AI SDK patterns:

// Simplified conceptual flow (based on Vercel AI SDK patterns)
import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: '/api/chat',
  });

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>
          {m.role}: {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
      </form>
    </div>
  );
}

On the backend, the /api/chat route would implement a pattern where it first queries Exa, then constructs a prompt for o3-mini that includes the search results as context for generating the final response.

The deployment target is Vercel’s edge infrastructure, which means the API routes run close to users globally rather than on a single server. This matters for an application making sequential external API calls—network latency compounds when you’re chaining Exa → o3-mini → streaming response. Edge deployment helps mitigate some of this, though you’re still bounded by the third-party API response times.

The project uses TailwindCSS for styling, which aligns with the modern Next.js ecosystem’s preference for utility-first CSS. TypeScript provides type safety across the full stack, particularly valuable when dealing with the structured responses from both Exa and OpenAI APIs. The codebase represents a clean example of contemporary React patterns: server components where possible, client components only where interactivity demands it, and API routes handling the sensitive work of managing API keys and external service communication.

Gotcha

The most significant limitation is the dual API dependency. This isn’t just about needing two API keys—it’s about potential costs, rate limits, and architectural coupling. Every conversation requires at least one Exa search call plus an o3-mini API call. For a prototype or personal project, this is manageable, but for a production application with many users, you’ll need careful cost modeling and potentially aggressive caching strategies that aren’t implemented in this starter template.

There’s no conversation history persistence mentioned in the documentation. The chat interface works during a session, but refresh the page and your conversation likely disappears. For a production application, you’d need to implement database storage, user authentication, and conversation management—none of which are included. This is explicitly described as a “simple chat experience which you can clone and build upon,” not a complete solution. The project also lacks any form of user management, rate limiting, or abuse prevention. Anyone with access to your deployed instance could potentially burn through your API quotas. You’d need to add authentication layers, implement server-side rate limiting, and potentially add moderation filters before exposing this publicly.

As a relatively focused starter template, you shouldn’t expect extensive documentation beyond what’s provided, extensive community troubleshooting resources, or a plugin ecosystem. The README provides installation steps and API key setup, but doesn’t explain detailed architectural decisions, customization patterns, or best practices for extending the functionality beyond the core template.

Verdict

Use if: You’re building a proof-of-concept for search-augmented chat and want a clean, modern Next.js foundation that handles the streaming UI and API orchestration correctly out of the box. The template particularly shines if you’re already evaluating Exa’s search API or want to work with OpenAI’s o3-mini model for chat applications. It’s also valuable as a learning resource—the codebase demonstrates current best practices for Vercel AI SDK integration and Next.js 14 App Router patterns without unnecessary abstraction layers obscuring the core concepts.

Skip if: You need production features like user authentication, conversation persistence, or built-in cost controls. The dual API dependency means you’ll need to manage two services and their associated costs, and you’d spend significant time building the infrastructure around the core chat functionality. Also skip if you want a single, unified API—some providers offer integrated search-augmented chat without managing two separate services. Finally, if you’re not specifically invested in Exa’s search approach, you’d have more flexibility with frameworks like LangChain that support multiple search providers and offer more extensive tooling ecosystems.

// QUOTABLE

Most RAG implementations throw everything at an LLM and hope for the best. This open-source template shows how deliberately separating search from reasoning—using Exa for retrieval and OpenAI's o3-...

[ Tweet This ]
// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/exa-labs-exa-o3mini-chat.svg)](https://starlog.is/api/badge-click/developer-tools/exa-labs-exa-o3mini-chat)