Back to roadmaps openai Course

Project: Smart Customer Agent with Database Querying

In this project, we will build a smart AI customer support agent. The agent can answer conversational questions, but when asked about order statuses, it will automatically query our local PostgreSQL database using tool calling.


1. System Interaction Architecture

graph TD
    A[User: Where is my order LS-1002?] --> B[Agent endpoint reads database tools schema]
    B --> C[Model requests call: queryDatabaseForOrder]
    C --> D[Prisma looks up Order details in PostgreSQL]
    D --> E[Model gets DB results: Status shipped]
    E --> F[Agent: Your order LS-1002 was shipped!]

2. Implementing the Smart Agent Endpoint

Create a route endpoint that processes the query and handles database lookup tools:

// app/api/support/agent/route.ts
import { NextResponse } from "next/server";
import { openai } from "../../../../lib/openai";
import { prisma } from "../../../../lib/prisma";
import { ChatCompletionTool } from "openai/resources/chat/completions";

// 1. Declare the database tool schema
const supportTools: ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "queryOrderDetails",
      description: "Lookup shipping and payment details for a specific order number.",
      parameters: {
        type: "object",
        properties: {
          orderNumber: {
            type: "string",
            description: "The unique order identification code (e.g. LS-1025).",
          },
        },
        required: ["orderNumber"],
        additionalProperties: false,
      },
    },
  },
];

// 2. Define the local function that runs on your server
async function queryOrderDetails(orderNumber: string) {
  const order = await prisma.order.findUnique({
    where: { orderNumber },
  });

  if (!order) {
    return JSON.stringify({ error: "Order not found" });
  }

  return JSON.stringify({
    orderNumber: order.orderNumber,
    status: order.status, // e.g. "shipped", "paid"
    amount: order.amount,
  });
}

export async function POST(req: Request) {
  const { userMessage } = await req.json();

  const messages: any[] = [
    { 
      role: "system", 
      content: "You are a customer support agent. Use tools to look up order details when asked. Be friendly." 
    },
    { role: "user", content: userMessage },
  ];

  try {
    // Call completions with support tools registered
    const completion = await openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages,
      tools: supportTools,
    });

    const responseMessage = completion.choices[0].message;
    const toolCalls = responseMessage.tool_calls;

    if (toolCalls) {
      messages.push(responseMessage); // Save assistant message

      for (const toolCall of toolCalls) {
        if (toolCall.function.name === "queryOrderDetails") {
          const args = JSON.parse(toolCall.function.arguments);
          const result = await queryOrderDetails(args.orderNumber);

          messages.push({
            role: "tool",
            tool_call_id: toolCall.id,
            name: "queryOrderDetails",
            content: result,
          });
        }
      }

      // Re-submit results back to OpenAI
      const finalCompletion = await openai.chat.completions.create({
        model: "gpt-4o-mini",
        messages,
      });

      return NextResponse.json({ reply: finalCompletion.choices[0].message.content });
    }

    return NextResponse.json({ reply: responseMessage.content });
  } catch (err: any) {
    return NextResponse.json({ error: err.message }, { status: 500 });
  }
}

3. Frontend Chat Test Action

Call the /api/support/agent endpoint from a chat interface. Ask "What is the status of my order LS-9922?" and confirm that the agent queries the database and gives a correct answer.

Published on Last updated: