Skip to content

查看一次 Agent 运行 ​

可运行示例在浏览器中运行本章示例

这里运行与本地夹具相同的 Vue 3 源码。模型请求由服务端网关转发,供应商密钥不会进入浏览器。

本地运行pnpm tutorial:dev v3-04 --locale zh源码examples/tutorials/v3-04-declared-action/

第一条 Todo Agent 路径已经可以工作。界面上能看到它新增了任务、勾选了记录,但“动作成功了”只是结果,不足以解释过程:模型当时看到了哪些任务,拿到了哪些工具,为什么选择其中一个,又为什么没有选择另一个。

本章打开 Pling 的只读运行检查器。它展示一次会话中每次模型调用真正收到的系统提示词、工具清单和 messages,以及请求发生时的页面快照。

本章不增加页面能力,也不改变 Todo 业务。目标只有一项:让读者在后续学习和排障时,能直接观察 Agent 的运行,而不是根据最终答复猜测。

为什么需要检查请求 ​

同一种失败可能来自完全不同的原因。模型没有找到动作,可能是控件没有声明;模型选错了动作,可能是说明或区域不够清楚;动作执行后没有效果,可能是目标解析、业务前置条件或后置检查没有满足。只改系统提示词无法区分这些情况。

浏览器开发者工具能看到网络请求,却不一定能方便地把一次请求与当时的页面状态对应起来。Pling 的检查器保存的是运行内部已经使用的那一份数据,因此可以直接回答三个问题:

  1. 这次调用时,页面向模型暴露了什么?
  2. 请求里实际发送了哪些规则、工具和对话消息?
  3. 模型回复了什么,下一步又基于什么继续?

检查器是开发工具,不是调试器替代品。它不执行动作,不修改页面,也不能证明业务一定成功。

打开检查器 ​

在助手入口上显式开启 debug:

vue
<AgentDock
  title="待办助手"
  :debug="{ maxCalls: 8 }"
/>

maxCalls 限制内存中保留的模型调用数。省略时默认保留最近 20 次;maxCalls: 8 适合教程和普通调试。

使用默认上限时,直接写不带冒号的属性:

vue
<AgentDock debug />

它等价于 :debug="true"。只写 :debug、不给表达式不是合法的 Vue 模板语法。

这个选项默认关闭。它会把页面投影、对话内容和模型请求放进当前聊天界面,任何能打开该界面的人都能看到。检查器不是隐私边界,生产环境不要默认开启;需要展示诊断入口时,应由构建开关、角色或环境决定。

进入运行记录 ​

启动本章示例,打开助手,先发送一条真实任务。然后:

  1. 打开助手顶部的“运行”(英文界面为 Activity)。
  2. 在“执行记录”标题旁选择“诊断信息”。
  3. 展开最近一次模型调用。

页面投影可以立即查看。模型调用、messages、tools 和响应只有在至少完成一次请求后才会出现。

界面同时保留两个时间视角:

  • 当前页面投影:打开检查器这一刻,注册表里有哪些区域、动作、不可用动作、记录和状态;
  • 每次调用的页面快照:模型当时看到的那一份页面。

页面在动作后会继续变化,因此排障时通常应看“请求时快照”,而不是只看当前投影。

一次请求由哪几层组成 ​

检查器把一次模型调用拆成几个部分。它们来自不同位置,生命周期也不同。

system:稳定规则与当前页面 ​

每条 system 消息都由两部分组成:稳定的 Agent 规则,以及根据当前快照重新生成的页面上下文。页面上下文可能包含页面身份、区域树、可用动作、记录、页面反馈、被隐藏的内容和显式暴露的状态。

应用提示词与回答语言 ​

稳定的操作规则由 Pling 提供。应用可以再补充一段简短的身份说明。本章的 Todo 示例把它和 createPling 放在一起:

ts
const pling = createPling({
  agent: {
    config: {
      systemPrompt: "You are the assistant for a small Todo app. Keep answers short.",
    },
  },
});

Pling 会把这段说明追加到操作规则之后,放在 ## This application 标题下,而不是替换操作规则。没有配置应用提示词时,这一段不会出现。

回答语言不由应用提示词决定。Pling 已经要求模型使用用户最近一条消息的语言。界面为中文时,运行时会再为本次请求附加中文回答约束;除非用户最近一条消息使用其他语言。把语言策略放在框架里,可以避免应用自己的提示词与界面或用户的要求相互矛盾。

换到其他应用时,应把这段文字换成该应用的身份和业务约束。所有权、审批策略和领域规则适合放在这里;动作 id 和逐个控件的操作步骤不适合。

下面是经过截取的示例,不是完整提示词:

text
## This application
You are the assistant for a small Todo app. Keep answers short.

## Page structure (regions)
- main "待办" (todo): 待办列表,以及新增待办的表单。; in viewport; actions 6/6

## Available actions on this page
- composer_text [type] (write, region: todo): 在这个输入框中填写一条新待办的内容。
- composer_submit [click] (write, region: todo): 把新待办输入框中的文字加入待办列表。
- toggle [record] (write, region: todo): 将“{record}”标记为已完成或未完成。

## Records on this page
- 1. t1: text 检查发布清单; status open
- 2. t2: text 预约设计评审; status open
- 3. t3: text 跟进客户; status completed

这解释了前几项声明的去向:v-scope 进入区域树,v-tool 进入动作清单,v-record 进入记录部分。它们不是写进每一条用户消息,而是根据当前页面状态组装进本轮 system。

system 每轮重建。模型执行一个动作后,下一次请求会看到更新后的记录、可用动作和页面反馈。稳定规则不必重复拼接,变化部分也不会停留在旧快照。

tools:模型可以调用的函数 ​

tools 是与 messages 并列的请求字段。每个工具包含名称、说明和参数 schema。检查器中的工具清单来自当前动作投影,而不是开发者手写的另一份定义。

同一类行内动作会被折叠。例如三个 toggle@t1、toggle@t2、toggle@t3 会投影成一个 toggle 工具,并增加必填的 record 参数。模型不需要在三个几乎相同的函数名之间猜。

工具清单与 system 中的动作文字描述的是同一组能力。两者用途不同:文字帮助模型理解页面,function schema 约束实际调用。

messages:真实组装的对话 ​

messages 只保存会话历史,通常包括:

  • 用户原话;
  • 助手发起工具调用时的回复;
  • 与每次调用 id 对应的工具回执;
  • 助手此前的回答。

用户原话是一条 user 消息,不会把整份页面快照重复写进去。页面状态来自本轮 system,因此同一段对话可以随着页面变化继续使用,而不需要不断在用户消息里追加 DOM 文本。

一个常见的中间调用大致如下:

json
[
  { "role": "user", "content": "把“预约设计评审”标记为完成。" },
  {
    "role": "assistant",
    "content": "",
    "toolCalls": [{ "id": "call_1", "name": "toggle", "arguments": { "record": "t2" } }]
  },
  {
    "role": "tool",
    "toolCallId": "call_1",
    "name": "toggle",
    "content": "工具执行结果与可观察的页面变化"
  }
]

实际字段与回执内容会比这个例子多。检查器展示的是发送给模型的版本,不是界面层的摘要。

response:这一轮的模型输出 ​

响应部分显示模型返回的文本和工具调用。没有工具调用时,文本通常就是最终答复;有工具调用时,文本可能只是动手前的说明,真正的动作在 tool_calls 中。

读取顺序应当是:先看 response 决定了什么,再看下一次请求新增了什么工具回执,最后看页面和最终回答是否一致。

跟随一次多轮调用 ​

新增一条待办通常不是一次模型请求。检查器里会看到类似下面的过程:

调用请求中新增的内容模型选择
1用户要求新增任务composer_text
2上一步的工具回执composer_submit
3提交后的工具回执与更新快照最终文字回答

每一步都有自己的请求时快照。第一次调用看不到提交按钮,因为输入框为空时按钮处于禁用状态;第二次调用发生时,输入已经写入,composer_submit 才出现在动作清单里。

完成已有待办通常更短:模型从记录中找到 t2,调用折叠后的 toggle,然后确认结果。随着动作声明和流程设计变得更复杂,调用数会变化。不要预设固定次数,应以实际 trace 为准。

对照阅读,而不是只看最后一条 ​

检查器最适合回答三类问题:

动作没有出现 ​

先看请求时的页面投影:动作是否已声明,是否因为禁用、不可见、被遮挡或业务前置条件而没有进入可用清单。当前页面有动作,不代表前一次请求时也有。

模型选了错误的动作 ​

对照 system 中的区域路径、动作说明和记录字段,再看 tools 中名称与参数。两个语言相近的按钮如果没有清楚的区域或结果说明,模型只能依赖更弱的线索。

动作执行了,但页面没有变化 ​

先看工具回执中的执行结果,再看 changed 或其他可观察证据,最后检查下一次请求的页面快照。原因可能在于目标元素、业务逻辑、异步更新,也可能在于改动根本没有暴露给模型。不要只根据助手的最终措辞判断。

边界 ​

检查器当前有三条重要边界:

  • 只读:不提供执行按钮,也不创建第二个 runtime;
  • 有界:只在内存中保留最近若干次模型调用,清空会话时一并清除;
  • 开发期:不替代服务端审计、计费、限额或长期观测。

模型调用记录会占用内存。页面处理敏感信息时,检查器也会显示实际出站内容;已经 token 化的值仍以代号显示,但页面投影和对话本身仍可能包含敏感上下文。是否允许打开它,应按环境决定。

运行并验证 ​

从仓库根目录启动本章示例:

bash
pnpm tutorial:dev v3-04 --locale zh

打开:

text
http://127.0.0.1:5197/?lang=zh

按下面顺序检查:

  1. 发送“把‘回复客户’加入待办”。
  2. 打开“运行”,再点“诊断信息”。
  3. 展开第一次调用。确认 system 中有“待办”区域和任务记录,tools 中有 composer_text。
  4. 展开第二次调用。确认 messages 里已有第一次工具调用的回执,tools 中出现了 composer_submit。
  5. 展开最后一次调用。确认模型基于更新后的页面给出最终答复。
  6. 再发送“把‘预约设计评审’标记为完成”,确认其中使用折叠后的 toggle 工具与 record 参数。
  7. 清空会话,确认调用记录一起消失。

使用英文界面时,启动命令不加 --locale zh,打开 http://127.0.0.1:5197/。

常见问题 ​

现象可能原因处理
运行页没有“诊断信息”debug 没有开启在 <AgentDock> 上显式传入 :debug="..."
只有页面投影,没有模型调用还没有发送请求,或会话已清空先完成一次任务再展开调用
看不到提交动作请求时输入框为空,按钮处于禁用状态对照下一次调用的页面快照
tools 与动作清单数量不一致行内动作被折叠查看折叠工具的 record 参数与记录列表
敏感值没有还原检查器展示的是出站内容这是预期行为;调试不是隐私边界
旧调用消失超过了 maxCalls 上限调大上限,或在更小的复现中定位

下一步 ​

现在可以看见模型实际收到的页面、工具和消息。接下来的问题不再是“它有没有工作”,而是怎样让业务操作更接近人的意图。

下一章会把“填写输入框”和“点击提交”合并成一个 add_task 动作,并为它声明参数、可用条件和成功判据。