⚠️ WARNING
If you plan to use this in production, ensure you have proper error handling and testing in place as interaction with AI models can be unpredictable.
About Murmuration
The name "Murmuration" is inspired by the mesmerizing flocking behavior of birds, symbolizing the framework's focus on coordinated agent interactions and dynamic workflows. 🐦💫
What's New in Murmuration 3.0.0 🐦
- Multiple LLM Provider Support: Added support for OpenAI, Google, and Anthropic models with an extensible provider system.
- Enhanced Tool System: Improved type safety and validation for tools and parameters.
- Improved State Management: Thread-safe operations with immutable state and type-safe access.
- Comprehensive Error Handling: New error handling system with detailed reporting.
- Enhanced Logging: Structured logging with performance metrics and error tracking.
- Security Improvements: Secure API key handling, input validation, and access control.
- Resource Management: Memory optimization, connection pooling, and rate limiting.
Breaking Changes
This version includes significant changes that may require updates to your implementation. Please refer to the Migration Guide for detailed steps to upgrade smoothly.
Table of Contents 📚
Overview 🔍
Murmuration offers:
- Type-safe schema validation system for ensuring data integrity
- Thread-safe state management to prevent race conditions
- Robust error handling with detailed error reporting
- Message history management with persistence
- Tool and function integration for extended capabilities
- Agent chain orchestration for complex workflows
- Streaming response support for real-time processing
- Comprehensive logging for debugging and monitoring
Installation ⚙️
Add to your pubspec.yaml
:
dependencies: murmuration: ^3.0.0
Then run:
dart pub get
Core Features 🛠️
Configuration
final config = MurmurationConfig( provider: LLMProvider.openAI, // Choose from OpenAI, Google, or Anthropic apiKey: 'your-api-key', model: 'gpt-4-turbo-preview', // Model specific to the chosen provider debug: true, // Enable debug mode for verbose logging stream: false, // Disable streaming by default logger: MurmurationLogger(enabled: true), // Enable logging timeout: Duration(seconds: 30), // Set request timeout maxRetries: 3, // Number of retry attempts retryDelay: Duration(seconds: 1), // Delay between retries enableCache: true, // Enable response caching cacheTimeout: Duration(hours: 1), // Cache expiration time rateLimit: RateLimit( // Rate limiting configuration requestsPerMinute: 60, maxConcurrentRequests: 5 ) );
Error Handling
try { final result = await agent.execute("Process data"); } on MurmurationException catch (e) { print('Error: ${e.message}'); // Human-readable error message print('Original error: ${e.originalError}'); // Original exception print('Stack trace: ${e.stackTrace}'); // Full stack trace }
Logging
final logger = MurmurationLogger( enabled: true, onLog: (message) => print('Log: $message'), // Log handler onError: (message, error, stackTrace) { // Error handler print('Error: $message'); print('Details: $error'); } );
Usage Guide 📖
Basic Usage
void main() async { final murmur = Murmuration(config); final agent = await murmur.createAgent( {'role': 'Assistant', 'context': 'Data processing'}, currentAgentIndex: 1, totalAgents: 1 ); final result = await agent.execute("Process this data"); print(result.output); }
Advanced Usage
Custom Schema Fields
class DateTimeSchemaField extends SchemaField{ final DateTime? minDate; final DateTime? maxDate; const DateTimeSchemaField({ required String description, this.minDate, this.maxDate, bool required = true, }) : super( description: description, required: required, ); @override bool isValidType(Object? value) => value == null || value is DateTime || (value is String && DateTime.tryParse(value) != null); @override bool validate(DateTime? value) { if (value == null) return !required; if (minDate != null && value.isBefore(minDate!)) return false; if (maxDate != null && value.isAfter(maxDate!)) return false; return true; } @override DateTime? convert(Object? value) { if (value == null) return null; if (value is DateTime) return value; if (value is String) return DateTime.tryParse(value); return null; } } // Usage example: final schema = OutputSchema( fields: { 'name': StringSchemaField( description: 'User name', minLength: 2, required: true ), 'birthDate': DateTimeSchemaField( description: 'Birth date', minDate: DateTime(1900), maxDate: DateTime.now(), required: true ) } );
Streaming Responses 🌊
final config = MurmurationConfig( apiKey: 'your-api-key', stream: true, // Enable streaming onStreamProgress: (progress) { // Track streaming progress print('Progress: ${progress.percentage}%'); print('Tokens received: ${progress.tokensReceived}'); print('Time elapsed: ${progress.timeElapsed}'); } ); final agent = await murmur.createAgent({'role': 'Assistant'}); final result = await agent.execute("Generate a long story"); if (result.stream != null) { await for (final chunk in result.stream!) { print(chunk); // Process each chunk as it arrives } // Access streaming statistics print('Total tokens: ${result.streamStats.totalTokens}'); print('Stream duration: ${result.streamStats.duration}'); }
Agent Chains ⛓️
final result = await murmur.runAgentChain( input: documentText, agentInstructions: [ {'role': 'Document Parser'}, {'role': 'Data Analyzer'}, {'role': 'Report Generator'} ], tools: [ Tool( name: 'document_parser', description: 'Parses document text', parameters: {'text': StringSchemaField(description: 'Document text')}, execute: (params) async => parseDocument(params['text']) ) ], functions: { 'analyze': (params) async => analyzeData(params), 'generate_report': (params) async => generateReport(params) }, logProgress: true, onProgress: (progress) { print('Progress: ${progress.currentAgent}/${progress.totalAgents}'); print('Status: ${progress.status}'); } ); print('Final report: ${result.finalOutput}');
Core Systems 🔧
1. Message History
final history = MessageHistory( threadId: 'user-123', // Unique thread identifier maxMessages: 50, // Maximum messages to retain maxTokens: 4000 // Maximum total tokens ); await history.addMessage(Message( role: 'user', content: 'Hello!', timestamp: DateTime.now() )); await history.save(); // Persist to storage await history.load(); // Load from storage await history.clear(); // Clear history
2. State Management
final state = ImmutableState() .copyWith({ 'user': {'name': 'John', 'age': 30}, 'preferences': {'theme': 'dark'} }); final userName = state.get('user.name'); // Type-safe access
Real-World Examples 💡
Customer Support Bot
final supportBot = await murmur.createAgent({ 'role': 'Customer Support', 'context': ''' You are a helpful customer support agent. Follow company guidelines and maintain professional tone. Escalate sensitive issues to human support. ''' }); // Add ticket management tool supportBot.addTool(Tool( name: 'create_ticket', description: 'Creates support ticket', parameters: { 'priority': StringSchemaField( description: 'Ticket priority', enumValues: ['low', 'medium', 'high'] ), 'category': StringSchemaField(description: 'Issue category') }, execute: (params) async => createSupportTicket(params) )); final response = await supportBot.execute(userQuery);
Data Processing Pipeline
final pipeline = await murmur.runAgentChain( input: rawData, agentInstructions: [ {'role': 'Data Validator'}, {'role': 'Data Transformer'}, {'role': 'Data Analyzer'}, {'role': 'Report Generator'} ], tools: [ Tool( name: 'data_validation', description: 'Validates data format', execute: validateData ), Tool( name: 'data_transform', description: 'Transforms data format', execute: transformData ) ] );
Troubleshooting 🔍
Common Issues
Timeout Errors
// Increase timeout duration final config = MurmurationConfig( timeout: Duration(minutes: 2), maxRetries: 5 );
Memory Issues
// Manage message history final config = MurmurationConfig( maxMessages: 30, maxTokens: 2000 );
State Management Issues
// Use proper state copying final newState = state.copyWith(newData); // Don't modify state directly state._data['key'] = value; // Wrong!
Best Practices 🏆
- Error Handling
- Always wrap agent execution in try-catch blocks
- Implement proper retry mechanisms
- Log errors comprehensively
- Handle timeouts appropriately
- Performance
- Enable caching for repetitive tasks
- Implement cleanup mechanisms
- Monitor memory usage
- Use appropriate timeout values
- Security
- Validate all inputs
- Handle sensitive data carefully
- Implement proper access controls
- Monitor API usage
- Message History
- Set appropriate message limits
- Implement cleanup policies
- Handle thread IDs carefully
- Monitor storage usage
Contributing 🤝
Guidelines for contributing to Murmuration:
- Fork the repository
- Create a feature branch
- Implement your changes
- Add tests
- Submit a pull request
Please ensure your code:
- Follows Dart conventions
- Includes proper documentation
- Has comprehensive error handling
- Includes appropriate tests
- Maintains type safety
License 📜
This project is licensed under the MIT License - see the LICENSE file for details.
Author ✍️
This project is authored and maintained by Agniva Maiti.