CopilotKit

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');
}