← 返回目录

第 4 卷

第 4 / 4 卷日期:

等待点等待的内容等待
模型流(llm.stream)provider把chunk吐完for
工具分发(executeToolCalls)所有工具执行完并行

四个监听器跑完:agent/pre-step(改这一步要发的消息)、agent/request(改这次的调用配置)、

四类扩展点agent/request-error(返回 retry 就重试,不处理即三个终态)、agent/turn-stopping(turn 要关了,可再

插一步让它继续)

本讲小结

今天这一讲,我们先把零件组装成一个 Agent:六个包按 inject 声明依赖;装出来的 Agent 由五样组成,从 announce(agent) 发出 agent/created 那一刻起才算一个

Agent;它的生灭都挂在注册表上。

再装上 AgentLoop 驱动它自己跑:一个轮次从 turn/start 开账,跑成一个个 step(组装请求 → 流式响应 → 记进日志 → 要不要工具),直到没有工具、没有新 steering 才

turn/end;跑完之后还跑不跑,看有没有新的 followup 或 steer 把它叫起来。叫起来后再看队列里有没有活。

这背后真正的变化是:你不再把 Agent 当成一个现成的东⻄,而是知道它是怎么装起来的;

也知道它是怎么一轮轮驱动下去的。

到这里,你已经知道一个 Agent 是怎么装起来、又怎么被驱动起来了。接下来的问题是:同一份 dsh,怎么让不同会话各有各的一套?下一讲,我们讲 Agent Preset。

第 1、2、3 次 stream() 各 yield 一个 tool-call 块(工具名还是 echo),第 4 次才给文字答案。重跑 npm run start:ch13,回答两个问题:

  1. 第 1 轮里出现了几个 step/start?turn/end 落在第几条 seq?
  2. 这期间 agent/status 变过几次?

别把它改成“每次都要工具”:那会让 await agent.whenIdle() 永不返回、日志无限增长。这正是官方 README 那条“没有内置轮次预算”:想让它停,得自己挂 agent/turn-

stopping 监听器、或在工具执行处抛错,循环不会自己叫停。

小改动:在 main() 里、收尾(拆掉循环那个 fiber)之前,也就是第 2 轮跑完、agent 正空闲的时候,用两种方式各排一条:先 agent.followup(createUserMessage({

content: [{ type: 'text', text: 'A:下一轮再答我' }], source: { kind:

'user' } })),紧接着 agent.steer(createUserMessage({ content: [{ type:

'text', text: 'B:这一步就插进来' }], source: { kind: 'user' } })),最后 await agent.whenIdle()。

先猜:两条消息会落进同一个 turn/start 之后,还是分属两个轮次?再重跑,数一数日志里 agent/inbox/spliced 的位置来验证你的猜测。提示:想想这两条队分别在什么时候

被取走,答案可能与直觉不同。

欢迎把你的运行结果分享出来。如果你觉得这节课对你有帮助,也欢迎分享给其他朋友,我们下节课再见!

© 版权归极客邦科技所有,未经许可不得传播售卖。页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。

精选留言

全站分卷索引 · 4 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷