An in-app AI assistant that ships inside your Flutter app
The most common reason teams reach for agentlib: they want a real agent — one that can call tools, keep context, and stream — living inside the app, not behind a server round-trip for every turn. agentlib is pure Dart, so the same AgentSpec runs on the device that renders your UI.
Why in-app instead of server-side
A server-side agent adds a network hop to every tool call and can't touch on-device state — contacts, the current screen, local files — without exfiltrating it. An in-app agent keeps the loop next to the UI. agentlib gives you the streaming Runner event loop (TextDelta, ToolCalled, Finished) so you can render tokens as they arrive and drive Flutter widgets directly from tool results.
Tools are your app's own functions
Register Dart functions as CLIs in the Vfs and the model composes them through the Sh mini-shell — contacts grep 'Mom' | jq -r .number | xargs whatsapp send. No JSON-RPC ceremony, no subprocess. Every high-impact tool auto-snapshots first, so a mistaken send is one revert() away.
Consent and audit come free
Wrap sensitive actions with the PermissionRequestHook to surface a native consent sheet, and PostToolUse to write an audit line. That's how you ship an assistant that can act on the user's behalf without hard-coding a permission dialog into every call site.
final agent = AgentSpec(
name: 'assistant',
instructions: 'Help the user with tasks in this app.',
model: AnthropicProvider(
apiKey: const String.fromEnvironment('ANTHROPIC_API_KEY'),
),
);
final run = Runner.runStreamed(
agent.toRunConfig(vfs: appVfs, threadId: 'chat'),
input: userMessage,
);
await for (final e in run.events) {
if (e is TextDelta) appendToBubble(e.delta);
} Related use cases
- Offline and on-device agents with cloud fallback — Run agents on Apple Foundation Models, Gemini Nano, or llama.cpp — and fall back to Anthropic, OpenAI, or Google only when needed.
- Long-running agents that survive backgrounding and app kills — Serialize a run's state, let the OS suspend or kill the app, then resume — even via push — with agentlib's lifecycle hooks.
See how these fit together in the architecture overview, or browse all eight primitives in depth.