Files
agent-workbench/references/operations.md

28 KiB
Raw Permalink Blame History

运行接入

配置与部署

服务由 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//respond提交{expected_revision,option_id|null,comment,idempotency_key},允许选择合法方案或仅填写非空意见,至少一项。仅open/needs_reconsideration接受提交,保存内容及选项快照,状态统一pending_review;同key/body/revision幂等,不同返回409。旧decided/pending_verification且有response映射pending_review,不能伪造已接受。响应不授予运维权限。通知及ACK路径继续兼容,新增事件规则见下文。

桥接私有配置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//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仍是包含关系,不能拿这些字段替代集成验收。

本轮验收包括旧数据默认、创建和更新非法归属、被引用交付降级、报告字段保护;前端纯逻辑覆盖长链、多依赖、无依赖、筛选与汇合门禁。执行负责人以既有持久报告流程上报真实证据,收到落库回执后等待集成;集成负责人另做真实浏览器验证和发布,不能以执行完成代替正式验收。

执行会话可按人类已授权的项目协作范围,使用宿主支持的定向消息就共享接口与交接点相互协调;无需每次抄送副主控。唯一事项负责人把关键决定、版本、影响与交接回执落库;范围或归属冲突才交直属副主控。普通进度只更新状态,不制造互相唤醒链。副主控的判断可由推理模型结合明确规则承担,具体模型、费用与执行权限分别核实;用户仅询问模型能力不构成切换型号或购买服务的授权。

决策生命周期接口契约

状态为open/pending_review/accepted/completed/needs_reconsideration。对象增加summary、task_id、revision正整数、session_id/session_thread_id可空、archive_status(none/pending/archived)、review/completion可空、supersedes_id及related_decision_ids。GET /api/decisions/读取当前对象,GET /history返回{history:[版本、提交、检查、完成、绑定、归档事件]},所有版本与提交快照保留。创建支持简介、关联任务及替代来源并持久生成session_required;仅创建真实需求。

PATCH当前对象携expected_revision、reason及允许内容字段,乐观锁成功增版本,禁止覆盖response/submissions/review/binding。影响已提交问题或方案的实质改动保留旧选择并转needs_reconsideration,必须重新确认新版本。POST /review携expected_revision/idempotency_key/outcome(accept或reconsider)/reason/impact/execution_plan,可附authorization_evidence;仅检查当前revision真实pending_review提交,转accepted或needs_reconsideration。授权证据只是记录,须主控核对真实人类消息,不能自动执行。

POST /complete携expected_revision/idempotency_key/conclusion/handoff/evidence可选列表,仅有review的accepted/needs_reconsideration可完成并置archive_status=pending。POST /archive-receipt携thread_id/idempotency_key/receipt,仅completed且review/completion/handoff齐备;先由根调用宿主真实归档,再登记回执。

POST /bind-session携expected_revision/idempotency_key/session_id/thread_id,仅普通控制凭据。会话须已注册role=decision、wp=decision.id,真实thread UUID不复用其他决策、主会话或执行者;仅首次或严格重复绑定,禁止静默换绑。真实存在另由宿主工具验证。GET /consultation返回{messages:[既有conversation projection]},POST携text/client_key仅发送绑定session,不接受替代sid;完成归档后只读。GET /api/decision-bridge-bindings仅控制凭据,返回bindings内decision_id/session_id/thread_id/worktree/status/archive_status;fleet只接已有真实thread,不创建模型会话。

POST /consultation-credential由普通凭据签发专用token,数据库只存hash;该token仅允许本决策GET当前/history/consultation、PATCH内容和POST /facts,其余403,completed后禁写仍可读历史。不得向咨询agent分发普通panel token。POST /facts携idempotency_key/question/context可选,持久去重核实请求;POST /facts/<request_id>/answer由普通凭据提交idempotency_key/answer/evidence可选,写历史并通知绑定咨询thread,回复不是用户批准。

通知保留原GET /api/decision-notifications及ACK;工作流事件用独立持久表避免旧decision_id唯一约束。返回notification_id/target(control、human、decision)/通知创建时不可变decision与event快照(含kind、revision及相关字段),event_key幂等。GET不得重写为最新对象,避免破坏持久输入哈希;已提交/未知发送标记和历史保留。只有fact_answered可target=decision,绑定thread由真实session_thread_id确定。session_required、submitted、fact_requested、archive_required送control;reviewed送human仅简述影响与计划;fact_answered送decision,由notifier按已核实绑定定位。绑定后未发session_required、已答facts、已归档请求不再出队;已实际入宿主队列的旧输入按版本核对,不伪称撤回。普通决策事件不能一律路由control覆盖上述目标。

已有唯一人类入口时,所有主控、副主控、执行者的问题/选择/授权/关键结论定向交入口,不能直接使用用户提问工具绕过;入口理解后直接交主控,不经下层事件队列。独立咨询只限该决策内嵌页面,不成为一般项目沟通入口。真实会话创建、绑定核实和归档由根按既定授权执行。

验收覆盖两种检查分支、版本并发、不可改提交快照、选项变化重确认、关联新决策、有限凭据与任务/会话隔离、归档前置及幂等;真实咨询绑定与往返单独验收。暂无真实事项时仅做隔离测试,保留未验证限制,不造生产事项。

完成与归档前须检查绑定咨询session消息:有queued/claimed/uncertain未完成输入时返回409,保持可交流;completed立即拒绝新咨询POST,历史GET保留。fleet仅在archive_status=archived且本机worker无inflight/pending_completion/needs_reconciliation时停止自有子进程,不终止模型writer。已入队旧通知接收者fresh GET核对revision,过期静默停止,不能由快照直接执行。有限CLI及fleet负责已有绑定的桥接,不自行创建或归档宿主会话。

真实决策独立会话的创建、绑定后签发有限凭据、桥接、事实核实和完成归档步骤见 独立决策会话接入。notifier调用决策通知submitting接口后才向宿主队列外发,保留不可变快照与未知结果保护;不能仅清应用队列冒充取消宿主输入。