Multi-turn Chat (Message History)

You can pass a list of Message objects to the agent for context-aware, multi-turn conversations. Each message has a role (system, user, model) and a list of content parts (text, media, etc.). All providers support this interface.

import 'package:dartantic_ai/dartantic_ai.dart';
import 'package:dartantic_ai/src/models/message.dart';

void main() async {
  final agent = Agent(
    'openai:gpt-4o',
    systemPrompt: 'You are a helpful assistant. Keep responses concise.',
  );

  // Start with empty message history
  var messages = <Message>[];

  // First turn
  final response1 = await agent.run(
    'What is the capital of France?',
    messages: messages,
  );
  print('User: What is the capital of France?');
  print('Assistant: ${response1.output}'); // Output: The capital of France is Paris.

  // Update message history with the response
  messages = response1.messages;

  // Second turn - the agent should remember the context
  final response2 = await agent.run(
    'What is the population of that city?',
    messages: messages,
  );
  print('User: What is the population of that city?');
  print('Assistant: ${response2.output}'); // Output: Paris has approximately 2.1 million people in the city proper.

  print('Message history contains ${response2.messages.length} messages'); // Output: Message history contains 4 messages
}

You can find a working example in multi_turn.dart.

Content and Message Construction

As you work with messages and history, you may find that you're creating messages and the content of those messages to build up messasge history on the fly. dartantic_ai provides convenience methods to simplify this.

Content Constructors

The Content type alias makes working with message content more readable:

import 'package:dartantic_ai/dartantic_ai.dart';

void main() async {
  // Create text content easily
  final textContent = Content.text('Hello, how can I help you?');

  // Equivalent to: [TextPart('Hello, how can I help you?')]
  print(textContent); // Output: [TextPart(text: "Hello, how can I help you?")]
}

Message Role Constructors

If you find yourself wanting to create or update message history, you may find yourself wanting some helpers. For example, with the role constructors, you can messages for specific roles without specifying the role explicitly:

import 'package:dartantic_ai/dartantic_ai.dart';

void main() async {
  // Create messages using convenience constructors
  final userMessage = Message.user(Content.text('What is 2 + 2?'));
  final modelMessage = Message.model(Content.text('2 + 2 equals 4.'));

  // Use them in a conversation
  final messages = [userMessage, modelMessage];

  final agent = Agent('openai');
  final response = await agent.run('What about 3 + 3?', messages: messages);
  print(response.output); // Output: 3 + 3 equals 6.
}

You can also use Message(role: Messagerole.User, parts: [TextPart(prompt)]) if you'd like to. I don't judge.

Provider Switching

Because the list of messages is defined in a provider-agnostic way, you can switch between providers within a single conversation.

import 'package:dartantic_ai/dartantic_ai.dart';

void main() async {
  final openaiAgent = Agent.provider(OpenAiProvider(), systemPrompt: 'You are a helpful assistant.');
  final geminiAgent = Agent.provider(GeminiProvider(), systemPrompt: 'You are a helpful assistant.');

  // Start conversation with OpenAI
  var response = await openaiAgent.run('What animal says "moo"?');
  print('OpenAI: ${response.output}'); // Output: A cow says "moo".
  var history = response.messages;

  // Continue conversation with Gemini
  response = await geminiAgent.run('What animal says "quack"?', messages: history);
  print('Gemini: ${response.output}'); // Output: A duck says "quack".
  history = response.messages;

  // Store some info with OpenAI
  response = await openaiAgent.run('My favorite animal is the platypus.', messages: history);
  print('OpenAI: ${response.output}'); // Output: That's great! Platypuses are fascinating creatures.
  history = response.messages;

  // Retrieve info with Gemini
  response = await geminiAgent.run('What animal did I say I liked?', messages: history);
  print('Gemini: ${response.output}'); // Output: You said your favorite animal is the platypus.
}

You can find a working example in providers.dart.