6 Crucial Updates in Flutter's GenUI and A2UI Protocol You Must Know
Generative UI (GenUI) is revolutionizing how Flutter apps create dynamic, interactive user interfaces—where an agent not only generates content but also decides how to display and interact with it. At its heart lies A2UI, an open protocol that orchestrates collaboration between agents and renderers. The Flutter team's genui package leverages A2UI to connect agents with a widget catalog and present the resulting UI to users. Both genui and the A2UI protocol have just received major updates, shifting from a structured-output-first philosophy to a more flexible, prompt-first approach. This article breaks down the six essential changes you need to know, whether you're migrating an existing app or building a new one.
1. Shift from Structured Output to Prompt-First Design
The most fundamental change in genui v0.9 is its departure from the old "Structured Output First" model. Previously, A2UI messages were streamed through structured output APIs, tightly coupling the framework to specific response formats. Now, agents include blocks of JSON as plain text within their responses, a method known as "Prompt First." This gives you greater flexibility to craft prompts without being constrained by rigid API schemas. The result? Simpler integration with any LLM, easier debugging, and the ability to harness advanced prompting techniques like chain-of-thought. Developers can now directly inject the A2UI specification into the prompt, allowing the agent to decide when and how to format UI instructions. This shift also means the genui package no longer imposes a fixed communication protocol—adapt it to your unique use case.
2. Architecture Decoupling: Three New Layers Replace ContentGenerator
In previous versions, genui relied on a monolithic ContentGenerator class that handled prompt construction, LLM calls, and response parsing. The latest update removes ContentGenerator entirely, introducing a three-layer decoupled architecture. The Engine (via SurfaceController) manages UI state and rendering. The Transport layer (A2uiTransportAdapter) handles message streaming between agent and renderer. The Facade (Conversation) provides a high-level API for chat state management. This separation empowers you to take direct control over chat history, retry logic, and error handling. You are no longer forced to go through a common API to customize interactions; instead, you wire up each layer independently, giving you fine-grained control over how your application communicates with a Large Language Model.
3. Removal of Provider-Specific Wrapper Packages
With the death of ContentGenerator, the specialized wrapper packages that once simplified integration with specific LLM providers are no longer needed. Names like genui_dartantic, genui_google_generative_ai, and genui_firebase_ai have vanished from the dependency tree. This cleanup means you can now connect to any model—OpenAI, Anthropic, Google, or a local LLM—without pulling in extra packages. The genui framework no longer makes assumptions about your provider; it simply provides the transport adapters and surface controller. You write your own code to call the LLM, format the prompt, and handle responses. This reduction in boilerplate not only simplifies your pubspec.yaml but also eliminates version conflicts and reduces the learning curve for new team members.
4. New Way to Wire Up Agent Connections
Previously, you instantiated a ContentGenerator and passed it to your SurfaceController. Now, you are responsible for setting up the connection to your agent yourself. The old code looked like this:
final generator = FirebaseAiContentGenerator();
final controller = SurfaceController(generator: generator);
In the updated paradigm, you create a TransportAdapter that communicates with your LLM, then wire it into the Conversation facade. Here's a simplified example:
final transport = MyCustomTransportAdapter(client: myHttpClient);
final conversation = Conversation(transport: transport);
final controller = SurfaceController(conversation: conversation);
This change gives you the freedom to add custom retry logic, stream tokens for real-time updates, or even multiplex multiple agents. The Conversation facade manages chat history automatically, but you can override storage or add your own caching. It's a more explicit but ultimately more flexible setup that scales with your application's complexity.
5. Direct Control Over LLM Configuration and Functions
Because the framework no longer wraps your agent, you can now tweak every aspect of the LLM interaction without circumventing genui's APIs. Want to adjust temperature, top-p, or max tokens? Simply set those parameters when you instantiate your model client. Need to add custom tools or function-calling capabilities? Do it in your transport layer. The genui v0.9 update intentionally stays out of your way, letting you use the LLM provider's native SDK for fine-tuning. This is especially valuable for production apps that require precise generation settings, rate limiting, or integration with Retrieval-Augmented Generation (RAG) pipelines. You maintain full ownership of the prompting strategy, including how A2UI JSON blocks are embedded and extracted from the model's text output.
6. Migration Steps from v0.7.0 to v0.9.0
If you are upgrading an existing app, follow these high-level guidelines. First, remove any dependencies on provider-specific genui wrapper packages (e.g., genui_firebase_ai). Second, replace your ContentGenerator instantiation with a custom TransportAdapter implementation that formats prompts with A2UI specifications and parses the JSON from the LLM's text response. Third, wrap your transport in a Conversation object and pass it to SurfaceController. Fourth, adjust your chat loop to use the new facade methods—send a user message via conversation.sendMessage() and listen for state updates from the controller. Finally, test with a simple widget to ensure the agent correctly renders the generated UI. For a detailed code walkthrough, refer to the official migration guide in the Flutter documentation.
These six updates mark a significant evolution in Flutter's generative UI toolkit. By embracing a prompt-first approach and decoupling the architecture, the genui package now offers unparalleled flexibility while retaining the core power of A2UI. Whether you're prototyping a conversational interface or building a production-grade adaptive UI system, these changes empower you to create smarter, more responsive applications. Upgrade today and take full control of your AI-driven user experiences.
Related Articles
- Kubernetes v1.36: 5 Key Insights into Declarative Validation's GA Release
- 10 Game-Changing Features of GitHub’s New Copilot Desktop App
- Revolutionary 26M Parameter Model Needle Brings Tool Calling to Consumer Devices
- Your Guide to Publishing on the Python Insider Blog (New Home)
- Mastering Qt Designer with Python for Rapid GUI Development
- Understanding Code: Its Dual Role and Future with AI
- Supply Chain Attacks Now Target Developer Secrets: Three Major Campaigns in 48 Hours
- Stack Overflow's 2008 Launch Revolutionized Developer Collaboration Overnight, Experts Say