reference
Message types
mantis-agent-sdk exposes two parallel shapes:
- Flat shape (
SDKMessagefamily) — matches the Claude Agent SDK exactly. Yielded byquery()andclient.query(). - Internal shape (
Messagefamily) — what the runtime uses internally. Imported asAssistantMessage,UserMessage, etc.
You can mostly work with the flat shape and never touch the internal one.
Flat shape (SDKMessage)
from mantis_agent import (
SDKAssistantMessage,
SDKCompactBoundaryMessage,
SDKMessage,
SDKPermissionDenial,
SDKResultMessage,
SDKStatusMessage,
SDKSystemMessage,
SDKUserMessage,
)Every yielded value from query() has a .type attribute:
.type |
Class | What it represents |
|---|---|---|
"assistant" |
SDKAssistantMessage |
A completed assistant turn. |
"user" |
SDKUserMessage |
Tool results threaded back as a user turn. |
"system" |
SDKSystemMessage |
Internal event (compact, MCP elicit/sample request, etc). |
"result" |
SDKResultMessage |
Final result with cost / usage / stop reason. |
"status" |
SDKStatusMessage |
Progress / status update. |
"compact_boundary" |
SDKCompactBoundaryMessage |
Compaction occurred at this point. |
"permission_denial" |
SDKPermissionDenial |
Surfaced into result.permission_denials. |
SDKAssistantMessage
@dataclass
class SDKAssistantMessage:
type: Literal["assistant"]
message: dict # {"role":"assistant","content":[block_dict, ...]}
session_id: str
parent_tool_use_id: str | Nonemessage["content"] is a list of block dicts:
{"type":"text","text":...}{"type":"thinking","text":...}{"type":"tool_use","id":...,"name":...,"input":{...}}
SDKResultMessage
@dataclass
class SDKResultMessage:
type: Literal["result"]
session_id: str
stop_reason: str # end_turn / max_turns / max_tokens / max_usd / cancelled
total_cost_usd: float
modelUsage: dict[str, ModelUsage]
duration_ms: int
permission_denials: list[SDKPermissionDenial]
error: str | NoneInternal shape (Message)
from mantis_agent import (
AssistantMessage,
Message,
SystemMessage as InternalSystemMessage,
UserMessage,
)These are msgspec.Struct types matching Anthropic's message shape but
implementation-internal. Use them when you need to feed a pre-built
transcript into query(prompt=[...]):
from mantis_agent import AssistantMessage, UserMessage, TextBlock
seed = [
UserMessage(role="user", content=[TextBlock(text="hi")]),
AssistantMessage(role="assistant", content=[TextBlock(text="hello!")]),
]
async for msg in query(prompt=seed, options={...}):
...Content blocks
Both shapes share the same block types:
from mantis_agent import (
TextBlock,
ThinkingBlock,
ToolUseBlock,
ToolResultBlock,
ContentBlock,
)| Block | type |
|---|---|
TextBlock(text) |
"text" |
ThinkingBlock(text) |
"thinking" |
ToolUseBlock(id, name, input) |
"tool_use" |
ToolResultBlock(tool_use_id, content, is_error=False) |
"tool_result" |
All blocks implement .to_dict() for serialisation.
Usage and cost
from mantis_agent import Usage, ModelUsage
@dataclass
class Usage:
input_tokens: int
output_tokens: int
@dataclass
class ModelUsage:
model: str
input_tokens: int
output_tokens: int
cost_usd: floatModelUsage is what SDKResultMessage.modelUsage is keyed by model. See
Budget for how cost is computed.