图片

2026 年聊 AI Agent,绕不开三个名字:LangGraph、AgentScope 2.0、DeepSeek Harness。

但真正让技术人纠结的,从来不是“哪个更火”,而是同一件事——搭一个能自己干活的多智能体——三个框架给出了三种完全不同的答案。

我最近把 AgentScope 2.0 从头跑了一遍。这篇文章用一份 15 分钟实操加一张对比表,讲清楚三者的本质差异,以及你该怎么选。

01 真正难选的不是框架,是三种不同的“编排哲学”

先给一个判断:三个框架的差别,不在功能多少,而在它们默认相信谁。

LangGraph 相信“流程”。它把你的业务画成一张图(节点加边),每一步谁先谁后、哪里需要人工审批、哪里可以自动,都由开发者预先定义。它的招牌能力是持久化执行:中途崩溃、服务器重启,都能从检查点恢复。

AgentScope 2.0 相信“模型”。它不让你画流程,而是给你一个 ReAct 循环(推理、行动、观察),让模型自己决定下一步干什么;框架的重点是管住边界——什么工具能用、什么权限能碰、代码在什么沙箱里跑。

DeepSeek Harness 相信“拆装”。它把自己定位成“元框架”,用 Cordis 插件内核把模型、工具、沙箱、会话、UI 全拆成插件,你在配置里自由组合,招牌主张就是“一切皆插件”。

一句话总结:LangGraph 在解决“流程怎么不丢”,AgentScope 2.0 在解决“模型怎么不乱来”,DeepSeek Harness 在解决“框架怎么随便改”。

02 AgentScope 2.0:它是什么,不是什么

用三句话把它说清楚。

一句人话:AgentScope 2.0 是阿里通义实验室开源的智能体框架,核心是“ReAct 智能体 + 工具系统 + 权限沙箱 + 记忆”,目标是让模型在受控边界内自主干活。

一句排除:它不是流程编排器(不用画状态图),不是低代码平台,也不绑定某一家模型——OpenAI、Anthropic、Gemini、DashScope、DeepSeek、Kimi、xAI、Ollama 都有内置接入。

一句关系:对后端开发者来说,它最特别的是“生产护栏”出厂自带:5 种权限模式、8 种沙箱后端(本地、Docker、E2B、K8s)、事件流可观测、分布式多租户,而且 Python、Java 双版本。

它同时支持:工具函数(同步/异步/流式/并行)、MCP 服务器、长期记忆、结构化输出、运行中实时中断。核心智能体是开箱即用的 ReActAgent,也提供 AgentBase / ReActAgentBase 让你从零自定义。

03 15 分钟实操:装好、跑通、加工具

这一步我全程在终端跑过,按顺序做即可。

Step 1 安装(Python 3.11+)

pip install agentscope

用 uv 更省心:

uv pip install agentscope

一行验证装好没有:

python -c "import agentscope; print(agentscope.__version__)"

图片

Step 2 写一个最小 ReAct 智能体

核心就四件事:名字、人设、模型、工具。下面是官方快速开始简化版,让它用 Python 跑一个 Hello World。

# -*- coding: utf-8 -*-
"""最小 ReAct 智能体:Reasoning + Acting 循环。
AgentScope 2.x 里**没有**单独的 ``ReActAgent`` 类:``Agent`` 本身就是
ReAct 循环(reason → act → observe → reason → …),循环行为由
``react_config`` 控制。所以「最小 ReAct 智能体」=
    Agent + 工具(Toolkit) + ReActConfig(max_iters=...)
本示例给 Agent 两个只读工具,并问一个必须「先查天气、再换算单位」的
问题,从而触发两轮工具调用(Act)与结果观察(Observe)。
运行::
    python react_agent.py
密钥优先读环境变量 ``DASHSCOPE_API_KEY``,其次读本目录的 ``.env``。
"""
import asyncio
import os
from pathlib import Path
from agentscope.agent import Agent, ReActConfig
from agentscope.credential import DashScopeCredential
from agentscope.event import (
    ReplyEndEvent,
    ReplyFinishedReason,
    TextBlockDeltaEvent,
    ThinkingBlockDeltaEvent,
    ToolCallDeltaEvent,
    ToolCallStartEvent,
    ToolResultEndEvent,
    ToolResultTextDeltaEvent,
)
from agentscope.message import UserMsg
from agentscope.model import DashScopeChatModel
from agentscope.tool import FunctionTool, Toolkit
# ---------------------------------------------------------------- 工具(Act)
# 普通 Python 函数即可,FunctionTool 会从函数签名 + docstring 自动生成
# JSON Schema。is_read_only=True 表示无副作用,权限引擎直接放行,
# 不会停下来问你「是否允许调用」。
def get_weather(city: str) -> str:
    """查询指定城市的实时天气。
    Args:
        city: 城市名,例如 "成都"
    """
    # 示例用假数据,换成真实 API 调用即可
    mock = {
        "成都": "多云,气温 18℃",
        "北京": "晴,气温 12℃",
    }
    return mock.get(city, f"暂无 {city} 的天气数据")
def celsius_to_fahrenheit(celsius: float) -> str:
    """把摄氏度换算成华氏度。
    Args:
        celsius: 摄氏温度数值
    """
    return f"{celsius:g}℃ = {celsius * 9 / 5 + 32:.1f}℉"
# ------------------------------------------------- ReAct 轨迹打印(可选)
async def run(agent: Agent, question: str) -> str:
    """跑一轮对话,并把 ReAct 的每一步打印出来。
    事件流里的关键事件对应 ReAct 的三个环节:
    - ``ThinkingBlockDeltaEvent`` / ``TextBlockDeltaEvent`` → Reasoning
    - ``ToolCallStartEvent`` / ``ToolCallDeltaEvent``        → Acting
    - ``ToolResultEndEvent``                                 → Observation
    """
    names: dict[str, str] = {}
    args: dict[str, str] = {}
    results: dict[str, str] = {}
    # 每次模型调用都会另起一个 text block:只保留最后一个,即最终答案
    answer: list[str] = []
    answer_block: str | None = None
    async for ev in agent.reply_stream(
        inputs=UserMsg(name="user", content=question),
    ):
        if isinstance(ev, ToolCallStartEvent):
            names[ev.tool_call_id] = ev.tool_call_name
            args[ev.tool_call_id] = ""
            results[ev.tool_call_id] = ""
        elif isinstance(ev, ToolCallDeltaEvent):
            args[ev.tool_call_id] += ev.delta
        elif isinstance(ev, ToolResultTextDeltaEvent):
            results[ev.tool_call_id] += ev.delta
        elif isinstance(ev, ToolResultEndEvent):
            print(f"  [Act] {names.pop(ev.tool_call_id, '?')}({args.pop(ev.tool_call_id, '')})")
            print(f"  [Obs] {results.pop(ev.tool_call_id, '').strip()}")
        elif isinstance(ev, ThinkingBlockDeltaEvent):
            # 仅当开启 thinking_enable 时才会出现
            print(f"  [Think] {ev.delta}")
        elif isinstance(ev, TextBlockDeltaEvent):
            if ev.block_id != answer_block:
                answer_block, answer[:] = ev.block_id, []
            answer.append(ev.delta)
        elif (
            isinstance(ev, ReplyEndEvent)
            and ev.finished_reason != ReplyFinishedReason.COMPLETED
        ):
            print(f"  [End] finished_reason={ev.finished_reason}")
    return "".join(answer)
def _load_env_file() -> None:
    """读取脚本同目录的 ``.env``,已存在的环境变量优先。"""
    env_file = Path(__file__).with_name(".env")
    if not env_file.is_file():
        return
    for line in env_file.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        key, value = line.split("=", 1)
        os.environ.setdefault(key.strip(), value.strip().strip("\"'"))
async def main() -> None:
    _load_env_file()
    api_key = os.environ.get("DASHSCOPE_API_KEY")
    if not api_key:
        raise SystemExit("请先 export DASHSCOPE_API_KEY=sk-...,或写入 examples/ggs/.env")
    agent = Agent(
        name="ReAct",
        # 明确要求「用工具」而不是心算,这样才看得到多轮 ReAct 循环
        system_prompt=(
            "你是一个严谨的助手。需要外部数据时必须调用工具获取,不要凭记忆"
            "编造;所有单位换算也必须调用工具完成,不要自己心算。"
        ),
        model=DashScopeChatModel(
            credential=DashScopeCredential(api_key=api_key),
            model="qwen3.7-plus",
            stream=True,
            # 想看到 Reasoning 的思考块,可打开 thinking_enable
            # parameters=DashScopeChatModel.Parameters(thinking_enable=True),
        ),
        toolkit=Toolkit(
            tools=[
                FunctionTool(get_weather, is_read_only=True),
                FunctionTool(celsius_to_fahrenheit, is_read_only=True),
            ],
        ),
        # ReAct 循环控制:一个 reply 内最多几轮 reason-act(默认 50)
        react_config=ReActConfig(max_iters=5),
    )
    question = "成都现在气温多少华氏度?"
    print(f"user: {question}")
    answer = await run(agent, question)
    print(f"\n{agent.name}: {answer}")
asyncio.run(main())

图片

跑起来后,你会看到智能体先输出一次工具调用(执行 Python 代码),拿到结果后再给出最终回复——这就是一个完整的 ReAct 循环。

Step 3 想更快体验?直接跑终端 console

from agentscope.agent import Agent
from agentscope.console import launch_console
from agentscope.tool import Toolkit, Bash, Grep, Glob, Read, Write, Edit
from agentscope.credential import DashScopeCredential
from agentscope.model import DashScopeChatModel

import os, asyncio


async def main() -> None:
    agent = Agent(
        name="Friday",
        system_prompt="You're a helpful assistant named Friday.",
        model=DashScopeChatModel(
            credential=DashScopeCredential(
              api_key=os.environ["DASHSCOPE_API_KEY"]
            ),
            model="qwen3.7-plus",
        )
    )

    # Chat with the agent in the terminal — streamed output, tool-call
    # confirmation and Ctrl+C interruption are all handled for you
    await launch_console(agent)

asyncio.run(main())

图片

流式输出、工具调用确认、Ctrl+C 中断,全部开箱即用。

Step 4 给 Agent 配上“能干活”的工具

文件读写、搜索、命令执行这些高频工具是内置的,注册即用。

from agentscope.agent import Agent
from agentscope.credential import DashScopeCredential
from agentscope.model import DashScopeChatModel
from agentscope.tool import Toolkit, Bash, Grep, Glob, Read, Write, Edit
agent = Agent(
    name="Friday",
    system_prompt="You are a helpful assistant named Friday.",
    model=DashScopeChatModel(
        credential=DashScopeCredential(
            api_key=os.environ["DASHSCOPE_API_KEY"]
        ),
        model="qwen3.7-plus",
    ),
    toolkit=Toolkit(
        tools=[Bash(), Grep(), Glob(), Read(), Write(), Edit()]
    ),
)

到这一步,你的智能体已经能读代码、搜文件、执行命令、改文件——一个最小“能干活”的 Agent 就绪。

Step 5 给 Agent 配上长期记忆

from agentscope.agent import Agent
from agentscope.middleware import AgenticMemoryMiddleware
from agentscope.tool import Toolkit
from agentscope.workspace import LocalWorkspace
async with LocalWorkspace(workdir="./workspace") as workspace:
    agent = Agent(
        name="Friday",
        system_prompt=(
            "You are a helpful assistant named Friday. "
            "Use the provided tools whenever they help.\n\n"
            + await workspace.get_instructions()   # 把 workspace 说明注入系统提示
        ),
        model=...,  # 与第 3 节相同,此处省略
        toolkit=Toolkit(
            tools=await workspace.list_tools(),      # 文件工具来自 workspace
            skills_or_loaders=await workspace.list_skills(),
        ),
        middlewares=[
            AgenticMemoryMiddleware(
                workdir=workspace.workdir,
                backend=workspace.get_backend(),
            ),
        ],
        offloader=workspace,   # 把压缩后的上下文和超大工具结果卸载到磁盘
    )

我把我的爱好跟他说

图片

退出进程后,还是可以记得我的爱好

图片

Step 6 给 Agent 服务化,配上WEBUI

# server.py
import os
from pathlib import Path
import uvicorn
from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware
from agentscope.app import create_app
from agentscope.app.message_bus import InMemoryMessageBus
from agentscope.app.rag import LocalBlobStore
from agentscope.app.rag.knowledge_base_manager import CollectionPerKbManager
from agentscope.app.storage import AsyncSQLAlchemyStorage
from agentscope.app.workspace_manager import LocalWorkspaceManager
from agentscope.rag import (
    ApproxTokenChunker,
    ExcelParser,
    PDFParser,
    PPTParser,
    QdrantStore,
    TextParser,
    WordParser,
)
_HERE = Path(__file__).resolve().parent
_DB = os.environ.get("AGENTSCOPE_DB", str(_HERE / "agentscope.db"))
storage = AsyncSQLAlchemyStorage(f"sqlite+aiosqlite:///{_DB}")
app = create_app(
    storage=storage,
    message_bus=InMemoryMessageBus(),
    workspace_manager=LocalWorkspaceManager(basedir=str(_HERE / "workspaces")),
    # 不传这个,所有 /knowledge_bases/* 都会返回 503
    knowledge_base_manager=CollectionPerKbManager(
        storage=storage,
        vector_store=QdrantStore(path=str(_HERE / "qdrant_data")),
    ),
    knowledge_parsers=[
        TextParser(), PDFParser(), WordParser(), ExcelParser(), PPTParser(),
    ],
    knowledge_chunkers=[ApproxTokenChunker],
    blob_store=LocalBlobStore(root_dir=str(_HERE / "blobs")),
    # 前端跑在另一个 origin,不挂 CORS 的话预检 OPTIONS 全是 405
    extra_middlewares=[
        Middleware(
            CORSMiddleware,
            allow_origins=["*"], allow_methods=["*"], allow_headers=["*"],
        ),
    ],
)
if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8000)

图片

启动webui

cd examples/web_ui
pnpm install
pnpm dev

图片

浏览器打开后,在设置页填 server_url = http://127.0.0.1:8000 和你的用户名(这个用户名就是上面那个 X-User-ID),然后新建 Agent、选模型,就能聊了。

图片

给 Java 架构师的一句提示

AgentScope 同时发布了 Java 2.0:JDK 17 起步,Maven 引入 io.agentscope:agentscope-harness,从 HarnessAgent 开始;只想用轻量 ReAct 循环就用 agentscope-core。配置里写模型字符串、工作区、上下文压缩策略即可。

04 进阶:权限、沙箱与 Agent Team

入门只是热身。AgentScope 2.0 真正拉开差距的,是下面三块生产级能力。

1. 权限:5 种模式细粒度管控

每一次工具调用都可以设置权限模式:从完全自主、需要审批,到直接禁止。多智能体场景下,可以给不同 Agent 配不同权限等级,而不是一把钥匙开所有门。

2. 沙箱:8 种后端隔离代码执行

本地、Docker、E2B、K8s 等 8 种沙箱后端,限制 Agent 的代码执行和文件操作范围。这是它和“研究型框架”最大的分水岭——默认按生产安全设计。

3. Agent Team:多智能体怎么协作

和多智能体框架常见的“层层嵌套”不同,AgentScope 2.0 的团队模型是:leader 创建 team,worker 是独立会话、在同一服务上并发执行,leader 通过读会话流观察进度;成员之间用 Redis 做消息总线通信。

加上类型化事件流(运行过程可观测、可中断、可恢复),以及上下文自动压缩、长期记忆,一套“可信、可控、可审计”的底座基本齐了。

05 一张表看清三个框架

信息来自各自官方文档与公开发布资料(2026 年 9 月核对),同一维度并排列出,方便横向比较。

维度

AgentScope 2.0

LangGraph

DeepSeek Harness

出品方

阿里通义实验室

LangChain 团队

DeepSeek

编排哲学

弱编排:模型自主决策,框架管安全边界

强编排:图/状态机,节点加边预定义

元框架:一切皆插件,配置里自由组合

核心抽象

ReAct 智能体 + 事件流

图 + Checkpointer 检查点

Cordis 插件内核 + 工具契约

语言生态

Python、Java

Python、JS/TS

npm/TypeScript 为主

上手成本

pip 安装,20 行起

需理解状态图,学习曲线较陡

npx 一行起,深度定制需懂插件机制

安全边界

5 种权限模式 + 8 种沙箱后端

基础权限,靠检查点保证执行可靠

TS 工具契约 + Docker 沙箱

多智能体

Agent Team(leader-worker,Redis 总线)

图内子图/节点编排

子 Agent 以插件形式挂载

可观测性

类型化事件流

LangSmith 生态

Trajectory 轨迹,可回放、可分叉

成本优化

记忆压缩、上下文管理

依赖模型层/外部方案

KV Cache 优化,官方称省 80%+ Token

部署形态

本地/Serverless/K8s,多租户

单机强,分布式需自建或平台版

本地/私有部署,npm + GitHub

最适合

生产级开放任务、多租户、要安全边界

严格流程、人工审批、审计

深度定制 Agent 产品、省 Token、插件生态

06 三个最容易踩的误区

误区一:框架越“重”越安全。

有一定道理:AgentScope 2.0 权限加沙箱、DSH 的 Docker 隔离,确实比裸调模型安全。但“安全”是配置出来的,不是框架自带光环——权限模式设成“全自主”、沙箱用本地后端,照样裸奔。判断标准不是框架名,而是你的权限策略和沙箱配置。

误区二:“LangGraph 不适合生产”是误读。

它和 AgentScope 的差异是“防什么”:LangGraph 用检查点防的是执行丢状态,AgentScope 用权限沙箱防的是越权乱跑。如果你的业务是固定流程、要人工审批和审计,LangGraph 的持久化执行恰恰是生产刚需。

误区三:插件化就是万能。

DeepSeek Harness 的“一切皆插件”解决的是定制与组合问题,不解决模型能力和流程设计问题。插件再多,模型推理弱、工具契约写得含糊,Agent 照样干不好活。元框架的代价是:你决定的东西变多了,要自己扛的责任也变多了。

07 以后怎么选:一套判断框架

不用记参数,记住三个问题就行。

问题一:你的任务到底“确定”还是“开放”?

流程固定、步骤可枚举、要审批要审计——选 LangGraph,图编排和检查点正好。任务开放、结果不确定、要靠模型临场发挥——选 AgentScope 2.0,让模型自主、框架管边界。

问题二:你是“用框架”还是“造产品”?

快速搭业务智能体,AgentScope 2.0 的出厂护栏最省事;想深度定制一个 Agent 产品、要省 Token、要自己定义运行规则——DeepSeek Harness 的插件化给你最大自由度。

问题三:你的团队是什么技术栈?

Java 团队优先看 AgentScope 2.0(JVM 原生支持);前端/全栈团队可以顺手上 DeepSeek Harness(npm 生态);LangGraph 则对 LangChain 生态用户最平滑。

补充一句:这三个框架不是互斥关系。生产环境里完全可以用 AgentScope 管多租户边界、内部再挂 LangGraph 跑确定性子流程——先选对主框架,再谈组合。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐