FlutterFever Studio
Back to packages

Flutter Agent Harness package guide

A cross‑platform AI agent harness for Flutter and Dart with streaming adapters, tool integration, and session persistence.

Install command
Copy and run in your Flutter project
flutter pub add flutter_agent_harness

When to use Flutter Agent Harness

Flutter Agent Harness is a lightweight yet powerful library that brings autonomous AI agents directly into your Flutter applications. By abstracting the complexities of LLM interaction, streaming responses, tool execution, and session management, the package lets developers focus on the user experience instead of the plumbing. It ships with a set of provider‑style adapters that can be dropped into Provider, Riverpod, Bloc, or any other state‑management solution, making it a natural fit for existing codebases. The core loop handles request/response cycles, supports incremental streaming for chat‑like interfaces, and can invoke custom tools—such as database lookups or external API calls—without breaking the reactive flow.

When to use Flutter Agent Harness? If your app needs to embed conversational AI, generate code snippets, provide contextual assistance, or orchestrate multi‑step workflows powered by a language model, this package gives you a ready‑made harness. It shines in scenarios where you need persistent sessions across app restarts, such as personal assistants, tutoring apps, or collaborative editors. The built‑in context compaction algorithm automatically trims older messages while preserving essential information, preventing token overflow and keeping costs predictable.

Architecturally, the harness sits between your UI layer and the LLM service. It can be instantiated as a singleton, injected via a Provider, or managed by a Bloc/Cubit. Because it does not prescribe a UI framework, you can pair it with Flutter's declarative widgets, Compose‑style UI, or even a pure Dart console app. The package respects the unidirectional data flow pattern: UI dispatches intents, the harness processes them, streams results back, and the UI rebuilds accordingly. This separation keeps your business logic testable and your UI responsive.

Getting started is straightforward. After adding the dependency, you create an `AgentController` with your chosen LLM endpoint and optional tool callbacks. The controller exposes a `Stream<String>` that emits partial responses, ideal for building type‑ahead chat bubbles. You can also persist the conversation state using the built‑in `SessionStore`, which writes to shared preferences on mobile and local storage on web/desktop. For production use, consider configuring retry policies, rate‑limit handling, and secure storage of API keys. The package deliberately avoids hard‑coded credentials, encouraging developers to inject secrets via environment variables or secure keystore solutions.

For beginners, a minimal example involves initializing the harness with an OpenAI API key, wiring it to a `StreamBuilder`, and sending user messages through a simple text field. The harness will stream the assistant’s reply character by character, giving the impression of a live conversation. More advanced use cases include chaining tools—like a weather lookup followed by a recommendation engine—or persisting sessions across devices using a cloud backend. The flexibility of the adapter system means you can swap the streaming implementation, add caching layers, or integrate with custom authentication flows without rewriting the core agent logic.

In production, keep an eye on token usage and latency. While the context compaction feature helps, you should still monitor the size of persisted sessions and prune them according to your cost model. The harness also provides hooks for logging and error handling, allowing you to surface meaningful messages to users when the LLM service is unavailable. Finally, because the library is pure Dart, it works seamlessly on iOS, Android, web, macOS, Windows, and Linux, making it a truly cross‑platform solution for AI‑driven Flutter apps.

chat assistants
code generation tools
context‑aware tutoring
dynamic content creation
multi‑step workflow orchestration

Pros

  • cross‑platform
  • streaming UI updates
  • built‑in session storage
  • tool‑callback extensibility
  • compatible with any state manager

Watch outs

  • requires LLM endpoint configuration
  • no built‑in UI components
  • session size must be managed manually for cost

Setup notes

Add the dependency with: ``` flutter pub add flutter_agent_harness ``` Then run `flutter pub get`. Import the package and create an `AgentController` with your LLM endpoint and optional tool callbacks. Wrap the controller in a Provider or any state‑management solution you prefer, and start streaming responses to your UI.

Requires Flutter 3.10 or newer and Dart SDK >=2.19. Works on iOS, Android, web, macOS, Windows, and Linux. Ensure your LLM provider supports HTTP/2 streaming for optimal performance.

import 'package:flutter/material.dart';
import 'package:flutter_agent_harness/flutter_agent_harness.dart';
import 'package:provider/provider.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return Provider(
      create: (_) => AgentController(
        apiKey: const String.fromEnvironment('OPENAI_API_KEY'),
        endpoint: 'https://api.openai.com/v1/chat/completions',
      ),
      child: const MaterialApp(home: ChatScreen()),
    );
  }
}

class ChatScreen extends StatefulWidget {
  const ChatScreen({super.key});
  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final _controller = TextEditingController();
  late final AgentController _agent;

  @override
  void initState() {
    super.initState();
    _agent = Provider.of<AgentController>(context, listen: false);
  }

  void _sendMessage() {
    final text = _controller.text.trim();
    if (text.isEmpty) return;
    _agent.sendMessage(text);
    _controller.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AI Chat')),
      body: Column(
        children: [
          Expanded(
            child: StreamBuilder<String>(
              stream: _agent.responseStream,
              builder: (context, snapshot) {
                final reply = snapshot.data ?? '';
                return ListView(
                  padding: const EdgeInsets.all(12),
                  children: [
                    Text('Assistant: $reply'),
                  ],
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(hintText: 'Type a message'),
                    onSubmitted: (_) => _sendMessage(),
                  ),
                ),
                IconButton(icon: const Icon(Icons.send), onPressed: _sendMessage),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

Official package resources