cd /news/ai-agents/ai-engineering-for-flutter-developer… · home topics ai-agents article
[ARTICLE · art-113273] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

AI Engineering for Flutter Developers - AI Agents & Workflows in Flutter

A developer demonstrates how to build a multi-agent AI system in Flutter, using a Planning Agent, Generation Agent, and Validation Agent to handle complex tasks. The approach leverages Gemini API with structured output to convert vague user requests into actionable plans and generate code suggestions.

read8 min views1 publishedAug 27, 2026

In the first two articles, we covered the fundamentals and how to build more reliable AI features using structured output, streaming, and proper error handling.

But there's a big limitation with single AI calls: they struggle with complex, multi-step tasks.

That's where AI Agents come in.

Today, we're going to build a simple but powerful multi-agent system in Flutter — specifically, a Planning Agent, a Generation Agent, and a Validation Agent.

By the end of this video, you'll understand how to design agentic workflows and implement them in real Flutter applications.

An AI Agent is more like giving someone a goal and letting them think, plan, and take multiple steps to achieve it, WHILE a regular LLM call is like asking a smart person one question and getting one answer.

We'll focus on a simple and practical multi-agent pattern:

This pattern is extremely useful for real applications.

We'll build a simple Smart Feature Builder,

The user gives a high level request like: 'Create a clean Flutter logins creen with email and password validation.'

Then the system works like this:

The goal of this agent is to take a vague user request and turn it into a clear, structured plan.

  • we define the role and system prompt for the Planning Agent

  • we use structured output so we can get a clean list of steps

  • then we create a Dart model for the plan

  • finally, call the agent and display the result.

import 'dart:convert';
import 'package:googleai_dart/googleai_dart.dart';
import '../models/feature_plan.dart';

/// Stage 1: Planning Agent
/// Takes raw user feature requests and converts them into a structured architectural plan via Gemini API.
class PlanningAgent {
  final String apiKey;
  final String modelName;

  PlanningAgent({
    required this.apiKey,
    this.modelName = 'gemini-3.1-flash-lite',
  });

  static const String _systemInstruction = '''
You are a Senior Flutter Software Architect.
Your role is to take a high-level mobile/web feature request and generate a clean, structured architectural plan.

You must respond ONLY with a valid JSON object matching this exact schema:
{
  "title": "String - Concise title of the feature plan",
  "overview": "String - Executive summary of the architectural strategy",
  "targetPlatform": "String - Target platforms (e.g. Flutter Web, iOS & Android)",
  "componentsToBuild": ["List of String - Individual UI components, widgets, or services to build"],
  "implementationSteps": ["List of String - Sequential step-by-step engineering tasks"],
  "riskConsiderations": ["List of String - Potential state management, security, performance or edge case risks"]
}
''';

  Future<FeaturePlan> planFeature(String prompt) async {
    if (apiKey.isEmpty) {
      throw StateError('Gemini API Key is missing. Please configure your API key before running the pipeline.');
    }

    final config = GoogleAIConfig(authProvider: ApiKeyProvider(apiKey));
    final client = GoogleAIClient(config: config);

    final request = GenerateContentRequest(
      contents: [Content.text('Feature Request:\n$prompt')],
      systemInstruction: Content.text(_systemInstruction),
      generationConfig: const GenerationConfig(
        responseMimeType: 'application/json',
        temperature: 0.2,
      ),
    );

    final response = await client.models.generateContent(
      model: modelName,
      request: request,
    );

    final text = response.text;
    if (text == null || text.trim().isEmpty) {
      throw Exception('Planning Agent returned empty response from Gemini API.');
    }

    final jsonMap = jsonDecode(text) as Map<String, dynamic>;
    return FeaturePlan.fromJson(jsonMap);
  }
}

This agent takes the structured plan and actually produces the output, in our case, Flutter-related code/content suggestions.

  • first, we create the Generation Agent with a clear role

  • then pass the plan from the previous agent

  • generate the final output

  • show how we keep the response structured and useful

import 'dart:convert';
import 'package:googleai_dart/googleai_dart.dart';
import '../models/feature_plan.dart';
import '../models/generated_feature_code.dart';

/// Stage 2: Generation Agent
/// Takes the architectural FeaturePlan and user request, then generates complete, production-ready Flutter code via Gemini API.
class GenerationAgent {
  final String apiKey;
  final String modelName;

  GenerationAgent({
    required this.apiKey,
    this.modelName = 'gemini-3.1-flash-lite',
  });

  static const String _systemInstruction = '''
You are an expert Lead Flutter Engineer.
Your task is to take an Architectural Feature Plan and write production-ready, clean, well-formatted Flutter Dart code.

You must respond ONLY with a valid JSON object matching this exact schema:
{
  "title": "String - Title of the generated feature code",
  "explanation": "String - Clear explanation of key implementation patterns and Dart features used",
  "flutterCode": "String - Complete, fully functioning, syntactically correct Flutter Widget Dart code",
  "dependencies": ["List of String - Required packages in pubspec.yaml (e.g. google_fonts, flutter_animate)"]
}
''';

  Future<GeneratedFeatureCode> generateCode({
    required String userPrompt,
    required FeaturePlan plan,
  }) async {
    if (apiKey.isEmpty) {
      throw StateError('Gemini API Key is missing. Please configure your API key before running the pipeline.');
    }

    final config = GoogleAIConfig(authProvider: ApiKeyProvider(apiKey));
    final client = GoogleAIClient(config: config);

    final promptInput = '''
User Feature Request:
$userPrompt

Architectural Plan:
${plan.toFormattedJson()}
''';

    final request = GenerateContentRequest(
      contents: [Content.text(promptInput)],
      systemInstruction: Content.text(_systemInstruction),
      generationConfig: const GenerationConfig(
        responseMimeType: 'application/json',
        temperature: 0.3,
      ),
    );

    final response = await client.models.generateContent(
      model: modelName,
      request: request,
    );

    final text = response.text;
    if (text == null || text.trim().isEmpty) {
      throw Exception('Generation Agent returned empty response from Gemini API.');
    }

    final jsonMap = jsonDecode(text) as Map<String, dynamic>;
    return GeneratedFeatureCode.fromJson(jsonMap);
  }
}

This agent acts like a reviewer. It checks the output from the Generation Agent for issues, missing pieces, or areas for improvement.

  • again, we create the Validation Agent

  • feed it the original request + the generated output

  • get structured feedback

  • optionally show a simple improvement loop

import 'dart:convert';
import 'package:googleai_dart/googleai_dart.dart';
import '../models/feature_plan.dart';
import '../models/generated_feature_code.dart';
import '../models/validation_report.dart';

/// Stage 3: Validation Agent
/// Reviews generated code against the original user prompt and architectural plan via Gemini API.
class ValidationAgent {
  final String apiKey;
  final String modelName;

  ValidationAgent({
    required this.apiKey,
    this.modelName = 'gemini-3.1-flash-lite',
  });

  static const String _systemInstruction = '''
You are a Lead Code Auditor and Security Reviewer for Flutter applications.
Your job is to audit generated Flutter code against the user request and architectural plan.

You must evaluate code quality, completeness, error handling, accessibility, and performance.
You must respond ONLY with a valid JSON object matching this exact schema:
{
  "qualityScore": 92, // Integer between 0 and 100
  "isPassed": true, // Boolean - true if qualityScore >= 75
  "identifiedIssues": ["List of String - Specific flaws, missing validations, or anti-patterns"],
  "improvementSuggestions": ["List of String - Actionable code quality or performance recommendations"],
  "refinedCodeSnippet": "String or Null - Improved/corrected snippet fixing identified issues"
}
''';

  Future<ValidationReport> validateOutput({
    required String userPrompt,
    required FeaturePlan plan,
    required GeneratedFeatureCode generatedCode,
  }) async {
    if (apiKey.isEmpty) {
      throw StateError('Gemini API Key is missing. Please configure your API key before running the pipeline.');
    }

    final config = GoogleAIConfig(authProvider: ApiKeyProvider(apiKey));
    final client = GoogleAIClient(config: config);

    final promptInput = '''
Original Request:
$userPrompt

Architectural Plan:
${plan.toFormattedJson()}

Generated Code to Audit:
${generatedCode.toFormattedJson()}
''';

    final request = GenerateContentRequest(
      contents: [Content.text(promptInput)],
      systemInstruction: Content.text(_systemInstruction),
      generationConfig: const GenerationConfig(
        responseMimeType: 'application/json',
        temperature: 0.1,
      ),
    );

    final response = await client.models.generateContent(
      model: modelName,
      request: request,
    );

    final text = response.text;
    if (text == null || text.trim().isEmpty) {
      throw Exception('Validation Agent returned empty response from Gemini API.');
    }

    final jsonMap = jsonDecode(text) as Map<String, dynamic>;
    return ValidationReport.fromJson(jsonMap);
  }
}

We need to connect everything into one workflow.

We will create a simple orchestrator that:

  1. Calls the Planning Agent

  2. Passes the plan to the Generation Agent

  3. Sends the result to the Validation Agent

  4. Displays the final output and feedback

/// Orchestrator Service
/// Coordinates the multi-agent pipeline: Planning -> Generation -> Validation
class AgentOrchestrationService extends ValueNotifier<AgentWorkflowState> {

  ...

  Future<void> runWorkflow(String prompt, {required String apiKey}) async {
    if (prompt.trim().isEmpty) return;

    _addLog('Orchestrator', 'Workflow started for prompt: "$prompt"');

    try {
      // -----------------------------------------------------------------------
      // STAGE 1: Planning Agent
      // -----------------------------------------------------------------------
      _addLog('Planning Agent', 'Analyzing request & composing architectural plan...');
      final planningAgent = PlanningAgent(apiKey: apiKey);
      final plan = await planningAgent.planFeature(prompt);

      value = value.copyWith(
        stage: AgentStage.generating,
        plan: plan,
      );
      _addLog('Planning Agent', 'Plan generated successfully: "${plan.title}"', payload: plan.toFormattedJson());

      // -----------------------------------------------------------------------
      // STAGE 2: Generation Agent
      // -----------------------------------------------------------------------
      _addLog('Generation Agent', 'Writing Flutter code & module dependencies...');
      final generationAgent = GenerationAgent(apiKey: apiKey);
      final generatedCode = await generationAgent.generateCode(
        userPrompt: prompt,
        plan: plan,
      );

      value = value.copyWith(
        stage: AgentStage.validating,
        generatedCode: generatedCode,
      );
      _addLog('Generation Agent', 'Code generated successfully (${generatedCode.flutterCode.length} chars)', payload: generatedCode.toFormattedJson());

      // -----------------------------------------------------------------------
      // STAGE 3: Validation Agent
      // -----------------------------------------------------------------------
      _addLog('Validation Agent', 'Auditing code quality, security & accessibility...');
      final validationAgent = ValidationAgent(apiKey: apiKey);
      final validationReport = await validationAgent.validateOutput(
        userPrompt: prompt,
        plan: plan,
        generatedCode: generatedCode,
      );

      _tickerTimer?.cancel();

      value = value.copyWith(
        stage: AgentStage.completed,
        validationReport: validationReport,
      );
      _addLog('Validation Agent', 'Audit complete. Quality Score: ${validationReport.qualityScore}/100 (Passed: ${validationReport.isPassed})', payload: validationReport.toFormattedJson());
      _addLog('Orchestrator', 'Multi-Agent pipeline executed successfully!');
    } catch (e) {
      _tickerTimer?.cancel();
      _addLog('Orchestrator', 'Pipeline failed: $e');
      value = value.copyWith(
        stage: AgentStage.failed,
        error: e,
      );
    }
  }
}

The full source code is on GitHub: github.com/techwithsam/ai_engineer_for_flutter_devs/tree/video-3

Quick summary of what we covered:

This is a foundational pattern you can expand in many directions.

If you haven't already, download the free AI Engineering Starter Pack - I've updated it with the code and patterns from this article.

Here: techwithsam.dev/ai-starter-kit-3

Just enter your email, and it will be sent to you instantly.

In the next and final video of this series, we'll focus on Production AI Engineering - covering performance, privacy, security, evaluation, and best practices for shipping AI features in real Flutter apps.

If you found this valuable, please like and drop a comment.

I'd love to know: What kind of multi-agent workflow would you like to see next?

Thank you for following. I'll see you in the final one.

Take care!

── more in #ai-agents 4 stories · sorted by recency
── more on @flutter 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/ai-engineering-for-f…] indexed:0 read:8min 2026-08-27 ·