中途插话和接手
你从来不必等 agent 做完。消息会在它的下一步送到它那里,你可以让它就地停下,也可以随时把电脑拿回来。所有前端的做法都一样;下表列出 app 和终端里的操作方式。
| 想要 | 在 harness 里 |
在 app 里 |
|---|---|---|
| 告诉它一件事 | 输入一条消息 | 输入一条消息 |
| 暂停 | Esc(或 Ctrl+C) | 停止 或 Esc |
| 继续 | /continue |
继续 |
| 结束它的这一轮 | /cancel |
|
| 批准或拒绝一步 | 输入框上方的选项(按数字,或 ↑ ↓ 加 Enter) | 卡片上的按钮 |
| 自己使用电脑 | 接管,然后 交还 | |
| 结束对话 | /end |
开始一个新对话(旧的留在列表里) |
在它工作时告诉它一件事
Section titled “在它工作时告诉它一件事”消息对模型来说是新情况,它会随模型的下一次调用送达:
- 模型正在写回复时,这条回复照常写完,回复里要做的事照常做;然后模型带着你的消息被询问。
- 程序正在运行时,程序继续运行,模型立即带着你的消息被询问:程序从不占住模型的这一轮。它的回答决定接下来怎么办:让程序继续并等它,在旁边再启动一个程序,或者取消它改做别的事。
- 模型正在等待时,等待结束。
- 它启动的任务和子 agent 会继续运行,直到 agent 通知或停止它们。
所以“用便宜的那趟航班”会改变计划,而不会丢掉 agent 正在读的页面。要让它就地停下,先暂停(见下文)再说明原因:暂停期间发送的消息会替换掉还没开始的程序。
模型什么时候被调用
Section titled “模型什么时候被调用”模型的每一次调用都是一次思考,由下面某一种情况触发:
| 什么时候 | |
|---|---|
| 对话开始 | |
| 你发了一条消息 | 随它的下一次调用送达;它在等待时等待结束 |
| 一个程序结束 | 带着它的结果 |
| 一个程序过了片刻仍在运行 | 模型的这一轮先回来,程序继续运行 |
| 它启动的另一个单元结束(子 agent、程序启动的代码) | 带着它结束时的结果 |
| 一个没人处理的事件或错误上报给模型 | |
| 它自己选择的等待结束 | 会被告知原因:单元结束、消息、事件或时间到 |
| 一条回复没法用 | |
| episode 结束 | 一次简短的反思,可能提出学到的东西 |
模型写的每个程序都作为一个单元与其他单元并排运行。片刻之内结束的程序(runtime.turn_grace_seconds,默认 2 秒)带着结果把这一轮交给模型;更长的程序继续运行,这一轮立刻回来。此时模型可以再启动一个程序、取消一个,或者回复 <wait>:等待期间不发起调用,它启动的某个单元结束、有消息或事件到达、或时间到(最长为 runtime.longest_wait_seconds,默认 60 秒)时等待结束。两次调用之间,规则不经过模型就行动。
一个队列,三级优先
Section titled “一个队列,三级优先”自己到达模型的东西都是同一个队列里的通知,优先级由它的来源给定:
| 优先级 | 哪些东西 | 效果 |
|---|---|---|
now |
事件、环境告知的事、以出错或事件结束的单元 | 途中的调用被放在一边,不知情的回复不产生任何效果,模型带着它重新被询问 |
next |
正常结束的单元、你的消息、宿主的告知 | 途中的调用照常进行;随下一次调用送达 |
later |
被程序的优先级挡住的反射 | 随模型下一次等待之后的第一次调用送达,或随它的下一轮送达 |
每条通知都会结束等待,并在两轮之间开始新的一轮;只有被取消的单元的结束不唤醒谁,随下一次调用一并告知。每次调用,模型按这个顺序被告知:它上一条回复的结果(程序的句柄、等待为何结束、为何什么都没运行);通知,更紧急的在前;以及现在的情况:状态、正在运行的单元、反射树的变化。这次运行还剩多少(调用次数、步数、时间)只在 runtime.tell_budget 为 "always" 时告知。
模型留下仍在运行的东西由它自己看管。单元运行期间,模型可以读它到目前为止打印的内容:用单元的名字调用 output_of("e3"),或者对 entries() 给出的句柄调用 .output(),得到最后的若干字符(默认 2000,最多 30000),并且不会从结果里取走任何东西:单元结束时,结果里仍有全部输出。每次调用,模型都会被告知当时的状态,以及哪些单元在运行、各运行了多久、各自上一次打印是多久以前,这样它可以先检查自己的工作再继续等待,并取消没有按预期进行的程序。抛出事件的规则可以在某个条件成立时唤醒它,不需要它去检查。隔离工作区里的程序只在结束时给出它的输出。
harness 里的 Esc(或 app 里的 停止)让每个正在运行的程序在下一步停下,规则也被搁置:不再有任何操作,在你输入 /continue(继续)或发送消息之前,模型不会再被调用。暂停期间发送的消息会替换掉还没开始的程序。
/cancel 结束正在进行的这一轮:模型的调用被放到一边,它的程序被取消,对话带着它的一切等待你的下一条消息。
End 结束对话。如果是 benchmark 的一次运行,环境随后会给这个 episode 打分。
模型的回答(一条纯文本回复)结束的是它的这一轮,不是对话。之后对话带着它的消息、程序的变量、规则、facts 和环境等待。模型留下仍在运行的东西继续运行,某个单元结束或有事件到达时,不需要你的消息就开始它的下一轮。一轮也会在这些时候结束:用完了它的模型调用次数或时间(两者都随下一轮重新开始)、达到对话的费用上限、出错,或者你取消它;终端会说明是哪一种。
敏感步骤总会等你:执行它的环境识别出它涉及凭据、付款、发送、删除或无法撤销的操作(哪些环境会检查)。你允许或拒绝它,只对这一步有效。在 [approvals] 下设置 ask = "programs"(app 里的 动手前先问我)时,每个程序也要等:agent 会在程序运行前把它展示出来,你可以批准,或者附上理由拒绝,模型会读到理由。被拒绝的步骤不会运行(权限)。
当 agent 在你自己的桌面上工作时:
- 接管 会在你使用电脑时暂停它。交还 把电脑还给它,agent 会先重新看一遍屏幕再继续。
- 你的操作优先。 你使用鼠标或键盘时,它的步骤会等到你停下,然后它重新看一遍。如果你把自己的某个窗口切到前台,它会像 接管 之后那样停下,在你交还之前不会把屏幕拿回去。
- 要立即停止它,把指针推到屏幕的一个角落。
后台浏览器、后台应用和独立显示屏从不使用你的鼠标和键盘,所以没有什么需要拿回来:你使用电脑的时候,agent 照常工作。
它何时可以使用你的鼠标和键盘
Section titled “它何时可以使用你的鼠标和键盘”agent 是否可以使用真实的鼠标和键盘、可以在哪些应用里使用、是否要先询问,是一项有多个级别的设置,从从不到总是,并且可以针对应用、窗口和操作类型设定规则。权限和隐私介绍了这些设置;在 harness 里用 /settings,或在 app 的 Settings 里修改它们。
你的消息在时间轴上标为 ●,agent 的消息标为 ○,暂停标为 ‖,结束标为 ■。回复被放在一边或没有被使用的模型调用会画得颜色较浅,所以你可以看出你的消息改变了什么。
