Ortem Technologies
    Mobile Development

    GenUI in FlutterFlow 2026: How AI Agents Now Compose Your App's UI in Real Time

    Praveen JhaMay 15, 202613 min read
    GenUI in FlutterFlow 2026: How AI Agents Now Compose Your App's UI in Real Time
    Quick Answer

    GenUI is Google's open-source SDK for Flutter that enables AI agents to compose user interfaces dynamically at runtime. Instead of showing a chat text response, the AI agent assembles actual UI components — product cards, booking tiles, dashboards — from your app's existing widget catalog, in response to what the user needs. FlutterFlow implements GenUI as "GenUI Chat," allowing FlutterFlow apps to deliver agent-driven experiences where the UI adapts in real time to user intent. The underlying protocol is A2UI (Agent-to-UI), an open project by Google defining declarative UI communication between agents and frontends.

    Commercial Expertise

    Need help with Mobile Development?

    Ortem deploys dedicated Enterprise Mobile Solutions squads in 72 hours.

    Build Your App Team

    Next Best Reads

    Continue your research on Mobile Development

    These links are chosen to move readers from general education into service understanding, proof, and buying-context pages.

    Every UI you have ever built makes the same assumption: you know in advance what the user will need.

    You design screens for the expected user journeys. You build forms for the expected inputs. You create navigation for the expected flows. The UI is a static prediction of what users will want.

    GenUI breaks this assumption. The AI agent observes what the user is trying to accomplish — and assembles the appropriate UI at runtime, from your existing widget catalog, in response to the user's actual intent.

    The Core Concept: From Text to UI

    The evolution of AI in apps:

    Gen 1: AI returns text
    User: "Show available rooms for next weekend"
    AI: "We have Room 101 available at $120/night and Room 205 at $150/night..."
    
    Gen 2: AI returns structured data (JSON)
    User: "Show available rooms for next weekend"
    AI returns: { rooms: [{id: 101, price: 120, ...}, {id: 205, ...}] }
    App renders: a list view using hardcoded template
    
    Gen 3 (GenUI): AI returns UI specification
    User: "Show available rooms for next weekend"
    AI returns A2UI JSON: {
      type: "RoomGrid",
      items: [{widget: "RoomCard", id: 101, price: 120, features: [...], cta: "Book Now"}],
      layout: "grid_2col",
      filter_widget: "PriceRangeSlider"
    }
    App renders: actual RoomCard widgets + PriceRangeSlider, all interactive
    

    In Gen 3, the agent does not just answer — it builds the interface. The user gets functional UI components, not a text description of what the UI would show.

    How GenUI Works Technically

    GenUI uses a three-layer architecture:

    Layer 1: Widget Catalog Registration

    You register your app's components with the GenUI SDK — defining what widgets exist and what data they accept:

    // Register your widget catalog with GenUI
    final catalog = GenUIWidgetCatalog(
      widgets: [
        WidgetSpec(
          name: "ProductCard",
          description: "Displays a product with image, name, price, and add-to-cart button",
          schema: {
            "product_id": SchemaField.string(required: true),
            "name": SchemaField.string(required: true),
            "price": SchemaField.number(required: true),
            "image_url": SchemaField.string(),
            "rating": SchemaField.number(min: 0, max: 5),
            "in_stock": SchemaField.boolean(defaultValue: true),
          },
          builder: (data, onAction) => ProductCard(
            productId: data["product_id"],
            name: data["name"],
            price: data["price"],
            imageUrl: data["image_url"],
            rating: data["rating"],
            onAddToCart: () => onAction("add_to_cart", {"product_id": data["product_id"]}),
          ),
        ),
        WidgetSpec(
          name: "BookingCalendar",
          description: "Interactive calendar for selecting available appointment slots",
          schema: {
            "available_dates": SchemaField.array(SchemaField.string()),
            "time_slots": SchemaField.array(SchemaField.string()),
            "service_type": SchemaField.string(),
          },
          builder: (data, onAction) => BookingCalendar(
            availableDates: data["available_dates"],
            timeSlots: data["time_slots"],
            onSlotSelected: (date, time) => onAction("slot_selected", {
              "date": date, "time": time
            }),
          ),
        ),
        // ... more widgets
      ],
    );
    

    Layer 2: Agent-to-UI Communication

    When the user sends input, GenUI sends it to the LLM along with the widget catalog schema. The LLM responds with A2UI JSON — a specification of which widgets to render with what data:

    {
      "ui_response": {
        "message": "I found 3 available slots for your haircut appointment this week:",
        "components": [
          {
            "widget": "BookingCalendar",
            "data": {
              "available_dates": ["2026-05-19", "2026-05-20", "2026-05-22"],
              "time_slots": ["10:00 AM", "2:00 PM", "4:30 PM"],
              "service_type": "haircut"
            }
          },
          {
            "widget": "ServiceInfoCard",
            "data": {
              "service": "Classic Haircut",
              "duration": "45 minutes",
              "price": 35
            }
          }
        ]
      }
    }
    

    Layer 3: State Feedback Loop

    When the user interacts with the rendered widget (selects a time slot, clicks Add to Cart, fills a form), the action is fed back to the agent:

    // GenUI automatically feeds user actions back to the agent
    GenUIChat(
      catalog: catalog,
      model: FirebaseAI.googleAI().generativeModel("gemini-2.5-flash"),
      onAction: (actionType, actionData, conversation) {
        // "slot_selected" action fires when user picks a booking time
        // GenUI automatically includes this in the next agent context
        // The agent knows what the user selected and responds appropriately
      },
    )
    

    The agent maintains context of the entire interaction — what UI it showed, what the user clicked, what data was displayed. The next user input continues a stateful conversation where the agent knows exactly where you are in the flow.

    FlutterFlow's GenUI Chat

    For FlutterFlow developers, GenUI Chat is available without writing the SDK integration manually:

    1. Enable GenUI Chat in the FlutterFlow widget library
    2. Define your widget catalog — select which FlutterFlow components the agent can use (you pick from your existing component library)
    3. Connect AI model — select Firebase AI Logic + Gemini (zero configuration) or configure a custom LLM endpoint
    4. Configure the agent's system prompt — define the agent's role, what it can do, what widgets to use for different scenarios

    FlutterFlow generates the widget catalog schema automatically from your component library — you do not need to write JSON schemas by hand.

    Real Use Cases in Production

    E-Commerce: Dynamic Product Discovery

    Instead of fixed category pages, the agent assembles product grids based on natural language queries. "Show me running shoes under $100 for wide feet" → agent renders a filtered ProductGrid with PriceRangeSlider and FootWidthFilter widgets, with results pre-filtered to the user's criteria.

    Healthcare: Personalized Patient Dashboards

    Instead of one-size-fits-all health dashboards, the agent assembles relevant widgets based on each patient's conditions, medications, and upcoming appointments. A diabetic patient's dashboard shows GlucoseTracker and MealLogger. A cardiac patient's shows HeartRateCard and MedicationSchedule. For regulated environments, this requires HIPAA-compliant development practices throughout the agent and data layers.

    B2B SaaS: Adaptive Analytics

    Instead of fixed dashboard layouts, the agent assembles the metrics most relevant to each user's role and current goals. The sales VP sees pipeline and quota attainment. The account manager sees their book of business and renewal risk. This adaptive approach is core to modern SaaS development where personalization drives retention.

    Travel Apps: Conversational Booking

    "I want a beach vacation in Southeast Asia, first week of July, family of 4, ~$3,000 budget" → agent assembles FlightSearchResults + HotelGrid + ItineraryBuilder, pre-filtered and pre-populated with the user's constraints.

    What This Changes for Flutter Developers

    GenUI shifts the Flutter developer's role:

    Before GenUI: You design every possible screen, every state, every user flow — and hope you predicted what users would need.

    With GenUI: You build a rich widget catalog — high-quality, composable components. The agent decides which widgets to assemble for each user's specific situation. You focus on making great widgets; the AI focuses on assembling them correctly. This shifts Flutter development from predicting flows to building vocabularies of reusable components.

    The implication: the UI layer becomes a vocabulary of components, and the agent is the grammar that arranges them. Apps that implement GenUI can handle user intents that were never explicitly designed for, because the agent can assemble novel combinations of existing widgets.

    Technical Reference: Events, dispatchAction and Direct Mode

    This is the part of GenUI that is hardest to find written down anywhere. FlutterFlow's own App Event Integration documentation never names dispatchAction, and the phrase most developers search for — "direct mode" — does not appear in the official docs at all. Here is the vocabulary reconciled against what the framework actually does.

    The two integration modes, and what they are really called

    When a FlutterFlow app event reaches GenUI, exactly one of two things happens, controlled by a single auto_respond flag.

    auto_respond: false — context injection. The event message is added to a pending queue. Nothing happens immediately. The queue is flushed into the conversation just before the next user message is sent, so the agent sees the event as background context when it next responds. Use this for ambient state: a filter changed, a scroll position, an item added to a cart — cases where you want the agent aware but not talking.

    auto_respond: true — proactive response. This is what developers mean when they say direct mode. The event message is sent directly into the conversation as an InternalMessage and inference starts immediately. The model may respond with text, with UI, with both, or with nothing visible at all, depending on your prompt and the surrounding context. Use it when the event should visibly cause something: a payment completed, an upload finished, a device disconnected.

    That silent-response case surprises people. A proactive event that produces no visible output is normal behaviour, not a failure — and it is why direct mode feels unreliable until you understand it.

    The pending context queue has a hard limit

    The pending queue holds 50 messages. On overflow the oldest is dropped, silently. In a chatty app that fires events on every interaction, an event from early in a session can vanish before it is ever flushed — which surfaces as an agent that appears to have forgotten something the user definitely did.

    If event ordering matters to your feature, do not rely on the queue to hold a long tail of context. Either fire fewer, richer events, or promote the important ones to auto_respond: true so they enter the conversation immediately.

    The event path, end to end

    When a user interacts with a widget, the flow is:

    1. The widget implementation dispatches a UiEvent.
    2. The framework attaches context — the surfaceId identifying which GenUI surface raised it, plus relevant data-model values.
    3. The enriched event is routed to the model through the ContentGenerator.

    surfaceId is the piece worth internalising. A single screen can host several GenUI surfaces, and without it the agent has no way to tell which one an interaction came from. If your agent responds to the right event on the wrong surface, that is where to look first.

    Structured payloads and toMap()

    Event payload data is appended automatically by GenUI, and structured payloads are serialised by calling toMap() on the payload object. If your custom data class does not implement toMap(), the agent receives nothing useful from it — the event still fires, and the model simply has no visibility into what your object contained. This is the most common cause of "the agent ignored my event."

    FlutterFlow GenUI and the Flutter GenUI SDK are two different things

    These are constantly conflated, including in search results:

    • FlutterFlow GenUI / GenUI Chat — documented at docs.flutterflow.io, configured visually inside FlutterFlow, and what you get when you enable GenUI on a FlutterFlow project.
    • The Flutter GenUI SDK — documented at docs.flutter.dev/ai/genui, a package you use in hand-written Flutter code, with its own component model.

    Both run on Firebase AI Logic with Gemini underneath, which is why the concepts rhyme. The APIs do not. Confirm which surface a code sample targets before adapting it — a snippet from one will not drop into the other.

    Quick reference

    What you are trying to doWhat to reach for
    Agent should know, but not speakauto_respond: false (context injection)
    Event should trigger a response nowauto_respond: true (direct mode)
    Identify which surface fired an eventsurfaceId on the UiEvent
    Send your own structured dataImplement toMap() on the payload
    Agent "forgot" an earlier event50-message pending queue overflow
    Agent replied to the wrong surfaceWrong or missing surfaceId

    Ortem Technologies builds Flutter and FlutterFlow applications with GenUI integration — creating adaptive, agent-driven experiences for healthcare, fintech, and enterprise clients. Explore our Flutter development services → | Cross-platform app development → | AI agent development → | Talk to our mobile team →

    About Ortem Technologies

    Ortem Technologies is a premier custom software, mobile app, and AI development company. We serve enterprise and startup clients across the USA, UK, Australia, Canada, and the Middle East. Our cross-industry expertise spans fintech, healthcare, and logistics, enabling us to deliver scalable, secure, and innovative digital solutions worldwide.

    📬

    Get the Ortem Tech Digest

    Monthly insights on AI, mobile, and software strategy - straight to your inbox. No spam, ever.

    GenUI FlutterFlutterFlow GenUIagent-driven UIA2UI protocolFlutter AI 2026generative UI FlutterFlutterFlow 2026AI app UI generation

    Sources & References

    1. 1.GenUI SDK for Flutter - Flutter.dev
    2. 2.Rich and Dynamic UIs with Flutter and GenUI - Flutter Blog
    3. 3.GenUI Chat in FlutterFlow - FlutterFlow Docs
    4. 4.GenUI + Firebase AI in Flutter 2026 - Flutter Fever

    About the Author

    P
    Praveen Jha

    Director – AI Product Strategy, Development, Sales & Business Development, Ortem Technologies

    Praveen Jha is the Director of AI Product Strategy, Development, Sales & Business Development at Ortem Technologies. With deep expertise in technology consulting and enterprise sales, he helps businesses identify the right digital transformation strategies - from mobile and AI solutions to cloud-native platforms. He writes about technology adoption, business growth, and building software partnerships that deliver real ROI.

    Business DevelopmentTechnology ConsultingDigital Transformation
    LinkedIn

    Frequently Asked Questions

    Stay Ahead

    Get engineering insights in your inbox

    Practical guides on software development, AI, and cloud. No fluff — published when it's worth your time.

    Ready to Start Your Project?

    Let Ortem Technologies help you build innovative software solutions for your business.