Aklman · Library

12 / 第十二章

流式 · 让用户看着它干活.

不流式的 agent 是个黑盒:用户发一个请求,盯着转圈等一分钟,分不清它在干活还是卡死。


你的研究助手现在能跑、能上生产了,但它对用户还是个黑盒:发一个问题,盯着转圈等一分钟,不知道它在搜、在算,还是卡死了。这一章讲流式 —— 让用户看着它干活。对多步 agent,流式不是锦上添花,是它能不能真给人用的分界。

I

不流式的 agent 是个黑盒.

多步 agent 不流式,用户体验就是「发一个请求,盯着转圈等」—— 而且分不清它在干活还是卡死。 模型 API 本身支持流式:client.messages.stream 用 SSE 逐块产出,事件里有 content_block_deltatext_delta / thinking_delta)。1注 1Anthropic 文档 · Streaming —— Messages API 用 SSE 流式返回,事件含 content_block_delta(text_delta / thinking_delta)等;client.messages.stream 逐块产出。截至 2026-05。但对 agent,token 级流式只解决了一半 —— 它让「等待」变成「在动」,可用户看到的还只是最后那段文字一个字一个字蹦,看不到「它走到哪一步了」。

II

Agent 的流式是事件级的,不只是 token.

给用户流的,是 agent 的行动轨迹:它在搜什么、调了哪个工具、跑到第几步 —— 而不只是最后那段文字。 在循环里,每一步 emit 一个事件:「搜索中 'X'」「找到 5 个来源」「在沙箱跑分析」「写报告」。这等于把第十章那条 trace 的一部分,直接变成给用户看的进度。我们的研究助手就该这样流 —— 用户看着它搜、读、算、写,而不是盯着一个转圈。3注 3OpenAI Agents SDK · Streaming —— 把 agent 运行中的事件(工具调用、步骤、增量输出)以流的形式抛给调用方,是「事件级流式」的一个实现参考。
async def run_streamed(goal):
    emit("开始:" + goal)                         # 事件级:给用户看的进度
    messages = [{"role": "user", "content": goal}]
    for step in range(MAX_STEPS):
        async with client.messages.stream(
            model="claude-opus-4-8", max_tokens=1024,
            tools=TOOLS, messages=messages,
        ) as stream:
            resp = await stream.get_final_message()
        for b in resp.content:
            if b.type == "tool_use":
                emit(f"调用 {b.name}…")            # 不是原始 JSON,是人话
                ...
        if resp.stop_reason != "tool_use":
            emit("完成"); return

在 agent 循环里,向用户流出「人话的步骤」

但别把内部细节全倒给用户。trace 是给你 debug 的,进度是给用户安心的 —— 流给用户的是「人话的步骤」,不是原始工具 JSON 和完整推理。两者的受众不同,详略也不同。

III

流式改变你的架构 —— 它得是异步、可中断的.

一旦流式,你的 agent 就不能是「跑完才返回」的同步函数了 —— 它得边跑边吐,还能被用户中途叫停。 流式要求异步(async generator / SSE),而异步顺带让「中断」变得可能 —— 用户看到它跑偏了,能当场喊停(呼应第九章的人工介入、第十一章的成本闸)。Vercel AI SDK 这类 streaming-first 框架,就是把「异步 + 流式 + 可中断」做成默认(呼应选型那一章)。2注 2Vercel AI SDK —— streaming-first 的 AI 应用 SDK:把流式 token 与 agent 步骤事件做成给前端用的一等原语。代表「流式优先」那一类框架。 流式和可中断是一对。能流不能停,用户只能眼睁睁看它烧钱;能停不能流,用户根本不知道该不该停。两个一起上,agent 才既透明又可控。 动手 · 给研究助手装上事件级流式:
01

在每一步 emit 一句人话进度

在 loop 里,每调一个工具、每跨一步,emit 一句话(「搜索中」「读到 X」「在算」),前端打印出来。
02

加一个「中途叫停」

给流式跑加一个中断入口(按键或一个 stop 信号),让用户看到跑偏时能当场停。
03

对比黑盒和流式的体感

同一个任务,跑改造前(等结果)和改造后(看着它干)各一次,记下体感差在哪 —— 那个差,就是 agent 能不能给真实用户用的差。

流给用户的不是 token, 是「它走到哪一步了」。.

What you stream to users isn't tokens — it's which step it's on..

Aklman Library

讨论

讨论.

评论区初始化中…