for · flutter devs

The agent SDK that ships in your Flutter app.

Pure Dart, one pub.dev package, no platform glue to write. Same code on iOS, Android, and macOS dev box.

  • iOS 12+
  • Android API 21+
  • macOS
  • Dart 3.10+ · Flutter 3.38+

Why Flutter devs end up here

  • You shipped a Flutter app and now your PM wants "AI features".
  • You want one Dart codebase, not a Python service + REST + UI client.
  • You want to call Apple Foundation Models or Gemini Nano without writing a Pigeon bridge yourself.
  • You don't want to embed Node in your iOS bundle.

What you write

lib/agents/helper.dart
import 'package:agentlib/agentlib.dart';

class HelperAgent {
  late final Runner runner;

  HelperAgent() {
    final agent = AgentSpec(
      name: 'helper',
      instructions: 'You are a helpful mobile assistant.',
      model: ModelRoute.preferOnDevice(
        onDevice: [FoundationModelsProvider(), GeminiNanoProvider()],
        fallback: AnthropicProvider(apiKey: ''),
      ),
    );
    runner = Runner(agent.toRunConfig(vfs: Vfs(), threadId: 'helper'));
  }

  Stream ask(String prompt) => runner.run(prompt);
}

How it fits Flutter idioms

  • Stream-first. Runner.runStreamed(...) returns a Dart Stream<RunEvent>. Drop it into StreamBuilder, Riverpod, BLoC — whatever you use.
  • Hot-reload safe. No global state, no native runtime to restart. Hot-reload works as you'd expect.
  • Platform-channel-free for you. agentlib already wires platform channels for Foundation Models, Gemini Nano, AICore, MediaPipe. You import a Dart class.
  • pub.dev native. flutter pub add agentlib. Standard semver. Standard scoring.

UI patterns

The streaming events map cleanly to standard Flutter UI idioms:

chat_screen.dart
StreamBuilder(
  stream: runner.run(prompt),
  builder: (ctx, snap) {
    if (snap.connectionState == ConnectionState.waiting) {
      return const LinearProgressIndicator();
    }
    final e = snap.data;
    if (e is TextDelta) _buf.write(e.delta);
    if (e is ToolCalled) _tools.add(e.tool);
    return Column(children: [
      Text(_buf.toString()),
      for (final t in _tools) Chip(label: Text('→ $t')),
    ]);
  },
)

What about packages I already use?

agentlib doesn't replace your stack — it plugs in.

  • Riverpod / BLoC / Provider / GetX: the Runner is just a Dart object. Wrap it in a notifier.
  • Drift / sqflite: agentlib's snapshot store uses sqflite already. Your DB sits next to it.
  • http / dio: the cloud providers use Dart's http for portability; if you need dio, implement a ModelProvider wrapper.
  • flutter_local_notifications: use the NotificationHook to fire local notifs when an agent finishes a long-running subagent.

Next

ship it

Pull agentlib into your next Flutter PR.

It's one pubspec line. The hello-agent example is 79 lines. You'll be streaming agent output before your coffee gets cold.