Message
Category: Agent
Source: message.dart
Conversation message types and the streaming/agent event vocabulary shared between the agent loop and the LLM strategies.
Status: part of the proposed core data model — see docs/plans/2026-04-29-harness-layers.md. Originally lived in agent/agent_core.dart; relocated so strategies (LLM clients, providers) can depend on these types without violating the layer rule.
The agent loop class itself ([AgentCore]) stays in agent/.
Enums
Role
Role of a message in the conversation.
| Value | Description |
|---|---|
user | |
assistant | |
toolResult |
Classes
Message
A single message in the conversation history.
Constructor
factory Message.user(String text, {List<ContentPart>? contentParts})Build a user message. Pass [contentParts] for multimodal input (text + images + resource links) — the LLM mappers will serialise them per provider, falling back to [text] for clients that don't support multimodal input.
factory Message.assistant({String? text, List<ToolCall>? toolCalls})factory Message.toolResult({
required ToolCallId callId,
required String content,
String? toolName,
List<ContentPart>? contentParts,
})Properties
| Property | Type | Description |
|---|---|---|
role | Role | |
text | String? | |
toolCalls | List<ToolCall> | |
toolCallId | String? | |
toolName | String? | |
contentParts | List<ContentPart>? | |
text | String | |
text | String | |
id | ToolCallId | |
name | String | |
toolCall | ToolCall | |
inputTokens | int | |
outputTokens | int | |
cacheReadTokens | int? | |
cacheCreationTokens | int? | |
totalTokens | int get | |
id | ToolCallId | |
name | String | |
arguments | Map<String, dynamic> | |
description | String | |
thoughtSignature | String? | Provider-specific opaque token that must be echoed back on the next request. Currently set only by the Gemini provider when the model is in thinking mode; null for all other providers. See https://ai.google.dev/gemini-api/docs/thought-signatures. |
totalTokens | int get |
sealed LlmChunk
A chunk emitted by the LLM streaming response.
TextDelta
A delta of generated text.
Constructor
TextDelta(this.text)Properties
| Property | Type | Description |
|---|---|---|
text | String |
ThinkingDelta
A delta of streaming reasoning/"thinking" content. Distinct from [TextDelta] so renderers can style it as deliberative-aside rather than final assistant output.
Only reasoning-capable models emit this — Claude 4.x with extended thinking, GPT-5 / o-series, DeepSeek R1, QwQ, etc. Parsers that don't see thinking blocks simply never yield this variant.
Thinking content is not appended to the assistant message that gets sent back to the model on the next turn — Anthropic explicitly forbids this without the right block structure, and including it would pollute context for other providers.
Constructor
ThinkingDelta(this.text)Properties
| Property | Type | Description |
|---|---|---|
text | String |
ToolCallStart
The model has started a tool call, but the arguments are still streaming in.
Use this to show early UI feedback (e.g. "preparing read_file…") before the full [ToolCallComplete] arrives with parsed arguments.
Not every provider emits this — Ollama delivers tool calls fully formed, so you may only receive [ToolCallComplete]. Always treat this event as optional.
Constructor
ToolCallStart({required this.id, required this.name})Properties
| Property | Type | Description |
|---|---|---|
id | ToolCallId | |
name | String |
ToolCallComplete
A fully-formed tool call with parsed arguments, ready to execute.
Constructor
ToolCallComplete(this.toolCall)Properties
| Property | Type | Description |
|---|---|---|
toolCall | ToolCall |
UsageInfo
Token usage reported by the LLM after a response.
[cacheReadTokens] and [cacheCreationTokens] surface provider-native prompt caching statistics when available. Both are nullable: null means the provider did not report the field (e.g. Ollama, or a cache miss on a provider that omits zeroed fields). Distinguish "not reported" from "reported as zero" — that distinction is the difference between a passive read and an unsupported provider.
inputTokens reflects only the uncached input tokens billed at the provider's standard rate. Cache reads are billed separately (Anthropic: 0.1× input price; OpenAI: ~50% discount). Total billed input across the request is roughly: inputTokens + (cacheReadTokens ?? 0) + (cacheCreationTokens ?? 0).
Constructor
UsageInfo({
required this.inputTokens,
required this.outputTokens,
this.cacheReadTokens,
this.cacheCreationTokens,
})Properties
| Property | Type | Description |
|---|---|---|
inputTokens | int | |
outputTokens | int | |
cacheReadTokens | int? | |
cacheCreationTokens | int? | |
totalTokens | int get | |
totalTokens | int get |
ToolCall
A tool invocation requested by the model.
Constructor
ToolCall({
required this.id,
required this.name,
required this.arguments,
this.description = '',
this.thoughtSignature,
})Properties
| Property | Type | Description |
|---|---|---|
id | ToolCallId | |
name | String | |
arguments | Map<String, dynamic> | |
description | String | |
thoughtSignature | String? | Provider-specific opaque token that must be echoed back on the next request. Currently set only by the Gemini provider when the model is in thinking mode; null for all other providers. See https://ai.google.dev/gemini-api/docs/thought-signatures. |