Concepts Components Blog Roadmap
Get Started
/ HiA2UI Team

Building a Flight Booking Agent with A2UI

A step-by-step guide to creating a flight booking agent using React, A2UI, and your favorite LLM provider.

The Goal: Build an Agent that doesn’t just say “Here is your flight,” but hands you a ticket you can click.

In this tutorial, we will build a Flight Booking Agent. The user will ask “Find me flights to Tokyo”, and the agent will respond with an interactive ticket component.

Why A2UI?

Before we code, let’s look at the alternative. You could have the agent output Markdown tables. But Markdown can’t have a “Book Now” button that calls your API. A2UI lets you treat UI Components as Vocabulary.

1. Setup

First, initiate a new project and actuate the necessary dependencies. We’ll use Vite for speed.

npm create vite@latest flight-agent -- --template react-ts
cd flight-agent
npm install @a2ui/react @a2ui/core ai

2. The “Vocabulary”: Creating Components

Think of your React components as the words your Agent can speak. Let’s teach it the word “FlightTicket”.

// src/components/FlightTicket.tsx
export const FlightTicket = ({ airline, price, depTime, arrTime }) => (
  <div className="border rounded-xl p-4 shadow-sm hover:shadow-md transition-all">
    <div className="flex justify-between items-center">
      <h3 className="font-bold text-lg">{airline}</h3>
      <span className="text-green-600 font-bold">${price}</span>
    </div>
    <div className="flex gap-4 mt-2 text-gray-600">
      <span>{depTime}</span>
      <span>→</span>
      <span>{arrTime}</span>
    </div>
    <button className="w-full mt-4 bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700">
      Book Now
    </button>
  </div>
);

3. The “Dictionary”: Registering Components

Now, we need to tell the Agent that this component exists. We do this via a Registry. This acts as a whitelist—the Agent can only use components listed here.

// src/registry.ts
import { createRegistry } from '@a2ui/react';
import { FlightTicket } from './components/FlightTicket';

export const flightRegistry = createRegistry({
  components: {
    // The key 'flight-ticket' is what the LLM will output
    'flight-ticket': FlightTicket,
  },
});

4. The “Conversation”: The Agent Loop

Use the <AIOutput /> component to render the stream. This component listens to the ag-ui protocol stream and dynamically mounts your React components.

// src/App.tsx
import { AIOutput } from '@a2ui/react';
import { flightRegistry } from './registry';

// Mocking an LLM response for demonstration
// In a real app, this comes from useChat() or a WebSocket
const mockStream = {
  type: 'flight-ticket',
  props: {
    airline: 'Japan Airlines',
    price: 1200,
    depTime: '10:00',
    arrTime: '14:00 (+1)'
  }
};

function App() {
  return (
    <div className="max-w-md mx-auto py-10 px-4">
      <h1 className="text-2xl font-bold mb-6">Agent Travel</h1>
      <div className="bg-gray-50 p-6 rounded-xl border border-gray-200">
         <p className="mb-4 text-gray-700">Here is the best option I found:</p>
         
         {/* The Magic Happens Here */}
         <AIOutput 
            registry={flightRegistry} 
            data={mockStream} 
         />
      </div>
    </div>
  );
}

5. The “Brain”: System Prompt

Finally, in your backend (Python/Node), instruct the LLM on how to speak this new language.

System Prompt: You are a travel assistant. When finding flights, output JSON with type 'flight-ticket' and properties: airline, price, depTime, arrTime. Do not simply list them in text.

Conclusion

You have just built a Generative UI. The agent “decided” to show a ticket, but YOU controlled exactly how that ticket looks and behaves.

What’s Next?