vantura 0.1.0
vantura: ^0.1.0 copied to clipboard
An AI Agentic Framework for Flutter. Build LLM-powered agents that reason, use tools, remember conversations, and stream responses in real-time. Works with any OpenAI-compatible API.
Vantura #
An AI Agentic Framework for Flutter â build LLM-powered agents that reason, use tools, remember conversations, and stream responses in real-time.
Features #
- đ§ ReAct Reasoning Loop â Agents autonomously decide when to think, call tools, and respond.
- đ ī¸ Extensible Tool System â Create custom tools with type-safe arguments and JSON Schema definitions.
- đ Streaming-First â Token-by-token streaming via SSE for real-time typewriter UIs.
- đž Smart Memory â Automatic summarization and pruning keeps the context window within token limits.
- đ¤ Multi-Agent Coordination â
AgentCoordinatorenables seamless hand-offs between specialist agents. - âšī¸ Request Cancellation â
CancellationTokenlets users abort generation mid-flight. - đ Token Usage Tracking â Monitor prompt/completion/total tokens per request.
- đ Error Callbacks â
onToolError,onAgentFailure,onWarninghooks for telemetry and resilience. - đ Built-in Markdown Renderer â Zero-dependency Flutter widget for rendering agent responses.
- đ Provider Agnostic â Works with any OpenAI-compatible API (Groq, OpenAI, Ollama, Together, etc.).
Installation #
Add to your pubspec.yaml:
dependencies:
vantura:
path: packages/vantura # local path (or pub.dev once published)
Quick Start #
1. Initialize the Client #
import 'package:vantura/core/index.dart';
final client = VanturaClient(
apiKey: 'your-api-key',
baseUrl: 'https://api.groq.com/openai/v1/chat/completions',
model: 'llama-3.3-70b-versatile',
);
2. Set Up Memory #
// In-memory only
final memory = VanturaMemory(sdkLogger, client);
// With persistence (provide your own VanturaPersistence implementation)
final memory = VanturaMemory(sdkLogger, client, persistence: myPersistence);
await memory.init();
3. Create and Run the Agent #
final agent = VanturaAgent(
name: 'assistant',
description: 'General-purpose assistant',
instructions: 'You are a helpful assistant.',
memory: memory,
tools: [...getStandardTools(), MyCustomTool()],
client: client,
state: VanturaState(),
onToolError: (tool, error, stack) => print('Tool $tool failed: $error'),
);
// Blocking call
final response = await agent.run('What is 2 + 2?');
print(response.text);
print('Tokens used: ${response.usage?.totalTokens}');
// Streaming (real-time chunks)
final token = CancellationToken();
await for (final chunk in agent.runStreaming('Tell me a story', cancellationToken: token)) {
if (chunk.textChunk != null) stdout.write(chunk.textChunk);
}
Architecture #
lib/
âââ core/ # Core SDK engine
â âââ index.dart # Barrel export
â âââ agent_coordinator.dart # Multi-agent routing & handoffs
â âââ cancellation_token.dart # Request cancellation
â âââ vantura_agent.dart # Agent reasoning loop + callbacks
â âââ vantura_client.dart # HTTP client (retry, rate-limit, SSE)
â âââ vantura_memory.dart # Short-term + long-term memory
â âââ vantura_persistence.dart # Abstract persistence interface
â âââ vantura_state.dart # UI state (ChangeNotifier)
â âââ vantura_tool.dart # Abstract tool base class
â âââ schema_helper.dart # JSON Schema builder
â âââ logger.dart # Abstract logger
âââ markdown/ # Built-in Markdown renderer
â âââ markdown.dart # MarkdownText widget
â âââ parser.dart # Markdown â AST
â âââ nodes.dart # AST node definitions
â âââ renderer.dart # AST â Flutter widgets
âââ tools/ # Built-in tools
âââ index.dart # getStandardTools() registry
âââ calculator_tool.dart
âââ network_connectivity_tool.dart
âââ device_info_tool.dart
âââ api_test_tool.dart
Core Classes #
VanturaClient #
HTTP client with connection pooling, 3-retry exponential backoff, and automatic HTTP 429 rate-limit handling.
| Property | Type | Description |
|---|---|---|
apiKey |
String |
API key for Bearer auth |
baseUrl |
String |
API endpoint URL |
model |
String |
Default model name |
temperature |
double? |
Sampling temperature |
maxCompletionTokens |
int? |
Max tokens in response |
VanturaAgent #
The reasoning engine. Runs a ReAct-style loop (configurable max iterations) alternating between LLM calls and tool execution.
| Constructor Param | Type | Description |
|---|---|---|
name |
String |
Agent identity for multi-agent routing |
description |
String |
Agent purpose (used by coordinators) |
instructions |
String |
System prompt |
onToolError |
Function? |
Callback when a tool throws |
onAgentFailure |
Function? |
Callback on critical agent failure |
onWarning |
Function? |
Callback for non-fatal warnings |
AgentCoordinator #
Manages multiple agents with automatic hand-off via an injected transfer_to_agent tool:
final coordinator = AgentCoordinator([
invoicingAgent,
inventoryAgent,
generalAgent,
]);
// Use exactly like a single agent
await for (final r in coordinator.runStreaming('Create an invoice')) { ... }
VanturaResponse #
| Field | Type | Description |
|---|---|---|
text |
String? |
Final complete text (from run()) |
textChunk |
String? |
Single streamed token (from runStreaming()) |
toolCalls |
List<Map<String, dynamic>>? |
Tool calls executed during this step |
usage |
TokenUsage? |
Prompt / completion / total token counts |
VanturaPersistence (Abstract) #
Plug in any storage backend. The SDK never imports sqflite, hive, or any database directly.
abstract class VanturaPersistence {
Future<void> saveMessage(String role, String content, {bool isSummary = false});
Future<List<Map<String, dynamic>>> loadMessages();
Future<void> clearMessages();
Future<void> deleteOldMessages(int limit);
}
Creating Custom Tools #
class GreetTool extends VanturaTool<GreetArgs> {
@override String get name => 'greet_user';
@override String get description => 'Greets a user by name';
@override
Map<String, dynamic> get parameters => SchemaHelper.generateSchema({
'name': SchemaHelper.stringProperty(description: 'The user name'),
});
@override GreetArgs parseArgs(Map<String, dynamic> json) => GreetArgs.fromJson(json);
@override
Future<String> execute(GreetArgs args) async => 'Hello, ${args.name}!';
}
For destructive operations, override requiresConfirmation => true for human-in-the-loop safety.
Built-in Tools #
| Tool | Name | Description |
|---|---|---|
CalculatorTool |
calculator |
Basic arithmetic |
NetworkConnectivityTool |
check_connectivity |
Internet connectivity check |
DeviceInfoTool |
get_device_info |
Platform and OS info |
ApiTestTool |
test_api |
HTTP GET/POST requests |
Access all via getStandardTools() from package:vantura/tools/index.dart.
Markdown Renderer #
Zero-dependency Flutter Markdown widget:
import 'package:vantura/markdown/markdown.dart';
MarkdownText('### Hello **World**', isUser: false)
Supports headers, bold, italic, inline code, bullet lists, and horizontal rules.
Design Principles #
- No database imports â Persistence is abstracted via
VanturaPersistence. - Minimal Flutter dependency â Only
VanturaStateusesChangeNotifier. Core is pure Dart. - Shared HTTP client â Connection pooling via a single
http.Client. - Streaming-first â
runStreaming()yields chunks as they arrive, not after completion. - Automatic memory management â Old messages are summarized and pruned.
- Human-in-the-loop â Tools can require user confirmation before execution.
License #
This project is licensed under the MIT License â see the LICENSE file for details.