# AI 建任务(AI Task Generator)设计文档 > 状态:**设计稿,尚未实现**(P0 未开工)——本文描述的是「要做什么、为什么这么做」,不是现状。 > 现状请读:[AI_CONSOLE.md](AI_CONSOLE.md)(AI 控制台已实现的能力)、[TASK_DEV.md](TASK_DEV.md)(任务与步骤)、[MCP.md](MCP.md)(已实现的 19 个工具)。 > 关联代码:`web/agent_api.py`、`mcp_server/`、`mcp_agent/`、`tasks/generic/`、`static/admin/editor.js`。最后核对:2026-09-10。 ## 1. 背景与目标 平台已有两套能力,但互不相通: - **AI 控制台**:一句话 + 选设备 → 多模态 Agent(DeepSeek)通过 19 个 `de_*` 工具在手机上「边看边做」(截图看屏、`de_ui_tree` 拿元素树、`de_tap_element/de_tap_text` 语义点按),流式回放步骤。 - **任务系统 + 步骤编辑器**:`generic_steps` 任务 = 一棵可嵌套步骤树(open_app/click/swipe/loop/group/if_el…18 种节点),在编辑器里拖拽编排、单步试跑、定时调度。 目标:让**非工程用户用一句自然语言需求**(例:「创建一个每日养号刷视频的任务,每天 8:00-9:00 在 100.100.10.13 跑」)得到**一条可直接调度、可继续在现有步骤编辑器里手改的任务**。AI 先自己在设备上打开 App、看 UI 树、确认可点元素,再直接撰写编辑器的步骤 JSON。 ### 产品体验(一页) 1. 用户进入「AI 控制台 → 模式=AI 建任务」,选一台**空闲**设备,填需求 +(可选)任务名/调度/目标。 2. AI 自探并**流式回放**(工具卡 + 截图,与现在一致):开 App → dump UI 树 → 确认要点的元素可命中 → 写步骤。 3. 完成后平台返回任务草稿 `draft`,服务端 schema 校验后,**前端直接打开现有「新建任务 → 步骤编辑器」**预填。 4. 用户核对/手改/单步试跑 → 保存 → 进任务列表,走原有调度器执行。 **核心信任原则:AI 只“提案”,不直接建库、不直接执行最终任务;最终落库/执行都在用户确认后由现有机制完成。** ## 2. 范围(P0 定稿,2026-09-09 与用户确认) - **入口**:AI 控制台加「聊天 / AI 建任务」模式开关,复用会话/SSE/设备选择/停止/刷新恢复骨架。不新建顶级 Tab。 - **产出方式**:**AI 直接撰写编辑器的步骤 JSON**(非操作轨迹翻译)。自探信息只作上下文与审计;探索中的误点/多余截图不会混入任务。 - **任务类型**:**只产 `generic_steps`**(通用步骤)——平台当前唯一的任务类型 (原 `douyin_nurture` 预设参数生成已随该类型删除,不再做)。 - **定位原则:全部基于 UI 树**: - 模型定位/点击一律走 `de_ui_tree` 拿到的元素(`text`/`id`/`description`/`text_contains`),多实例用 index,或后端 `uiauto_helper` 生成的 `//*[@resource-id=..][k]` XPath; - `de_tap_element` 确认能命中后才写进 `click` 步骤; - **默认不产 `click_xy` 坐标点击**;UI 树给不了的元素记入 notes,交给人工/OCR 兜底; - 滑动用方向语义 `swipe{direction}`,不用像素坐标。 - 产出完整任务信封:`{name, task_type:"generic_steps", target, schedule, retry, enabled, params:{max_duration, steps}}`。 ## 3. 现状与可复用点(实现依据) - 多模态 Agent 链路:`web/agent_api.py`(`POST /api/agent/run` 起后台线程、SSE `delta/step/done/error`、`/stop`、刷新恢复 `GET /api/agent/run`)→ `mcp_agent/agent.py`(OpenAI 兼容流式,工具经 fastmcp Client 拉 8033 的 19 个 `de_*`)→ `mcp_server/mcp_server.py`。 - 前端 AI 控制台骨架:`templates/admin/monitor.html` `#tab-agent` + `static/admin/agent.js`(设备选择、`sendAgentMsg`、`listenStream` 渲染 `agent-toolcard`、实时画面跟随)。 - 步骤权威 schema(前后端同构):`tasks/generic/task.py` `STEP_TYPES`(L44-83)/ `DEFAULT_PARAMS`(L86-103) 与 `static/admin/editor.js` `STEP_LIB`(L3-23)。 - 元素抓取 → XPath:`web/tasks_api.py /api/uiauto/elements`(L224)→ `core/uiauto_helper.get_elements`(`suggested.value` 即编辑器可用的 XPath)。 - 单步试跑:`/api/steps/test`(tasks_api.py L249)+ `editor.js _testStep`;`tasks/generic/task.py test_step`(L633)。 - 任务/调度/目标:`core/task_manager.py` `TaskJob`(L121-199);`POST /api/jobs`(tasks_api.py L68)。 - 设备占用语义:MCP 写工具 `_ensure_device_free`(mcp_server.py L60-78,running/connecting → `device_busy`);`agent_api` run 入口同样对 worker running/connecting 拒绝(409)。 - 经验库自进化:`agent_experience` + bigram 检索注入 + 每日巡检(`web/agent_api.py`)——P1 沉淀模板的现成载体。 ## 4. 架构与数据流 ``` 需求+设备(空闲) ──▶ Designer Agent(自探, 模式=designer) │ de_open_app / de_ui_tree / de_screenshot / de_tap_element… ▼ 平台工具 submit_task(draft) ← 结束性调用 │ 服务端 draft schema 校验(白名单+必填+深度≤5) ▼ 前端: 打开 openTaskModal 步骤编辑器, 预填 draft.task │ 用户核对/手改/单步试跑(/api/steps/test) ▼ POST /api/jobs → 任务列表(原调度器执行) (P1) draft+需求 沉淀 agent_experience, 相似需求注入参考 ``` ### 4.1 Designer Agent(新增模式,复用现有 Agent) - `mcp_agent` 增加 designer 系统提示词:角色=自动化任务设计师;行为约束见 §5.1。 - 增加**平台级工具**(不属设备 `de_*`): - `submit_task(draft)`:结束性工具,模型完成自探后提交草稿即停止,服务端立即校验。 - 会话内同时记录**结构化 trace**(每轮 `on_tool` 的 `{tool, args 精简, 屏号/证据}`),用于:校验证据(每个 selector 来自哪次树)、审计、P2 回放。 - `POST /api/agent/run` 增加 `mode:"designer"`;`done` 事件负载携带 `draft`(校验通过)或 `draft_error`(校验失败+原因,让模型补一轮)。 ### 4.2 draft 契约 ```json { "summary": "每日8-9点刷抖音养号:开抖音→循环(看5~35s+上滑)+随机间隔", "task": { "name": "抖音每日养号", "task_type": "generic_steps", "target": {"mode":"serial","serial":"100.100.10.13:5555"} | {"mode":"group","group_name":"测试"} | {"mode":"all"}, "schedule": {"mode":"once"} | {"mode":"cron","cron":"0 8 * * *"} | {"mode":"cron_stop","cron":"0 8 * * *","stop_cron":"0 9 * * *"}, "retry": {"max_attempts":5,"delay":30}, "enabled": true, "params": { "max_duration": 0, "steps": [ {"type":"open_app","label":"打开抖音","params":{"package":"com.ss.android.ugc.aweme","wait_home":true}}, {"type":"loop","params":{"loop_mode":"rounds","max_iterations":30,"children":[ {"type":"wait","params":{"min":5,"max":35}}, {"type":"swipe","params":{"direction":"up","duration_min":0.25,"duration_max":0.5}} ]}} ] } }, "notes": ["评论按钮需先进入视频页才可见"], "evidence": [{"screen":"抖音首页","element":{"text":"关注","id":"..."},"xpath":"//*[@resource-id=\".../gvo\"]"}] } ``` - 步骤节点结构:`{id?, type, label?, params}`;`id` 执行端忽略(编辑器重新生成),`params` 必填。 - 必填字段语义(**空值会被执行端静默跳过**,校验器必须拦): - `click / long_click / swipe_until / wait_el / if_el` → `params.selector_value` - `open_app / stop_app` → `params.package` - 容器:`loop / group` → `params.children`(非空);`if_el` → `params.then`(`else` 可选) - `swipe_until` → direction + max_swipes;`click_xy` P0 不产(如允许则 x/y 0-100) - 节点公共可选 `params.probability`(0-100,缺省 100) - `selector_type` 允许值:`xpath / description / text / resourceId / descriptionContains / className`(`if_el` 可 `ocr`)。 ### 4.3 服务端新增 - `core/task_draft.py`: - `STEP_TYPES` 白名单 + 每类必填/深度校验 `validate_steps(steps, depth)`(嵌套≤5); - `validate_draft(draft)`:任务信封(name 非空、task_type==generic_steps、target mode ∈ {all,group,serial}(group 名存在)、schedule cron 合法、steps 校验); - 归一化:把 `schedule` 里「每天 8-9 点」这类由前端/向导填的值转成 cron/cron_stop。 - `web/taskgen_api.py`(或并入 `agent_api`,推荐并入以最大化复用): - 入口检查:serial 必须、设备在池/在线、worker 非 running/connecting(409,与现有语义一致); - 起 designer 后台线程;SSE 事件在现有 `delta/step/done/error` 基础上,`done` 可带 `draft`。 - **注意**:现有 `POST /api/jobs` 对 params **盲存**(只校验 name+task_type)。AI 通道在**保存前**必须过 `validate_steps`,避免「任务 done 但什么都没做」(执行器对未知 type/空 selector 静默跳过)。 ### 4.4 前端 - `monitor.html` AI 控制台加模式切换;建任务模式下输入栏旁有折叠「任务设置」(名称/调度时间/目标 serial·分组·全部/备注)。 - `agent.js`:done 携带 draft 后: - generic_steps → 调 `openTaskModal()`(tasks.js)并把 `draft.task` 灌入步骤编辑器(step 卡片可视化、可拖改、单步试跑、保存); - 弹窗内对 `notes`(含“需人工复核/OCR 兜底”项)给出醒目提示。 - 过程回放沿用现有 `agent-toolcard` 渲染;可标记当前为 designer 轮以便后续区分。 ## 5. 约束与安全(红线) ### 5.1 Designer 自探规则(写入提示词) 1. 先 `de_open_app(package)`,再 `de_ui_tree` + `de_screenshot` 看每屏;点到关键状态后再 dump 下一屏。 2. 每个将写入步骤的目标元素,先用 `de_tap_element`(by=text/id/desc…)+ 截图**确认可命中**,并记下证据。 3. **不做破坏性动作**:需“评论/发送”时只确认输入框/发送键存在,不真发;产物里这类步骤 `probability` 调低并在 notes 标注“请人工复核”。 4. 探索步数上限(P0 建议 30 步),可被 `/stop` 打断;结束后尽力还原前台 App。 5. 未命中的元素一律不进任务;拿不准的进 notes 而非硬编。 ### 5.2 平台级约束 - 自探/试跑只在**用户选的空闲设备**(busy → 409),杜绝与运行中任务在设备上物理打架。 - AI 不直接建库;生成任务仍需用户点保存(POST /api/jobs 现有权限)。 - 尽量不写死坐标;P0 默认禁 `click_xy`,产物以树元素定位为主。 ## 6. 里程碑 - **P0(本设计主体)**:designer 模式 → 自探(UI 树定位)→ 直接撰写 generic_steps draft → 服务端 schema 校验 → 前端步骤编辑器预填确认保存。验收:一句话在真实设备上生成一条可调度的 generic_steps,步骤全部来自 UI 树且编辑器可打开。(平台只剩 generic_steps 一种任务类型,与原规划一致) - **P1**:模板沉淀:把 draft+需求写入 `agent_experience`(新列存结构化 steps 或 JSON),相似需求注入参考;整链「演示试跑」(把 steps 在设备上以受控方式跑一遍并截图回报,需新增端点,复刻 `device_busy` 拒绝语义)。 - **进展(2026-09-10)**:动作级沉淀已落地——`agent_action` 表 + 从**成功步骤**蒸馏"命名动作"(steps 用编辑器 schema、带元素定位、禁坐标)+ 执行前按名/别名召回注入(`web/agent_api.py`)。AI 建任务可直接把这些动作当作 generic_steps 的**预制件**复用。 - **P2**:自定义动作支持(内联展开成 group,或新增 `action_ref` 节点 + 执行器/编辑器同步);多设备并行;成本与 token 控制。 ## 7. 实现时需新增/改动文件(规划) - 改:`mcp_agent/`(designer 提示词与 `submit_task` 工具、结构化 trace)、`web/agent_api.py`(mode=designer、done 带 draft)、`static/admin/agent.js` + `templates/admin/monitor.html`(模式切换/任务设置/draft 预填)、`doc/`(本文档关联)。 - 新:`core/task_draft.py`(schema+校验+归一化)、(可选)`web/taskgen_api.py`。 - 不动:任务执行器、调度器、`POST /api/jobs` 主体(保持现有盲存,只在 AI 通道校验)。 ## 8. 验收(P0 实现后自测) 1. 目标设备空闲时:需求「每日 8-9 点刷抖音养号」→ 生成 generic_steps 任务,步骤为 `open_app → loop(wait+swipe)` 结构,调度 cron_stop 8-9 点。 2. 打开编辑器中该任务:步骤卡片完整、可拖改、单步试跑命中;保存后任务列表出现且下次运行时间正确。 3. 反例:模型产出含 `click_xy` 或未知 type / 空 selector → 服务端校验拦截并让模型补正;busy 设备入口 409。 4. 探索全程可在前端回放(工具卡+截图),未发送真实评论/未污染设备状态。 ## 9. 需要转成 MCP / 平台工具的能力(分层,2026-09-09 与用户确认) > 背景问答结论:目前 MCP 只有**设备层 19 个 `de_*`**(控制 + 只读 `de_list_tasks`),平台 CRUD(任务增改/启停/立即运行、分组、设备池、自定义动作、APK、备份、用户)**都还没 MCP 化**。方向认同「先把工具链补完善」,但不做"把所有平台 CRUD 一次性搬成 MCP"的大而全——**按消费方(AI 建任务 / 外部自动化)分层、按需补**。新增 MCP 工具一律:进 `doc/MCP.md` 手册 + `doc/MCP_DESIGN.md` 规格 + 与 web 同源的权限/busy/审计 + 校验逻辑下沉到 `core/` 共用(防双份漂移)。 ### 9.1 现状盘点 - MCP(`mcp_server/mcp_server.py`,19 个 `de_*`)= 设备控制 + 设备只读 + `de_list_tasks`(平台任务只读)。 - 任务创建/修改/删除、toggle、立即运行、分组、设备池管理、自定义动作、APK、系统备份等 **REST 路由只给前端用,未暴露 MCP**。 ### 9.2 P0 —— AI 建任务链路真正需要的「平台工具」(最小集) 只补两小类,其余设备操作全部复用现有 `de_*`: 1. **只读清单**(供自探确定 target/能不能做): - `list_task_types` / `list_groups`(target 选 group 用)/ `list_pool`(可调度设备,含 busy 状态) - (可与现有 `de_list_devices` 合并语义,避免重复) 2. **校验 + 提交(结束性)**: - `submit_task(draft)` → 服务端用 **共用** `core/task_draft.validate_steps()/validate_draft()` 校验,**不直接落库**,返回 draft 供前端打开步骤编辑器预填、人工确认后走 `POST /api/jobs`。 > 关键:P0 的 Agent **不暴露任务 CRUD 写权限**(create/update/toggle/run),否则模型可绕过"AI 提案 → 人工确认"直接入库,破坏信任模型。 ### 9.3 P1 —— 外部自动化 / 后续 Agent 的「写 MCP」(受权限约束,逐块加) 若目标延伸为"外部程序能像调 REST 一样操控平台",则按此清单**逐个**补(每加一个都做权限+busy+审计+校验下沉): - 任务:`create_job` / `update_job` / `delete_job` / `toggle_job` / `run_job_now` / `query_jobs` - 分组:`list_groups` / `create_group` / `update_group` / `delete_group` - 设备池:`pool_list` / `pool_add` / `pool_remove` / `pool_toggle` - 自定义动作 / APK 清单 等视使用再加 - **只读清单优先搬**;写类确认有真实消费方再做,避免空转。 ### 9.4 分层与登记(红线) - 每新增/修改/删除一个 MCP 工具或平台配置:同步更新 `doc/MCP.md`(全清单)、`doc/MCP_DESIGN.md`(规格/层级),并在提交里体现——见全局「doc 同步红线」。 - `core/task_draft.py` 是 web 校验与 MCP 校验的**唯一来源**,杜绝两套规则漂移。