Files
agent-workbench/references/operations.md

149 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运行接入
## 配置与部署
服务由 `python3 -m agent_control.server --config <私有JSON>` 启动。先构建 `assets/dashboard/`,生产静态根默认是其 `dist/`;`web_root` 可指向本轮明确的构建产物。
`scripts/setup.py` 在指定的当前账号家目录内建立私有运行根、配置与随机令牌,支持可选的自有 systemd 用户服务。不使用 sudo,不修改其他服务、网络、认证或防火墙。令牌文件权限600,运行根700,SQLite位于本地盘;不放入NFS、仓库或前端代码。
`examples/control.example.json` 展示配置字段。`bind` 必须明确为内网/回环IPv4,`allowed_hosts` 包含确实使用的域名与端口;`title` 为当前项目名称,`primary_session_id` 指定人类沟通会话。保留来源校验,不关闭TLS或主机身份验证来解决连接问题。
HTTP服务适合受控局域网或受保护隧道。跨不可信网络使用经过授权的TLS反向代理;公开代码仓库不意味着允许公开运行端口。服务使用单一操作员令牌,不是多租户权限系统;`source`标签不能证明人类批准。
## API与状态
读写API使用 `Authorization: Bearer <令牌>`;写操作还需 `X-CSRF-Token: 1`。浏览器令牌只放内存,退出清理。静态资源不包含运行数据。
| 接口 | 用途 |
|---|---|
| `GET /api/state` | 任务、会话连接、事件、指标缓存、默认会话与项目标题 |
| `POST /api/sessions` | 注册真实会话映射;`id/wp/name/role/worktree/thread_id` |
| `POST /api/session-requests` | 保存新会话请求,不声称已经创建 |
| `POST /api/tasks`、`PATCH /api/tasks/<id>` | 任务状态、阶段、ETA范围/依据和待决策 |
| `POST /api/messages` | `session_id/text/source/idempotency_key`,定向消息 |
| `GET /api/messages?session_id=<id>` | 当前会话最近500条消息及投递状态 |
| `POST /api/worker/claim` | 串行领取,返回有限租期及领取身份 |
| `POST /api/worker/start`、`renew` | 记录可能产生副作用的执行开始与续租 |
| `POST /api/worker/submission` | 在发送前登记完整输入哈希,随后持久保存真实排队回执与观察到的turn |
| `POST /api/worker/complete`、`uncertain` | 幂等回执或结果未知;未知停止该会话自动领取 |
| `POST /api/messages/reconcile` | 人工核查后显式重试/失败,须记录依据 |
| `POST /api/mirror` | 绑定thread的可见历史导入、更新、关联原输入/最终回复 |
| `POST /api/events` | 工作包汇报、方案、决策、队列回执等事件 |
任务状态:`queued/running/blocked/waiting/completed/failed/cancelled`。阶段:`planning/implementation/validation/integration/done`。完成任务须为done阶段。ETA包含最小值、最大值和依据;没有可靠估计时为空。
源代码与行为测试维护精确校验规则。接口没有任意命令执行能力,采集不在HTTP请求中同步运行。
`GET /api/messages` 的原输入行包含submission元数据。镜像只有在完整实际输入的服务端哈希、目标thread及已知turn都与登记记录一致时才能关联原消息;旧版本已投递但没有submission的消息须人工核查,不能伪造回执或重发来补登记。活跃领取中的最终回复可返回deferred,镜像不推进该项checkpoint,后续重试关联。正常输入上限32000字符;完整镜像正文及回复上限262144字符,对应请求体上限4MiB,超出明确拒绝而不截断或自动重执行。
## 当前会话与桥接
加载skill时默认绑定当前真实会话;用户明确要求专门入口才另建,并将其设为默认。用宿主受支持工具确认真实ID,建立项目归属与看板映射。不要把内部执行器thread和桌面会话混为一谈。
执行器使用既有模型登录。集群未认证时让本机运行worker和mirror,服务/指标留在集群;模型凭据不离开本机。远程API可用 `control.transport="ssh"`:配置入口账号、独立私钥、`remote_client` 与 `remote_config`。客户端使用严格主机校验,在服务端内存读取服务令牌;不把令牌或模型认证拷进前端。
`desktop_queue`模式向原thread使用官方`codex queue`发送。保存外部回执、输入哈希和观察到的turn,精确匹配完整输入,不把用户正文引用的标记当作回执。队列回执与历史的clientId并无已验证的一对一保证,不能擅自假定相等。独立`exec resume`遇到桌面writer锁时不得抢占;可用性必须按本机版本验收。
镜像通过官方App Server分页历史读取用户、助手可见正文和明确的跨会话汇报;排除推理与工具日志。保留外部thread/turn/item ID、来源和修订;checkpoint绑定服务端点、会话和协议版本,换目标须显式处理旧状态。网页输入与最终回复关联原队列消息,去重且能补回超时后的真实最终结果。
已开始的执行失联后不自动重跑。重启发现inflight或待对账时,先查保存的回执、原会话、现有进程和产物;不能因一个本机进程结束就认为远端操作没发生。确认原操作已完成则收敛回执,只有明确核查和批准后才重试。
对已accepted/unknown的旧投递,不在同一message下更换输入哈希重试。核查并结束旧投递后,确需再次执行时建立带新幂等键的新消息,保留旧记录与人工依据;不要通过清空数据库恢复执行。
Windows下桌面队列命令受系统命令行长度限制;过长消息与上下文明确失败,不截断用户正文后静默提交。可缩小上下文或按用户意图拆成多条消息。
## 指标与扩展
默认配置仅本机只读指标。远程主机必须在本地可信配置中明确列出并加入白名单,使用获准入口与身份。NFS只读挂载统计,不递归扫描工程。调度器wrapper路径由站点配置,wrapper仅接收固定采集参数。
LSF主机/队列RUN计数可能是槽位数,不能等同作业记录数量。Slurm与LSF分别显示节点状态、队列/作业汇总、错误和时间;缺命令、缺配置与无权限不补零。新指标实现受控采集器和解析回归,不能让网页提交shell文本。
## 定期汇报与验收
面向用户默认事件驱动,仅重大里程碑、关键结果、阻塞、关键失败、重大风险与待决策触发;普通进展合并,无变化不打扰。总控可使用正式heartbeat每10分钟进行内部巡检与会话汇总,记录真实计划ID/目标;内部巡检不固定向用户播报。项目结束且无待处理事件后暂停计划。
真实验收分别记录:认证和来源保护、消息隔离/幂等、租期/失联恢复、同一真实会话往返、原会话汇报镜像、六分页及返回刷新、窄屏、真实采集、局域网直连。模拟通过不能替代真实模型/集群测试。原业务项目仍执行其自己的测试和原生工具验收。
## 故障钩子
`POST /api/hooks` 只收认证结构事件:event_id/source、severity(info/warning/error/critical)、status(firing/resolved)、summary,以及可选task_id/session_id、impact、evidence字符串数组、action、next_step。来源与ID各最多128字符;摘要1000、其他说明2000、证据最多8项各1000。引用的任务或会话必须存在。正文不执行任何命令,也不能指定通知目标。
source+event_id+status持久幂等,相同故障重复不打扰;恢复必须对应原故障并保留原严重性。每次新故障使用新ID。服务保留按control/human目标生成的持久outbox记录;这不是向人类直接广播的依据。启用下述内部审查路由后,notifier将同一hook的两个目标合并交副主控审查,再按实际影响决定是否升级。`GET /api/hook-notifications`读pending通知,`POST /api/hooks/ack`以notification_id幂等确认。`GET /api/state`的hooks字段显示待投递数、活动故障和最近事件;通知确认仅代表进入目标会话队列,不代表修复成功。
在桥接私有配置增加 notification_targets: {"control":"<总控真实UUID>","human":"<入口真实UUID>"}、notification_state_file(仓库外私有状态)。bridge_service同时运行notifier,保存队列回执,进程异常退出进入故障记录并按持续影响分级,功能健康且持续成功30秒后发恢复,不把进程存活等同功能恢复。bridge-faults.json和通知状态中的health显示钩子自身失败;同一通知不因ack失败而重发,未知结果只对账。后台执行主机离线时无法保证立即通知,内部巡检负责发现失联。
显式开发检查可用 `python3 scripts/hooks.py --config <私有配置> --source build --event-id <本次故障ID> --severity critical --summary "开发检查失败" --evidence "本地检查日志位置" -- <已授权程序与参数>`。不使用shell,不上传原始日志或命令参数,保留原程序退出码。恢复时同ID使用 --status resolved,或运行成功的修复验证命令;包装器在私有配置旁持久保存检查生命周期;首次检查成功直接返回0,不上报不存在的恢复。钩子投递失败自身返回失败并提示核查,不隐瞒。
这是通用接入机制。集群其他服务、CI、调度作业的故障需在各自受授权检查入口接入;不自动修改站点Runner或业务服务配置。事件文字只作事实资料,不扩大修复权限。
恢复通知发送失败后组件又失去健康时,保存 uncertain_recovery/needs_reconciliation,不继续宣布恢复。先核对服务事件与原会话,再人工收敛记录;不能盲重发或复用旧故障ID启动新周期。
## 决策与响应投递
GET /api/state的decisions保存卡片与响应。POST /api/decisions登记固定id/title/question及impact/priority/details/recommendation/options/deadline/requires_authorization/task_id;同ID相同规范正文幂等,不同内容冲突。options是{id,label,description}数组,不指定真实thread或任意命令。
POST /api/decisions/<id>/respond提交{option_id,comment,idempotency_key}。有选项须选择合法项,无选项至少写意见;第一次提交原子保存,同key同正文返回原响应,冲突重用或其他提交拒绝。普通状态为decided,权限相关为pending_verification;响应含authorization:false,不能作为提权批准。GET /api/decision-notifications提供最早100条待投递,POST /api/decision-notifications/ack以notification_id幂等确认。
桥接私有配置decision_notifications:true启用notifier投递到notification_targets.control。保存回执与完整输入哈希,未知投递先对账,不盲重发;投递确认不代表方案执行。通知只携带问题、实际选项与意见,背景仍由总控通过API读取,避免塞满会话。沟通展示使用/api/conversation;后台继续用原始/api/messages做恢复与审计。
## 任务当前进度
任务的current_progress是一句实际正在做什么,与eta_basis的估计理由分别保存。创建或PATCH任务时可显式提交current_progress(最多1000字),服务端设置progress_updated,不接受客户端自填时间。其他字段更新保留原进度和时间,旧任务默认空/None,不回填旧ETA依据。用户页面标“目前进度”,空值如实显示尚未汇报;活跃任务10分钟未更新提示待核查,完成任务剩余为0。前端沿用3秒轮询,不能把轮询时间当成任务心跳。
新增页面/功能需求另登记真实任务,开始、推进、阶段切换、阻塞与完成时更新一句话进度和状态。已送达且真实回复的网页需求若暂有旧失败事件,先按保存的thread/turn回执对账,不重发;桌面历史的临时interrupted且无确定error不是可验证失败,等待真实最终回复或转待核查。
## ETA 内部检查点
服务后台每15秒调用持久eta_tick;state.eta_clock显示时钟健康和last_tick。有效范围在显式写入时初始化eta_estimated_at/eta_revision,旧记录只读取不伪造起算时间。相同范围的心跳不重置;实际更改范围必须eta_change_reason。upper bound定义周期,50%/80%/100%分别写half/near/overdue唯一记录,只扫描活跃任务;任务完成或换版后旧未投递记录取消且保留审计。
GET /api/eta-notifications返回{notifications:[{notification_id,target:"control",task,checkpoint,revision}],pending_count},POST /api/eta-notifications/ack只确认排队投递。私有桥接eta_notifications:true启用notifier,有execution_notification_targets任务归属映射时先投执行者;否则配置eta_review_thread_id时投向获委派的内部核查会话,未配置则回退总控。核查会话查询真实执行状态后POST /api/eta-reviews/<notification_id>/complete:result keep/revise/unknown、reason非空,可选current_progress;revise附eta_min_minutes/eta_max_minutes。相同完成正文幂等,不同或旧版本冲突;keep不重置范围/时刻,unknown显示待核查,revise生成新版本及理由。延长次数同任务累积最多3次,第4次保留原范围并标needs_decision,不能无限续期。
消息进入核查会话队列不代表已经查询或重评估;ack与complete分开。超期且未取得状态保持待核查,活跃任务不能显示0分钟。内部检查不周期打扰用户,仅显著延期或待决策升级。
## 日志投影与持续故障升级
GET /api/logs提供最近100条按source/event_id聚合的安全日志,可选level=info/warning/error/critical、status=active/resolved筛选。first_seen/last_seen/resolved_at分别记录发生、最近上报与恢复;repeat_count从1起是累计firing次数,重复不新增通知。投影遮蔽私有路径和凭据,原审计仍保留。
桥接故障初报warning仅进内部审查和日志;持续功能不健康超过fault_escalation_seconds(默认120,范围60至3600)调用POST /api/hooks/escalate {source,event_id,reason,impact?}。同一生命周期相同升级幂等,不同理由冲突,已恢复不可升级。通知副本含log_id,升级及其恢复带escalated:true,原firing审计不变。人类入口仅接持续重大升级与必要恢复,聊天保留简报和日志链接,普通自动恢复整轮隐藏。ETA可用eta_review_thread_id配置总控明确委派的内部核查会话,避免总控忙碌时检查点长期排队;此目标绑定到持久发送状态,改目标须先对账旧投递并显式新状态。
## 持久关注事项
POST /api/attention登记{id,page,required,reason,href?,decision_id?,task_id?,hook_source?,hook_event_id?}。page为六个固定页面之一,reason最多240字;true须非空,false可空撤销。href只允许已知站内页面及query,拒协议、双斜杠、反斜杠、HTML和编码绕过。id绑定page/关联主体,不能移绑;省略关联时保留。同内容幂等,不更新时间或重复审计。state.attention包含有效items及六页pages布尔值,原始撤销历史持久保留。
decision与升级hook在同事务创建稳定关注,重复事件不补回agent已撤销项。decision响应、hook恢复、task取消撤销关联项;普通completed任务不自动清,避免清掉重大完成结果。其他任务/集群/沟通关注由agent明确创建/取消,不根据轮询或点击推断。查看页面与解决分开,没有“已读即全部清除”。
旧版bridge-mirror把短暂中断也标成critical的已恢复记录,安全日志视图在120秒内自动恢复且无升级审计时按warning呈现;原始严重性与审计不改。历史聊天中的该自动故障/恢复轮次及仅确认恢复的内部汇报被隐藏,主动用户询问不受影响。
## 任务关系与集成登记
Task新增goal/scope/coupling_assessment、owner/integration_owner/version、parent_id/depends_on/parallel_with/parallel_scope、sync_points、acceptance_criteria、merge_sources/merged_into_id、integration_status。默认空值,不造关系;引用必须已登记。父层级、依赖因果图和归并图分别无环;包含与回父汇总可并存,不能把包含当先后。依赖与并行有交集时必须解释parallel_scope的先行部分与等待点。
POST /api/tasks/<target>/integrate {source_ids,owner,status,version?,reason}事务记录target.merge_sources及source.merged_into_id,status为waiting/integrating/integrated/verified。源/目标存在且不同,已有其他归属或归并环拒绝,同语义幂等;源任务状态与进度不自动改变。这个API不是Git合并,也不是验收,只有总控核实代码集成和检查后才提升状态。任务三视图及详情直接使用这些真实字段。
## 一层副主控的路由与可靠上报
职责以SKILL.md的一层规则为准:归属执行agent先处理并落库,跨任务/阻塞交唯一直属副主控,副主控定向核查后只将人类决策、冲突或重大事件升级总控。人类需求、决策响应仍直达总控,不受底层事件排队链替代。紧急越级须记录副主控失联证据、约定时限与有界尝试,沿用原关联ID,不广播或循环转发。
**当前路由:** 私有桥接 `execution_notification_targets` 是看板session_id到真实执行thread的显式映射。notifier从正式 `/api/state` 读取task.id与session_id,用ETA的task.id或hook.task_id查归属;存在映射且不是决策通知时,优先投该执行thread。没有映射、没有关联任务或系统hook时,hook回退 `internal_event_thread_id`;ETA回退 `eta_review_thread_id`,再回退notification_targets中的目标。本一层流程将两个内部回退字段均指向唯一直属副主控。决策响应始终走notification_targets.control,不被执行者映射覆盖。没有有效显式目标会报错,不猜thread或广播。配置内部事件目标时,同一hook的control/human通知仍合并为一次投递并分别确认原outbox项,即使最终目标为执行者。
映射只选择真实已授权目标,不新增工作包、层级或权限。已持久记录的thread和输入哈希不得随归属变化静默改写。control、notification_targets、internal_event_thread_id、eta_review_thread_id及execution_notification_targets参与状态绑定;改变绑定须先对账旧投递,再使用新的私有notification_state_file,保留旧文件作为prior_notification_states,不把换文件当清队列。
启用coalesce_stale_hooks时,notifier只读取control连接相同的旧通知状态,先对账accepted/submitting/observed的hook回执;有receipt_id或已observed才确认原通知,未知发送保持受保护,无法映射的未知记录要求人工核查。随后按服务端规则合并过时hook,不盲重放既有积压。这是hook旧回执对账,不等于所有ETA/决策记录已自动迁移,也不证明宿主原生排队已取消;迁移后仍须验证目标绑定、去重与真实处理回执。
完成报告需先保存私有持久outbox,包含稳定report_id、task_id、任务版本、执行负责人、目标、证据与检查结果,再有界退避重试。接收方以报告ID和正文校验幂等;落库回执与外部队列回执分别保存。超时/结果未知先查原记录,不重跑业务、不换ID盲发;达到约定上限转待核查并定向交副主控。该段规定报告流程,不新增不存在的通用完成报告API;worker的complete/pending_completion和通知outbox只证明各自消息链路,不能宣称覆盖所有手工执行agent。执行完成、报告落库、集成验收和版本发布分别记录,未完成集成时保持真实等待状态。
## 通知背压与宿主队列边界
每个目标最多一条未处理通知;应用侧启用 `enforce_backpressure`,并配置 `max_inflight_per_target: 1`(当前实现允许1至3,本协作规则要求1)。accepted/submitting/observed且未processing_done的投递仍占名额,只有真实处理证据才能释放;发送确认本身不释放。后续通知留在持久outbox,同一关联事项合并,未知项先对账。仅限制单次发送批量不等于每目标背压;未启用或未验收时不得宣称已满足。
queue_health分别报告application_pending、inflight_by_target及已知完成情况。当前host_full_queue_count为null、host_queue_cancel_supported为false,表示没有完整宿主原生队列总数和取消能力;不代表原生队列为空。停止本机notifier、清应用待办或取消旧ETA记录都不能证明已进入宿主的输入已撤回。只能用受支持宿主接口核实取消结果,无法核实时保留未知并禁止盲重发,不访问内部数据库或抢writer锁。
## 版本交付归属契约
Task.kind取work或delivery,旧数据缺省work;delivery_id缺省null。工作任务可显式引用已存在的kind=delivery任务,禁止自指、不存在引用及引用普通工作任务。delivery任务自身不能设置delivery_id;已被工作任务引用的delivery不得降为work。创建和更新均校验,执行报告不能绕过归属或集成字段的保护。旧数据不根据version推断归属;正式迁移由集成负责人显式登记并保留原关系与验收证据。
created_at由服务端在新建任务时记录,拒绝客户端输入及更新/报告改写;旧记录缺失返回null,不补造历史时间。交付主线仅按有效created_at展示版本登记顺序,以name/version标识;同时间稳定按ID排序。旧无时间项按ID稳定展示并标“时间未登记/顺序未登记”,不得用updated代替创建时间,也不得将登记顺序解释为版本因果或Git历史。delivery_id仅表示归属,不证明已经合入;绘制汇合必须有merged_into_id或merge_sources真实关系,目标kind=delivery且源、目标integration_status均为verified。completed本身不满足门禁。depends_on仍是前置关系,parent_id仍是包含关系,不能拿这些字段替代集成验收。
本轮验收包括旧数据默认、创建和更新非法归属、被引用交付降级、报告字段保护;前端纯逻辑覆盖长链、多依赖、无依赖、筛选与汇合门禁。执行负责人以既有持久报告流程上报真实证据,收到落库回执后等待集成;集成负责人另做真实浏览器验证和发布,不能以执行完成代替正式验收。
执行会话可按人类已授权的项目协作范围,使用宿主支持的定向消息就共享接口与交接点相互协调;无需每次抄送副主控。唯一事项负责人把关键决定、版本、影响与交接回执落库;范围或归属冲突才交直属副主控。普通进度只更新状态,不制造互相唤醒链。副主控的判断可由推理模型结合明确规则承担,具体模型、费用与执行权限分别核实;用户仅询问模型能力不构成切换型号或购买服务的授权。