Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agentscope.io/llms.txt

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.

Message

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).

Structure

The Msg class has the following core fields:
FieldTypeDescription
idstrUnique message identifier
namestrName of the sender
role"user" | "assistant" | "system"The sender’s role
contentlist[ContentBlock]Ordered list of content blocks
metadatadictArbitrary key-value metadata
created_atstrISO 8601 timestamp of creation
finished_atstr | NoneISO 8601 timestamp when the message was finalized
usageUsageToken usage statistics (for assistant messages)

Content Blocks

Message content is composed of typed blocks. Each block represents a distinct piece of information:
BlockDescriptionAllowed In
TextBlockPlain text contentuser, assistant, system
DataBlockBinary data (images, audio) via base64 or URLuser, assistant
ThinkingBlockModel reasoning (chain-of-thought)assistant
ToolCallBlockA tool invocation with name, input, and stateassistant
ToolResultBlockThe output of a tool executionassistant
HintBlockInstructions injected into the loop as user contextassistant
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.

Create Messages

AgentScope provides three shortcut factory functions for quickly creating messages with the correct role, without manually specifying role or wrapping content into blocks:
FactoryRoleAllowed Content
UserMsg(name, content)userstr or list[TextBlock | DataBlock]
AssistantMsg(name, content)assistantstr or list[ContentBlock]
SystemMsg(name, content)systemstr 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 images
user_msg = UserMsg(name="user", content="What's in this image?")

# User message with multimodal content
from agentscope.message import TextBlock, DataBlock, Base64Source
user_msg = UserMsg(
    name="user",
    content=[
        TextBlock(text="Describe this image:"),
        DataBlock(source=Base64Source(data="...", media_type="image/png")),
    ],
)

# System message — text only
system_msg = SystemMsg(name="system", content="You are a helpful assistant.")

# Assistant message — all block types allowed
assistant_msg = AssistantMsg(name="agent", content="Here is the result...")

Access Content

Msg provides helper methods to extract specific block types:
MethodReturns
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 content
text = msg.get_text_content()

# Get all tool calls
tool_calls = msg.get_content_blocks("tool_call")

# Check if message has tool results
if msg.has_content_blocks("tool_result"):
    ...

Event

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.

Event Lifecycle

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.

Event Types

All events inherit from EventBase which provides common fields:
FieldTypeDescription
idstrUnique event identifier
created_atstrISO 8601 timestamp
Events are grouped by category below. Every event also carries a reply_id field (except where noted) that links it to the message being constructed.
ReplyStartEvent — Agent begins a new reply.
FieldTypeDescription
reply_idstrID of the reply message
session_idstrID of the session
namestrAgent name
rolestrAgent role (default "assistant")
ReplyEndEvent — Agent finishes the reply.
FieldTypeDescription
reply_idstrID of the reply message
session_idstrID of the session
ExceedMaxItersEvent — Agent reached the maximum reasoning-acting iterations.
FieldTypeDescription
reply_idstrID of the reply message
namestrAgent name
TextBlockStartEvent — A new text block begins.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the text block
TextBlockDeltaEvent — Incremental text content arrives.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the text block
deltastrIncremental text content
TextBlockEndEvent — The text block is complete.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the text block
ThinkingBlockStartEvent — A new thinking block begins.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the thinking block
ThinkingBlockDeltaEvent — Incremental thinking content arrives.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the thinking block
deltastrIncremental thinking text
ThinkingBlockEndEvent — The thinking block is complete.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the thinking block
DataBlockStartEvent — A new data block begins (image, audio, etc.).
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the data block
media_typestrMIME type (e.g. "image/png")
DataBlockDeltaEvent — Incremental binary data arrives.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the data block
datastrIncremental base64-encoded data
media_typestrMIME type
DataBlockEndEvent — The data block is complete.
FieldTypeDescription
reply_idstrID of the reply message
block_idstrUnique identifier of the data block
ToolCallStartEvent — The agent begins a tool call.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrUnique identifier of the tool call
tool_call_namestrName of the tool being called
ToolCallDeltaEvent — Incremental tool call input arrives.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrUnique identifier of the tool call
deltastrIncremental JSON fragment of tool input
ToolCallEndEvent — The tool call input is complete.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrUnique identifier of the tool call
ToolResultStartEvent — Tool execution begins.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrID of the corresponding tool call
tool_call_namestrName of the tool
ToolResultTextDeltaEvent — Incremental text output from the tool.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrID of the corresponding tool call
deltastrIncremental text content
ToolResultDataDeltaEvent — Binary data output from the tool.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrID of the corresponding tool call
block_idstrUnique identifier of the data block
media_typestrMIME type of the content
datastr | NoneBase64-encoded data (mutually exclusive with url)
urlstr | NoneURL pointing to the content (mutually exclusive with data)
ToolResultEndEvent — Tool execution is complete.
FieldTypeDescription
reply_idstrID of the reply message
tool_call_idstrID of the corresponding tool call
stateToolResultStateFinal state: SUCCESS, ERROR, INTERRUPTED, DENIED, or RUNNING
ModelCallStartEvent — A model API call begins.
FieldTypeDescription
reply_idstrID of the reply message
model_namestrName of the model being called
ModelCallEndEvent — A model API call completes.
FieldTypeDescription
reply_idstrID of the reply message
input_tokensintNumber of input tokens consumed
output_tokensintNumber of output tokens generated
RequireUserConfirmEvent — Agent pauses for user confirmation.
FieldTypeDescription
reply_idstrID of the reply message
tool_callslist[ToolCallBlock]Tool calls pending user confirmation
RequireExternalExecutionEvent — Agent pauses for external execution.
FieldTypeDescription
reply_idstrID of the reply message
tool_callslist[ToolCallBlock]Tool calls to be executed externally
UserConfirmResultEvent — User provides confirmation results (input event).
FieldTypeDescription
reply_idstrID of the reply message
confirm_resultslist[ConfirmResult]Confirmation results for each pending tool call
ExternalExecutionResultEvent — External system provides execution results (input event).
FieldTypeDescription
reply_idstrID of the reply message
execution_resultslist[ToolResultBlock]Results returned by the external executor

Reconstruct Messages from 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, AssistantMsg

msg = None

# Accumulate events into the message
async 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 TypeEffect on Msg
ReplyEndEventSets finished_at timestamp
TextBlockStartEventAppends a new empty TextBlock
TextBlockDeltaEventConcatenates delta to the block’s text
DataBlockStartEventAppends a new empty DataBlock
DataBlockDeltaEventConcatenates data to the block’s base64 content
ThinkingBlockStartEventAppends a new empty ThinkingBlock
ThinkingBlockDeltaEventConcatenates delta to the block’s thinking text
ToolCallStartEventAppends a new ToolCallBlock with empty input
ToolCallDeltaEventConcatenates delta to the tool call’s input
ToolResultStartEventAppends a new ToolResultBlock with empty output
ToolResultTextDeltaEventAppends text to the tool result’s output
ToolResultDataDeltaEventAppends a binary data block to the tool result’s output
ToolResultEndEventSets the tool result’s final state
RequireUserConfirmEventUpdates tool call states to ASKING
ExternalExecutionResultEventAppends 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.

TypeScript Support

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

Example: Streaming UI

A typical pattern for building a streaming interface:
from agentscope.message import AssistantMsg, UserMsg
from agentscope.event import (
    ReplyStartEvent,
    TextBlockDeltaEvent,
    ToolCallStartEvent,
    ToolResultEndEvent,
    ReplyEndEvent,
)

msg = None

async for event in agent.reply_stream(UserMsg("user", "Fix the bug")):
    if isinstance(event, ReplyStartEvent):
        msg = AssistantMsg(name=event.name, content=[], id=event.reply_id)

    elif isinstance(event, TextBlockDeltaEvent):
        print(event.delta, end="", flush=True)

    elif isinstance(event, ToolCallStartEvent):
        print(f"\n[Calling {event.tool_call_name}...]")

    elif isinstance(event, ToolResultEndEvent):
        print(f"[Tool finished: {event.state}]")

    elif isinstance(event, ReplyEndEvent):
        print("\n[Done]")

    # Always accumulate into the message
    if msg is not None:
        msg.append_event(event)

# msg now contains the complete reply

Further Reading

Agent

How the agent produces events and messages in the ReAct loop

Context

How messages are stored, compressed, and offloaded