Intents
Intents are actions that the AI agent can perform on the user's behalf inside your Flutter app. You define what actions are available, what parameters they accept, and what state is currently relevant — the AI agent decides when and how to invoke them based on the user's voice input.
Overview
There are two building blocks:
| Concept | Purpose |
|---|---|
| Intent | Declares an action: its name, description, expected parameters, and handler |
| IntentState | A named piece of app state the AI agent can read (e.g. analytics, current items in view) |
Defining Intents
A VableIntent tells the AI what action exists, what parameters it needs, and what to call when the user triggers it.
VableIntent(
name: 'addToCart',
description: 'Add a product to the shopping cart',
parameters: {
'productId': VableIntentParameter(
type: 'string',
description: 'The ID of the product to add',
required: true,
),
'quantity': VableIntentParameter(
type: 'number',
description: 'How many units to add',
required: false,
),
},
onIntent: (parameters) async {
final productId = parameters['productId'] as String;
final quantity = (parameters['quantity'] as num?)?.toInt() ?? 1;
await CartService.add(productId: productId, quantity: quantity);
},
),
Parameter types
| Type | Dart type |
|---|---|
string | String |
number | num / int / double |
boolean | bool |
date | String (ISO 8601) |
Parameters can also define options to constrain the AI to a fixed set of values:
'status': VableIntentParameter(
type: 'string',
description: 'Filter by order status',
options: ['pending', 'shipped', 'delivered'],
),
Registering Intents
Call Vable.registerIntent to expose an intent to the AI agent. In Flutter, do this inside initState of the widget where the action is relevant:
void initState() {
super.initState();
Vable.registerIntent(
VableIntent(
name: 'addToCart',
description: 'Add a product to the shopping cart',
parameters: {
'productId': VableIntentParameter(
type: 'string',
description: 'The ID of the product to add',
required: true,
),
},
onIntent: (parameters) async {
// handle intent...
},
),
);
}
Intents are scoped to the widget that registers them. Unregister them in dispose so the AI agent doesn't attempt to invoke actions that are no longer available.
Intent States
Intent states are named pieces of app state that the AI agent can read as context. They are not tied to a specific intent — they describe what is currently happening in the app.
Vable.updateIntentState(
VableIntentState(
name: 'conversationAnalytics',
description: 'Contains analytics about conversations',
value: data,
),
);
Any data relevant to the current screen or session can be exposed this way:
// Products currently in view
Vable.updateIntentState(
VableIntentState(
name: 'productListing',
description: 'List of products currently displayed to the user',
value: products.map((p) => {'id': p.id, 'name': p.name, 'price': p.price}).toList(),
),
);
// Current user session
Vable.updateIntentState(
VableIntentState(
name: 'currentUser',
description: 'The currently logged-in user',
value: {'id': user.id, 'name': user.name, 'plan': user.plan},
),
);
// Cart contents
Vable.updateIntentState(
VableIntentState(
name: 'cart',
description: 'Items currently in the shopping cart',
value: cart.items.map((i) => {'productId': i.id, 'quantity': i.qty}).toList(),
),
);
Call updateIntentState whenever the underlying data changes so the AI always has current context.
Intent states don't need to match your intent names. They're free-form context — name them to describe what the data represents, not what action it's for.
Full Example
class ProductListPage extends StatefulWidget {
final List<Product> products;
const ProductListPage({super.key, required this.products});
State<ProductListPage> createState() => _ProductListPageState();
}
class _ProductListPageState extends State<ProductListPage> {
void initState() {
super.initState();
// Expose the add-to-cart action
Vable.registerIntent(
VableIntent(
name: 'addToCart',
description: 'Add a product to the shopping cart',
parameters: {
'productId': VableIntentParameter(
type: 'string',
description: 'The ID of the product to add',
required: true,
),
'quantity': VableIntentParameter(
type: 'number',
description: 'How many units to add',
),
},
onIntent: (parameters) async {
},
),
);
_syncState();
}
void didUpdateWidget(ProductListPage old) {
super.didUpdateWidget(old);
if (old.products != widget.products) _syncState();
}
void _syncState() {
// Give the AI context about what's currently on screen
Vable.updateIntentState(
VableIntentState(
name: 'productListing',
description: 'List of products currently displayed to the user',
value: widget.products
.map((p) => {'id': p.id, 'name': p.name, 'price': p.price})
.toList(),
),
);
}
void dispose() {
Vable.unregisterIntent('addToCart');
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: widget.products
.map((p) => ListTile(title: Text(p.name)))
.toList(),
),
);
}
}