Appearance
快速上手
这一页用 AgentScope 2.x 构建一个最小但完整的 Agent:它接收一条用户消息,调用真实 LLM,返回一段 中文回复。你会同时看到同步的 reply 与流式的 reply_stream 两种调用方式,并理解它们返回的 Msg 结构。
版本基线:本文示例以
agentscope 2.0.4(PyPI,2026-07-07)为准,要求 Python>=3.11。 1.x 的agent(msg)、ReActAgent等 API 已在 2.x 移除,本页不出现。
调用真实 LLM 会产生费用
本页示例会调用真实模型 API,按 provider 计费产生费用。如果想零成本跑通,可改用下方 Ollama 本地模型 变体,它在本地推理、不需要 API key、不产生云端费用。
目标
完成后你会接触到四个关键接口:
- 用
Agent类组装一个带system_prompt和model的 Agent。 - 用
UserMsg构造用户消息。 - 用
await agent.reply(...)获取完整的Msg,并用get_text_content()取出文本。 - 用
async for event in agent.reply_stream(...)逐字打印流式回复,并用Msg.append_event重建完整消息。
前端类比
可以把 Agent 类比为一个带生命周期的 React Component——构造参数是 props,reply 是一次 await 的同步渲染,reply_stream 是 SSE chunk 流。Msg 类比为强类型的消息对象,Toolkit 类比为按需聚合的 hooks。
AgentScope 原生语义:Agent 是无状态 ReAct 循环引擎。reply() 是协程,内部跑完整个 ReAct 循环后返回最终 Msg;reply_stream() 也是协程,但异步产出结构化事件(ReplyStartEvent、 TextBlockDeltaEvent、ReplyEndEvent 等)。Msg 不是普通字符串,而是由若干 ContentBlock (TextBlock / ToolCallBlock / ToolResultBlock 等)组成的列表,get_text_content() 只是 把其中所有 TextBlock 拼接出来方便展示。
1. 准备
- 已按 安装与环境 装好
agentscope 2.0.4,且 Python>=3.11。 - 已设置对应 provider 的环境变量(下方示例用
os.environ读取,不要把 key 写进代码):
bash
# DashScope(通义千问,本页默认)
export DASHSCOPE_API_KEY="你的密钥"
# 或 OpenAI
export OPENAI_API_KEY="你的密钥"
# 或 Ollama:先本地启动 ollama 服务并拉取模型,无需 key
# ollama pull qwen2.5:7b2. 配置模型
示例默认使用 DashScope 的 qwen-plus。它支持 tool calling,方便后续教程在同一个 Agent 上 叠加工具调用。你也可以改用 OpenAI 的 gpt-4.1 或本地 Ollama 的 qwen2.5:7b,三者仅 model 与 credential 不同,Agent 构造方式完全一致。
3. 最小 Agent
下面是一个完整可跑的脚本。把它存为 quickstart.py,设置好环境变量后执行 python quickstart.py。
python
import asyncio
import os
from agentscope.agent import Agent
from agentscope.credential import DashScopeCredential
from agentscope.message import UserMsg
from agentscope.model import DashScopeChatModel
async def main():
agent = Agent(
name="my_agent",
system_prompt="You are a helpful assistant.",
model=DashScopeChatModel(
credential=DashScopeCredential(
api_key=os.environ["DASHSCOPE_API_KEY"],
),
model="qwen-plus",
),
)
result = await agent.reply(
UserMsg(name="user", content="用一句话介绍 AgentScope"),
)
print(result.get_text_content())
asyncio.run(main())python
import asyncio
import os
from agentscope.agent import Agent
from agentscope.credential import OpenAICredential
from agentscope.message import UserMsg
from agentscope.model import OpenAIChatModel
async def main():
agent = Agent(
name="my_agent",
system_prompt="You are a helpful assistant.",
model=OpenAIChatModel(
credential=OpenAICredential(
api_key=os.environ["OPENAI_API_KEY"],
),
model="gpt-4.1",
),
)
result = await agent.reply(
UserMsg(name="user", content="用一句话介绍 AgentScope"),
)
print(result.get_text_content())
asyncio.run(main())python
import asyncio
from agentscope.agent import Agent
from agentscope.message import UserMsg
from agentscope.model import OllamaChatModel
async def main():
agent = Agent(
name="my_agent",
system_prompt="You are a helpful assistant.",
model=OllamaChatModel(
model="qwen2.5:7b",
),
)
result = await agent.reply(
UserMsg(name="user", content="用一句话介绍 AgentScope"),
)
print(result.get_text_content())
asyncio.run(main())reply 是协程,必须用 await 调用,并在顶层用 asyncio.run(main()) 驱动。直接写 agent.reply(msg) 而不 await 只会得到一个 coroutine 对象,不会真正执行。
4. 流式回复
reply_stream 返回一个异步迭代器,逐个产出事件。文本增量由 TextBlockDeltaEvent 携带,可以 边收边打印;同时用 Msg.append_event 把每个事件应用到一个空消息上,最终重建出与 reply 等价的完整 Msg。
python
import asyncio
import os
from agentscope.agent import Agent
from agentscope.credential import DashScopeCredential
from agentscope.event import ReplyStartEvent, TextBlockDeltaEvent, ReplyEndEvent
from agentscope.message import Msg, UserMsg
from agentscope.model import DashScopeChatModel
async def main():
agent = Agent(
name="my_agent",
system_prompt="You are a helpful assistant.",
model=DashScopeChatModel(
credential=DashScopeCredential(
api_key=os.environ["DASHSCOPE_API_KEY"],
),
model="qwen-plus",
),
)
reply_msg = None
async for event in agent.reply_stream(
UserMsg(name="user", content="用一句话介绍 AgentScope"),
):
# ReplyStartEvent 携带 reply_id,用它建立空消息,后续事件逐步填充
if isinstance(event, ReplyStartEvent):
reply_msg = Msg(
name="my_agent",
content=[],
role="assistant",
id=event.reply_id,
)
# 文本增量逐字打印(仅用于展示)
if isinstance(event, TextBlockDeltaEvent):
print(event.delta, end="", flush=True)
# 把每个事件应用到消息上,逐步重建完整 Msg
if reply_msg is not None:
reply_msg.append_event(event)
print() # 换行
print("完整回复:", reply_msg.get_text_content())
asyncio.run(main())append_event 会按事件类型更新 content、finished_at 与 usage:TEXT_BLOCK_START 追加空 TextBlock,TEXT_BLOCK_DELTA 往对应 block 追加文本,REPLY_END 盖时间戳, MODEL_CALL_END 累加 token 用量。因此重建出的 reply_msg 与 reply 直接返回的 Msg 结构一致。
5. 期望输出
同步版本会打印一段中文介绍,例如:
AgentScope 是一个由阿里巴巴开源的多智能体框架,专注于构建可观察、可理解、可信赖的 LLM 应用。流式版本会逐字打印同等内容,最后再以 完整回复:... 重复一次完整文本。具体措辞由模型决定, 不必与示例完全一致。
6. 关键 API 解释
Agent 构造参数
name:Agent 名称,会作为消息的name字段,便于在多 Agent 场景区分发送者。system_prompt:系统提示词,决定 Agent 的角色与行为约束,只允许TextBlock。model:模型客户端实例,决定调用哪个 provider。2.x 不再用字符串模型名,而是注入DashScopeChatModel/OpenAIChatModel/OllamaChatModel等封装好的客户端。
reply vs reply_stream
| 接口 | 返回 | 适用场景 |
|---|---|---|
await reply() | 最终 Msg | 后台任务、不需要实时展示进度 |
reply_stream() | 异步事件流(AgentEvent) | 聊天界面逐字输出、工具调用进度展示 |
两者跑的是同一个 ReAct 循环,区别只在结果交付方式。流式场景下,ReplyStartEvent 先到, 随后是若干 TextBlockDeltaEvent,最后 ReplyEndEvent 收尾。
UserMsg 与 Msg
UserMsg(name, content) 是创建用户消息的快捷函数,content 传字符串会被自动包成单个 TextBlock。Msg 是底层类,content 是 list[ContentBlock],role 为 "user" | "assistant" | "system"。get_text_content() 把所有 TextBlock 用换行符拼接 返回字符串,没有文本 block 时返回 None。
7. 常见错误
KeyError: 'DASHSCOPE_API_KEY'
环境变量未设置。确认已在当前 shell export,或写在 .env 并由启动脚本加载。不要把 key 硬编码进源码或提交到 Git。
SyntaxError 或 TypeError: 'coroutine' ... was never awaited
通常是 Python 版本低于 3.11,或调用了 agent.reply(msg) 却没有 await。reply 是协程, 必须 await;顶层用 asyncio.run(main()) 驱动。
模型不支持 tool calling
本页示例没有用工具,但后续教程会在同一个 Agent 上叠加工具调用。建议从一开始就选支持 tool calling 的模型(qwen-plus、gpt-4.1、qwen2.5:7b 均支持),避免后面换模型。
误用 1.x 调用方式
agent(msg)(__call__)、ReActAgent 在 2.x 已移除。2.x 统一用 Agent + reply / reply_stream。详见 1.x 到 2.x 迁移。
先修
- 核心概念 - 理解 Agent、Msg、Event 的关系
下一步
- 消息与事件 - 深入
Msg、ContentBlock与事件类型