Aven App Agent Flutter SDK
aven_app_agent is the MVP alpha Flutter SDK for Aven-powered in-app assistance and guided walkthroughs.
MVP alpha status
- Alpha package for manual Aven registration
- Manual page registration is required
- Manual element registration is required
- Manual workflow registration is required
- No automatic widget discovery
- No automatic page discovery
- No automatic navigation
What it does
- Resolves end-user questions into guided workflows
- Renders an assistant chat sheet inside your Flutter app
- Highlights registered widgets with a walkthrough overlay
- Continues workflows across screens when the current page changes
- Surfaces validation, health, and debug diagnostics for manual SDK setup
What it does not do yet
- Automatic widget discovery
- Automatic page discovery
- Automatic route-to-page mapping without your registration
- Automatic workflow authoring inside the SDK
Installation
dependencies:
aven_app_agent: ^0.2.0-alpha.1
import 'package:aven_app_agent/aven_app_agent.dart';
Backend contract
- Official backend endpoint:
POST /v1/workflows/resolve-page-context - The Flutter SDK sends a page-grouped contract:
appContext.pages[] - Each registered page includes its registered elements
Quick start
import 'package:flutter/material.dart';
import 'package:aven_app_agent/aven_app_agent.dart';
final bookTicketButtonKey = GlobalKey();
final sourceStationKey = GlobalKey();
void setupAven() {
Aven.init(
config: AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
appName: 'Your Flutter App',
debugMode: true,
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: false,
micInput: false,
),
voice: const AvenVoiceConfig(),
theme: const AvenTheme(),
),
);
Aven.registerPage(
pageId: 'home',
pageName: 'Home',
route: '/',
description: 'Landing page',
);
Aven.registerElement(
pageId: 'home',
elementId: 'book_ticket_button',
key: bookTicketButtonKey,
label: 'Book Ticket',
type: 'button',
action: 'navigate',
targetPageId: 'book_ticket',
);
Aven.registerPage(
pageId: 'book_ticket',
pageName: 'Book Ticket',
route: '/book-ticket',
);
Aven.registerElement(
pageId: 'book_ticket',
elementId: 'source_station_input',
key: sourceStationKey,
label: 'Source Station',
type: 'text_field',
action: 'input',
);
Aven.registerWorkflow(
const AvenRegisteredWorkflow(
workflowName: 'book_ticket',
title: 'Book a Train Ticket',
keywords: <String>['book', 'ticket'],
steps: <AvenWorkflowStep>[
AvenWorkflowStep(
stepId: 'step_001',
order: 1,
pageId: 'home',
elementId: 'book_ticket_button',
instruction: 'Tap Book Ticket.',
actionType: 'navigate',
),
AvenWorkflowStep(
stepId: 'step_002',
order: 2,
pageId: 'book_ticket',
elementId: 'source_station_input',
instruction: 'Enter the source station.',
actionType: 'input',
),
],
),
);
Aven.setCurrentPage('home');
}
Theming
Aven Flutter SDK now defaults to system theme resolution. The SDK reads brightness from MediaQuery.platformBrightnessOf(context) when available and falls back to WidgetsBinding.instance.platformDispatcher.platformBrightness.
Aven.init(
config: AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
themeMode: AvenThemeMode.system,
),
);
Force light or dark mode:
AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
themeMode: AvenThemeMode.light,
)
AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
themeMode: AvenThemeMode.dark,
)
Customize the default tokens:
AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
themeMode: AvenThemeMode.system,
darkTheme: const AvenThemeTokens.dark().copyWith(
accent: Color(0xFFA78BFA),
surface: Color(0xFF0C0C0E),
),
)
Notes:
themeModedefaults toAvenThemeMode.system- existing
theme: AvenTheme(...)customization still works and is merged into the resolved light or dark tokens - the SDK themes only Aven-owned surfaces and does not force your app's
MaterialApptheme
Initialization
Call Aven.init(...) once during app startup. The package validates:
appIdapiKeybaseUrl- request timeout configuration
Use a real backend URL in production. Placeholder example:
Aven.init(
config: AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
assistantModes: const AvenAssistantModes(),
voice: const AvenVoiceConfig(),
),
);
Flutter Voice Assistant Modes
AvenConfig now supports developer-controlled assistant modes and voice behavior:
Aven.init(
config: AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: true,
micInput: true,
),
voice: const AvenVoiceConfig(
defaultLocaleId: 'en-IN',
supportedLocaleIds: <String>['en-IN', 'en-US', 'hi-IN'],
speechRate: 0.88,
pitch: 1.0,
autoSpeakSteps: true,
autoSubmitVoiceInput: true,
),
),
);
Developer mode presets:
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: false,
micInput: false,
)
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: true,
micInput: true,
)
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: true,
micInput: false,
)
assistantModes: const AvenAssistantModes(
highlighter: true,
floatingCard: true,
speakSteps: false,
micInput: true,
)
Behavior notes:
- End users only see settings toggles for modes the developer enabled during
Aven.init(...). - Voice input uses
speech_to_textand keeps the typed input field as the fallback. - Speak steps uses
flutter_ttsand device TTS quality depends on the platform speech engine. - The SDK does not use paid cloud STT/TTS, does not upload raw audio, and never listens continuously.
Platform permissions:
- Android host apps must declare
android.permission.RECORD_AUDIO. - iOS host apps must add
NSMicrophoneUsageDescriptionandNSSpeechRecognitionUsageDescriptiontoInfo.plist.
If speech recognition or TTS is unavailable on a device, Aven keeps the typed assistant, highlighter, and walkthrough UI working normally.
Backend URL and API key configuration
baseUrlshould point to your Aven backend hostapiKeyshould be supplied by your backend or developer configuration- Do not ship demo keys or localhost defaults in production builds
Manual page registration
Aven.registerPage(
pageId: 'checkout',
pageName: 'Checkout',
route: '/checkout',
description: 'Checkout screen',
);
Manual element registration
Register widgets with stable GlobalKey instances.
final payNowKey = GlobalKey();
Aven.registerElement(
pageId: 'checkout',
elementId: 'pay_now_button',
key: payNowKey,
label: 'Pay Now',
type: 'button',
action: 'submit',
);
Manual workflow registration
Aven.registerWorkflow(
const AvenRegisteredWorkflow(
workflowName: 'complete_checkout',
title: 'Complete Checkout',
keywords: <String>['checkout', 'pay'],
steps: <AvenWorkflowStep>[
AvenWorkflowStep(
stepId: 'step_pay_now',
order: 1,
pageId: 'checkout',
elementId: 'pay_now_button',
instruction: 'Tap Pay Now to submit the order.',
),
],
),
);
Assistant UI setup
Wrap your app once with AvenScope so the package can render the assistant chat sheet, walkthrough overlay, and optional debug panel.
MaterialApp(
navigatorObservers: <NavigatorObserver>[
AvenNavigatorObserver(),
],
builder: (context, child) {
return AvenScope(
child: child ?? const SizedBox.shrink(),
);
},
);
AvenScope automatically manages the built-in AvenFab.
Navigator observer setup
If your app uses named routes, add AvenNavigatorObserver() so the SDK can react to route changes and continue multi-screen workflows more reliably.
Theme customization
AvenTheme is implemented and can be passed into AvenConfig.
Aven.init(
config: AvenConfig(
appId: 'your-app-id',
apiKey: 'YOUR_AVEN_API_KEY',
baseUrl: 'https://your-api-host.example.com',
theme: const AvenTheme(
primaryColor: Color(0xFF0A6EBD),
),
),
);
Asking questions and starting walkthroughs
End users can open the built-in assistant with:
Aven.openAssistant();
If you need to resolve a question programmatically, use the public controller:
final response = await Aven.controller.askQuestion(
'How do I complete checkout?',
);
if (response?.workflow != null) {
Aven.startWorkflow(response!.workflow);
}
Starting and controlling walkthroughs
Implemented controls include:
Aven.startWorkflow([workflow])Aven.markStepCompleted(elementId)Aven.clearActiveWorkflow()Aven.pauseWorkflow()Aven.resumeWorkflow()Aven.resetSession()
Example:
Aven.startWorkflow();
Aven.markStepCompleted('pay_now_button');
Aven.pauseWorkflow();
Aven.resumeWorkflow();
Health check and diagnostics
These APIs are implemented:
Aven.healthCheck()Aven.validateSetup()Aven.getDebugState()Aven.exportDebugSnapshot()
final validation = Aven.validateSetup();
final health = await Aven.healthCheck();
final debugState = Aven.getDebugState();
Missing element recovery
If a registered widget is not mounted or not on the current screen, the SDK:
- keeps the workflow active
- shows recovery UI instead of crashing
- waits for the correct page
- resumes highlighting when the target widget becomes available
Cross-screen continuation
The SDK supports workflows that continue across multiple registered screens. Keep Aven.setCurrentPage(pageId) updated whenever your app changes screens.
Aven.setCurrentPage('book_ticket');
Known limitations
- MVP alpha package
- Manual registration model only
- No automatic widget discovery
- No automatic page discovery
- No automatic navigation
- Widgets must be mounted before they can be highlighted
Migration
See the GuideAI Web and Flutter migration guide for the new package name, canonical import, and compatibility notes.
License
MIT