Types
The AG-UI Dart SDK provides strongly-typed data structures for agent interactions. All types are immutable and support JSON serialization.
RunAgentInput
Input parameters for executing an agent.
SimpleRunAgentInput
The standard implementation for most use cases:
class SimpleRunAgentInput extends RunAgentInput {
final List<Message> messages;
final Map<String, dynamic>? context;
final List<Tool>? tools;
final String? threadId;
final Map<String, dynamic>? modelConfig;
const SimpleRunAgentInput({
required this.messages,
this.context,
this.tools,
this.threadId,
this.modelConfig,
});
}Example
final input = SimpleRunAgentInput(
messages: [
UserMessage(id: 'msg_1', content: 'Hello!'),
],
context: {
'userId': 'user123',
'sessionId': 'session456',
},
tools: [
Tool(
name: 'get_weather',
description: 'Get current weather',
parameters: {
'type': 'object',
'properties': {
'location': {'type': 'string'},
},
},
),
],
threadId: 'thread_789',
);StructuredRunAgentInput
For complex inputs with additional metadata:
class StructuredRunAgentInput extends RunAgentInput {
final List<Message> messages;
final Map<String, dynamic> context;
final List<Tool> tools;
final String threadId;
final Map<String, dynamic> metadata;
final RunConfiguration configuration;
const StructuredRunAgentInput({
required this.messages,
required this.context,
required this.tools,
required this.threadId,
required this.metadata,
required this.configuration,
});
}Message Types
Messages represent communication between users, assistants, and tools.
UserMessage
A message from the user:
class UserMessage extends Message {
final String id;
final String content;
final List<Attachment>? attachments;
final Map<String, dynamic>? metadata;
const UserMessage({
required this.id,
required this.content,
this.attachments,
this.metadata,
});
}AssistantMessage
A message from the AI assistant:
class AssistantMessage extends Message {
final String id;
final String content;
final List<ToolCall>? toolCalls;
final Map<String, dynamic>? metadata;
const AssistantMessage({
required this.id,
required this.content,
this.toolCalls,
this.metadata,
});
}ToolCallMessage
A request to call a tool:
class ToolCallMessage extends Message {
final String id;
final String toolCallId;
final String name;
final Map<String, dynamic> arguments;
const ToolCallMessage({
required this.id,
required this.toolCallId,
required this.name,
required this.arguments,
});
}ToolResponseMessage
The response from a tool call:
class ToolResponseMessage extends Message {
final String id;
final String toolCallId;
final dynamic result;
final String? error;
const ToolResponseMessage({
required this.id,
required this.toolCallId,
required this.result,
this.error,
});
}SystemMessage
System-level messages:
class SystemMessage extends Message {
final String id;
final String content;
final SystemMessageType type;
const SystemMessage({
required this.id,
required this.content,
required this.type,
});
}Example Usage
final conversation = [
SystemMessage(
id: 'sys_1',
content: 'You are a helpful assistant.',
type: SystemMessageType.instruction,
),
UserMessage(
id: 'user_1',
content: 'What is the weather?',
attachments: [
Attachment(
type: AttachmentType.location,
data: {'lat': 37.7749, 'lon': -122.4194},
),
],
),
AssistantMessage(
id: 'asst_1',
content: 'Let me check the weather for you.',
toolCalls: [
ToolCall(
id: 'call_1',
name: 'get_weather',
arguments: {'location': 'San Francisco'},
),
],
),
ToolResponseMessage(
id: 'tool_1',
toolCallId: 'call_1',
result: {'temperature': 68, 'conditions': 'sunny'},
),
AssistantMessage(
id: 'asst_2',
content: 'It\'s 68°F and sunny in San Francisco.',
),
];Context
Context provides additional information to the agent:
class Context {
final Map<String, dynamic> data;
const Context(this.data);
// Typed accessors
String? getString(String key) => data[key] as String?;
int? getInt(String key) => data[key] as int?;
bool? getBool(String key) => data[key] as bool?;
Map<String, dynamic>? getMap(String key) =>
data[key] as Map<String, dynamic>?;
List<dynamic>? getList(String key) => data[key] as List<dynamic>?;
}Example
final context = Context({
'user': {
'id': 'user123',
'name': 'John Doe',
'preferences': {
'language': 'en',
'timezone': 'America/New_York',
},
},
'session': {
'id': 'session456',
'startTime': DateTime.now().toIso8601String(),
},
'features': ['advanced_search', 'voice_input'],
});
// Access context data
final userId = context.getMap('user')?['id'];
final language = context.getString('user.preferences.language');
final features = context.getList('features');Tool
Defines a function that agents can call:
class Tool {
final String name;
final String description;
final Map<String, dynamic> parameters;
final bool? required;
final Map<String, dynamic>? metadata;
const Tool({
required this.name,
required this.description,
required this.parameters,
this.required,
this.metadata,
});
}Example
final weatherTool = Tool(
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': 'City name or coordinates',
},
'units': {
'type': 'string',
'enum': ['celsius', 'fahrenheit'],
'default': 'celsius',
},
},
'required': ['location'],
},
required: false,
metadata: {
'apiVersion': '1.0',
'rateLimit': 100,
},
);
final calculatorTool = Tool(
name: 'calculate',
description: 'Perform mathematical calculations',
parameters: {
'type': 'object',
'properties': {
'expression': {
'type': 'string',
'description': 'Mathematical expression to evaluate',
},
},
'required': ['expression'],
},
);State
Represents agent state that can be persisted and restored:
class State {
final Map<String, dynamic> data;
final String? checkpointId;
final DateTime? timestamp;
const State({
required this.data,
this.checkpointId,
this.timestamp,
});
// Create a new state with updates
State update(Map<String, dynamic> updates) {
return State(
data: {...data, ...updates},
checkpointId: checkpointId,
timestamp: DateTime.now(),
);
}
// Apply a JSON Patch
State patch(List<JsonPatch> patches) {
final patchedData = applyJsonPatch(data, patches);
return State(
data: patchedData,
checkpointId: checkpointId,
timestamp: DateTime.now(),
);
}
}Example
// Initial state
var state = State(
data: {
'conversation': {
'messageCount': 0,
'topics': [],
},
'user': {
'satisfaction': null,
},
},
);
// Update state
state = state.update({
'conversation': {
'messageCount': 1,
'topics': ['weather'],
},
});
// Apply JSON Patch
state = state.patch([
JsonPatch(
op: 'replace',
path: '/user/satisfaction',
value: 'high',
),
JsonPatch(
op: 'add',
path: '/conversation/topics/-',
value: 'sports',
),
]);Attachment
Represents file or data attachments:
class Attachment {
final AttachmentType type;
final dynamic data;
final String? mimeType;
final String? filename;
final int? size;
const Attachment({
required this.type,
required this.data,
this.mimeType,
this.filename,
this.size,
});
}
enum AttachmentType {
image,
document,
audio,
video,
location,
custom,
}Example
final imageAttachment = Attachment(
type: AttachmentType.image,
data: base64ImageData,
mimeType: 'image/jpeg',
filename: 'photo.jpg',
size: 102400,
);
final locationAttachment = Attachment(
type: AttachmentType.location,
data: {
'latitude': 37.7749,
'longitude': -122.4194,
'name': 'San Francisco',
},
);ToolCall
Represents a tool invocation:
class ToolCall {
final String id;
final String name;
final Map<String, dynamic> arguments;
final ToolCallStatus? status;
final dynamic result;
final String? error;
const ToolCall({
required this.id,
required this.name,
required this.arguments,
this.status,
this.result,
this.error,
});
}
enum ToolCallStatus {
pending,
running,
completed,
failed,
}Type Conversions
All types support JSON serialization:
// Convert to JSON
final json = message.toJson();
final jsonString = jsonEncode(json);
// Convert from JSON
final decoded = jsonDecode(jsonString);
final message = Message.fromJson(decoded);
// Batch conversion
final messages = [msg1, msg2, msg3];
final jsonList = messages.map((m) => m.toJson()).toList();
final restored = jsonList.map((j) => Message.fromJson(j)).toList();Validation
All types include built-in validation:
// Automatic validation on construction
try {
final tool = Tool(
name: '', // Invalid: empty name
description: 'Test',
parameters: {},
);
} on ValidationError catch (e) {
print('Invalid tool: ${e.message}');
}
// Manual validation
final validator = TypeValidator();
final errors = validator.validateMessage(message);
if (errors.isNotEmpty) {
print('Validation errors: $errors');
}