Use this file to discover all available pages before exploring further.
Message and Event are the two fundamental data structures in AgentScope.
Message — the unit of inter-agent communication and persistence. Each Msg represents a complete conversation turn that is stored in context and exchanged between agents.
Event — the unit of frontend interaction and streaming. Events carry incremental progress updates (text tokens, tool call fragments, permission requests) and drive real-time UIs and human-in-the-loop workflows.
A sequence of events produced during a single reply call accumulates into exactly one assistant Msg. This guarantees that the complete message state is always recoverable from its event stream.
A Msg represents a single turn in a conversation — a user input, an assistant response, or a system instruction, carrying structured content as a list of typed blocks.
One assistant message corresponds to one complete reply cycle of the agent (repeated reasoning and acting until a final response is produced).
Message content is composed of typed blocks. Each block represents a distinct piece of information:
Block
Description
Allowed In
TextBlock
Plain text content
user, assistant, system
DataBlock
Binary data (images, audio) via base64 or URL
user, assistant
ThinkingBlock
Model reasoning (chain-of-thought)
assistant
ToolCallBlock
A tool invocation with name, input, and state
assistant
ToolResultBlock
The output of a tool execution
assistant
HintBlock
Instructions injected into the loop as user context
assistant
Role constraints are enforced at construction: user messages can only contain TextBlock and DataBlock; system messages can only contain TextBlock; assistant messages can contain all block types.
AgentScope provides three shortcut factory functions for quickly creating messages with the correct role, without manually specifying role or wrapping content into blocks:
Factory
Role
Allowed Content
UserMsg(name, content)
user
str or list[TextBlock | DataBlock]
AssistantMsg(name, content)
assistant
str or list[ContentBlock]
SystemMsg(name, content)
system
str or list[TextBlock]
When content is a plain string, it is automatically wrapped into a TextBlock.
from agentscope.message import UserMsg, AssistantMsg, SystemMsg# User message — text and optional imagesuser_msg = UserMsg(name="user", content="What's in this image?")# User message with multimodal contentfrom agentscope.message import TextBlock, DataBlock, Base64Sourceuser_msg = UserMsg( name="user", content=[ TextBlock(text="Describe this image:"), DataBlock(source=Base64Source(data="...", media_type="image/png")), ],)# System message — text onlysystem_msg = SystemMsg(name="system", content="You are a helpful assistant.")# Assistant message — all block types allowedassistant_msg = AssistantMsg(name="agent", content="Here is the result...")
Msg provides helper methods to extract specific block types:
Method
Returns
get_text_content(separator="\n")
Concatenated text from all TextBlocks, or None
get_content_blocks(block_type)
Filtered list of blocks by type
has_content_blocks(block_type)
True if blocks of the given type exist
# Get all text contenttext = msg.get_text_content()# Get all tool callstool_calls = msg.get_content_blocks("tool_call")# Check if message has tool resultsif msg.has_content_blocks("tool_result"): ...
Events are the streaming counterpart of messages. While the agent executes, it yields a sequence of AgentEvent objects that represent incremental progress — text tokens arriving, tool calls being constructed, results streaming back. Each event is lightweight and self-contained.
Every event carries a reply_id that links it to the message being constructed. Within a reply, block_id or tool_call_id identifies which content block an event belongs to. Events follow a start → delta → end pattern for each content block:All events within the same reply share the same reply_id. Within a reply, use block_id to correlate text/thinking/data block events, and tool_call_id to correlate tool call and tool result events.
Events and messages are not independent — they are two views of the same data. Every event produced by reply_stream can be applied to a Msg via append_event(), reconstructing the complete message incrementally. This guarantees that the final message state is fully recoverable from the event stream alone.
from agentscope.message import Msg, AssistantMsgmsg = None# Accumulate events into the messageasync for event in agent.reply_stream(user_msg): if isinstance(event, ReplyStartEvent): # Create a new message when the reply starts msg = AssistantMsg(name=event.name, content=[], id=event.reply_id) else: # For all other events, append to the message to reconstruct its state msg.append_event(event)
The append_event method handles all event types:
Event Type
Effect on Msg
ReplyEndEvent
Sets finished_at timestamp
TextBlockStartEvent
Appends a new empty TextBlock
TextBlockDeltaEvent
Concatenates delta to the block’s text
DataBlockStartEvent
Appends a new empty DataBlock
DataBlockDeltaEvent
Concatenates data to the block’s base64 content
ThinkingBlockStartEvent
Appends a new empty ThinkingBlock
ThinkingBlockDeltaEvent
Concatenates delta to the block’s thinking text
ToolCallStartEvent
Appends a new ToolCallBlock with empty input
ToolCallDeltaEvent
Concatenates delta to the tool call’s input
ToolResultStartEvent
Appends a new ToolResultBlock with empty output
ToolResultTextDeltaEvent
Appends text to the tool result’s output
ToolResultDataDeltaEvent
Appends a binary data block to the tool result’s output
ToolResultEndEvent
Sets the tool result’s final state
RequireUserConfirmEvent
Updates tool call states to ASKING
ExternalExecutionResultEvent
Appends ToolResultBlocks to content
This design enables flexible deployment: a backend can stream events over WebSocket to a frontend, which reconstructs the message client-side. If the connection drops, replaying the event sequence from any checkpoint restores the exact message state.
A TypeScript version of the message and event primitives is available on npm, so frontends can reconstruct messages from the event stream with the same appendEvent API:
pnpm install @agentscope-ai/agentscope
import { AssistantMsg, ReplyStartEvent } from "@agentscope-ai/agentscope/message";let msg: AssistantMsg | null = null;for await (const event of stream) { if (event.type === "REPLY_START") { msg = new AssistantMsg({ name: event.name, content: [], id: event.reply_id }); } else { msg?.appendEvent(event); }}