Lantide Data

AI Agent 架构:ReAct、状态路由与 UICommand

配套②:自行实作 ReAct 串流回圈,以换取对事件型别、状态过滤与 IDE 整合的完全控制。操作见 使用者指南 §12。


系列位置

完整导读见 系列导读与产品定位。

顺序 文章 本题
0 系列导读与产品定位 系列导读与产品定位
1–3 Agent 时代的数据分析工作流、可治理的 Agent Memory、Prompt 与 Context 工程 工作流、Context
4 本文 Agent runtime
5 统一查询层 查询层

一、为何自研 ReAct

ReAct(Reasoning + Acting,推理—行动回路)让模型在单轮对话中交替「思考 → 呼叫工具 → 读取观察 → 再思考」。通用 Agent 框架擅长编排,但 Lantide Data 需要更细的控制:

  • SSE 事件型别细分:thought、tool_call、tool_result、message、ask_user、error…
  • 状态依赖的工具白名单与 mid-turn 刷新
  • UICommand 与前端 interceptor 同步开 tab、写 SQL、Source Run 完成
  • IDE 整合执行:工具产出须落在真实 SQL 分页、TabCacheRegistry、UICommand——而非仅在远端 sandbox 回传图表
  • 探索预算、provider fallback、token 压缩等产品级策略

因此采用 Python AsyncGenerator + 自有 stream_react_run,而非套用现成 Agent 抽象——我们要的是与 IDE 状态、SSE 事件、工具白名单逐行对齐的执行回路,而不是通用编排上的便利。


二、架构总览

flowchart TB
  api[FastAPI_stream]
  runner[LantideDataAgent.stream_react_run]
  router[StateRouter]
  prompt[_build_system_prompt]
  loop[ReAct_iteration]
  llm[LLM_streaming]
  tools[tool_ask_user_UICommand]
  sse[SSE_events]

  api --> runner
  runner --> router
  runner --> prompt
  runner --> loop
  loop --> llm
  llm --> tools
  tools --> loop
  loop --> sse

每次迭代:解析状态 → 过滤工具 schemas → 组装 system prompt → LLM 串流 → 执行 tool / 暂停 ask_user / 推送 UICommand;状态转换工具执行后同轮刷新 prompt 与工具集。


三、工具注册与 TOOL_AVAILABILITY_MATRIX

每个工具定义 Safety(safe / write)与可用 AgentState。矩阵在每次迭代开始过滤 schemas,例如:

状态 典型差异
NoProject / Quick 探索工具 + focus_project
ProjectFocused open_plan、open_report、HTML 条件工具
PlanPlanning 文件与探索;限量 run_query 探数允许;无 SQL Tab 工具群、无统计 run_*(prompt 禁止 activate_analysis)
PlanExecuting run_sql_tab、source_run_sql_tab、add_report…;不含 update_report/patch_report(正式 closeout 须新增 Report)
ProjectFocused / PlanPlanning 除读取/小修与授权汇入外,可用 lantide:reference-authoring/add_reference 原生建立正文+alias+必填 Intro
ProjectFocused / PlanPlanning / PlanExecuting read_reference、patch_reference;授权汇入时另有 prepare_external_ref/get_external_ref_import/save_external_ref/read_reference_source(lantide:load-external-ref)

State prompt 不列工具目录 — 名称与参数以当轮 function schemas 为准(见 Prompt 与 Context 工程)。

3.1 Ask mode(内建 capability ceiling)

内建聊天 composer 可在 Agent 与 Ask 之间切换(session sticky;预设 Agent)。Ask 是叠加在 TOOL_AVAILABILITY_MATRIX 之上的 ceiling overlay,不是新的 AgentState,也不是 MCP Observe:

Ask(内建) MCP Observe
约束对象 内建 Agent 工具 外部 MCP session
仍可 读 artifact/schema、run_query、重跑既有 SQL Tab(run_sql_tab/source_run_sql_tab)、统计 run_*、ask_user、导航 依 AccessMode 政策
禁止 写 Plan/Report/HTML/SQL 正文、create_html_report、知识写入等 denylist 外部写入(不暂停内建 Agent)

Ask 下 schema 隐藏写入工具;若仍被呼叫 → 结构化 ASK_MODE_DENIED。切回 Agent 后下一 turn 恢复该 state 的完整工具集(含既有 overlays)。操作见 USER_GUIDE Agent/Ask 小节。


四、ReAct 回圈细节

4.1 迭代上限

max_iterations 预设 100,防止异常回圈耗尽资源;达上限发送 iteration_limit 事件。

4.2 探索预算(Exploration Budget)

show_tables、read_schema、validate_query 计入探索。超过 exploration_soft_cap(预设 7)后,工具呼叫被跳过并回传 EXPLORATION_BUDGET_REACHED。

续跑协议: 下一个工具呼叫必须为 ask_user,且问题含标记 [[EXPLORATION_BUDGET]],选项含 Continue exploring / Stop for now。使用者选择继续则重置本轮探索计数;选择停止则 Agent 应先整理发现再决策。不应仅靠静默注入系统字串绕过人类确认。

4.3 Auto-continuation 与 output ceiling

finish_reason == "length" 且仍有空间时,可追加 "Please continue..."(次数上限),避免长报告截断。空正文的 length 视为 output_truncated(非 context overflow)。

单次 max_tokens 由 resolve_output_ceiling 决定:Profile maxTokens(可选)→ litellm max_output_tokens → state 预设,再以 state band 夹限;无 Profile 时 discovered 为硬顶。html_report 另有 20480 floor。Compact / history truncate 预留同一 ceiling。

4.3.1 同 turn 文件类 compact

每轮 tool 批次后,对 read_plan / read_report / read_reference 做 docs_k=1(按 iteration 批次):仅保留最近一轮(含同轮并行多份)全文,更早批次压为最小 stub。完整 read_docs 与可配 K 见 PRD 260706_agent-token-p1-compact-read-docs。

4.4 Mid-turn 状态转换

focus_project、add_report 等执行后,从 session 重新解析状态,更新 messages[0] system prompt 与工具集,使同轮后续迭代落在正确状态(例如 NoProject → ProjectFocused)。


五、Provider fallback

LLM 呼叫失败时可依设定 fallback 至备用 profile,并在 SSE 中标示,减少单点模型不可用导致整轮失败。


六、System prompt 组装与 mid-turn 刷新

LantideDataAgent._build_system_prompt() 合并 core、state、知识、catalog 提示、HTML 条件段。状态转换或 html_report_active 翻转后同轮重建,与工具 schema 对齐。

6.1 Query Step Ledger 注入(Layer 3.5)

多步分析时,模型需要记住「上一步物化了哪张表、SQL 长什么样」。每个对话在 workspace 内维护 Query Step Ledger:run_query / run_sql_tab 成功或失败后写入步骤索引;system prompt 附加精简摘要(快取名 + SQL 预览,≤1500 字元),使多轮后模型仍知近期步骤。完整 SQL 靠 query_result、get_cache_source 或 registry 查阅。

与 Plan Progress 分工: Plan 执行期的 Steps UI 与 read_plan 的 execution_record.steps 来自 *.progress.json 的完整 steps[](report 后 steps_frozen);Ledger 仅保留最近 50 笔服务对话连续性。fork_conversation 会复制来源 conv 的保留窗与下一流水号,使 fork 后 list_query_steps 与摘要延续;正式 Plan 快照不受这个上下文保留窗限制。

6.2 Ledger 相关工具

工具 / API 何时用 用途
get_cache_source 需审阅某快取表的原始 SQL 等同 UI「查看 SQL」,与 GET /cache/{tab_id}/source 同源
list_query_steps 多步链失序或需核对 step_id 列出本对话步骤;可选附截断 SQL
query_result 读取某次 run 的结果与 SQL 记忆体或 spill 后的 meta sidecar
[[QUERY_STEP]] 协议 每次 run 成功后(assistant 正文) 一行摘要;runner 解析后回填 purpose / pitfalls

conversation_id 由 runner 注入,LLM 不可自传;无 conversation 时跳过 ledger,物化策略仍依 workspace 启发式运作。

批注不走 Query Step Ledger——状态在 *.annotations.json sidecar 与正文 mark,由 read_plan / read_report / resolve_annotations 处理(见 Prompt 与 Context 工程 §十一)。

6.3 专案文件与批注工具

工具 Safety 典型状态 用途
read_plan / read_report safe Plan/Report 相关 磁碟正文 + sidecar + annotation_summary;已 Executed 的 Plan 优先读 progress snapshot/执行 SQL(双 flag),避免只开 live tab 当 evidence
resolve_annotations write Planning(非 Executing/Executed 正文锁) 依 open 批注原子 patch 正文与 sidecar
read_reference safe ProjectFocused、PlanPlanning、PlanExecuting 依 [Ref: …] When to read 载入 Reference 全文(Markdown+连结;不含图像素)
patch_reference write 同上 小范围 find-replace;不建立新 Reference 档
add_reference write ProjectFocused、PlanPlanning(Ask/PlanExecuting 不可) 从对话/分析原生建立正文、alias 与必填 Intro;明确要求可一次提交,主动建议需 digest-bound 确认
prepare_external_ref write(授权) 同上(汇入流程) 以 GUI handle 或 Admin 路径开始解析 staging
get_external_ref_import safe 同上 读取 staging/汇入进度与摘要(不全文塞进 chat)
save_external_ref write 同上 原子写入 Reference Markdown、图片资产、来源证明与 Intro 状态
read_reference_source safe 同上 按页/sheet/slide 等读取不可变来源快照细节

七、HTML 工具与契约(正文摘要)

产品动机见 Agent 时代的数据分析工作流 §五。操作见 §10。

7.1 条件注册 html_report_active

为真时(task_mode=html_report 或 Report tab 且磁碟已有契约 HTML):

  • 常驻 create_html_report(Generate / Re-generate)
  • 追加 read_html_text、get/patch_html_chunk_by_id(含 mode=full 与 mode=replace/replacements)、insert_html_chunk、delete_html_chunk、get/patch_html_styles 等
  • 注入 Editing HTML Reports state 段

同轮 create_html_report 成功后,下一 iteration 重算 flag 与 schemas,无需换 tab。Ask mode 开启时上述写入工具一律不可用(含 Generate)。

Scoped 结构编辑: 「加一段/删一段」优先 insert_html_chunk/delete_html_chunk;区块内改字用 mode=replace;整版换版面才 Re-generate。使用者操作细节见 使用者指南 §10。

7.2 activate_html_editing

当使用者不在 Report tab 却要改 HTML 时,Agent 先呼叫此工具解锁 chunk/样式工具,再 read → get → patch。多份 report 皆有 HTML 且未指定档名时应追问或回 AMBIGUOUS_REPORT。无 data-report-contract="1" 的旧档应 Re-generate。每轮对话需重新 activate 或回到 Report tab。

7.3 契约要点(内化叙述)

  • 根元素:<html data-report-contract="1" data-report-profile="standard|standard-chartjs|revealjs|offline">
  • <head> 内恰一个 <style id="report-styles"> 承载全域 CSS
  • <body> 直下可 patch 区块:data-text-id(regex ^[a-z][a-z0-9_-]{0,63}$)+ data-chunk-desc;禁止巢状可 patch 容器
  • create_html_report 做 full 验证;chunk 工具仅验证 body
  • standard-chartjs:head 含 Chart.js CDN + datalabels CDN + annotation CDN + #report-chart-init;图表用 canvas[data-chart-spec] JSON(options.plugins.datalabels / annotation 纯 JSON;deprecated lantide.dataLabels 仍兼容);patch 后需重新 Open Report 才重绘

7.4 内容品质警告与 skill recovery

create_html_report 通过契约验证后,html_report_guidance 会评估可 patch 区块数与 executive summary/limitations 关键字,附非阻断 content_hints(legacy 别名 content_warnings 仍回传同一阵列;如 HTML_CONTENT_THIN、HTML_MISSING_EXECUTIVE_SUMMARY、HTML_MISSING_LIMITATIONS)与 delivery_guidance/content_hint_guidance。这不 hard-block 工具成功,但 runner/外部 playbook 期望 Agent 扩写后再 announce。

契约错误时 error payload 含 next_action:先 load_skill(lantide:html-report-design 或 presentation 变体)→ read_skill_resource → read_report → 重建。外部 MCP Agent 可读 playbook shared_skills.html_report_design(见 USER_GUIDE §10.5.3)。


八、Agent Memory 工具

工具 方向 说明
expand_knowledge_catalog 读 catalog 模式下以父标签批次载入 Rules/Info 完整条目
propose_knowledge 写伫列 主动提案可重用知识进 Queued Knowledge;须使用者 Apply 后才注入

propose_knowledge 与被动萃取共用 knowledge_queue.json;提案入队后仍须使用者 Apply 才注入。频控:每则使用者讯息(整次 Agent stream)最多 2 条提案;每 conversation 最多 5 条 pending(Apply/Dismiss 后释放)。evidence_quote 是可选的审阅依据,不要求逐字验证;仍禁止 SQL、快取表名等执行态内容。详见 可治理的 Agent Memory §4.3。


九、UICommand 与前端 interceptor

部分工具不直接回传字串结束,而发送 UICommand SSE:前端 handleUICommand 执行 open_tab、update_tab_content、set_tab_results、source_run_complete、focus_project 等,并以 processedEventIds 去重。使用者看见 tab 与结果变化,形成「副驾驶」体验。见 §12.6。


十、ask_user:暂停/恢复

  1. Agent 呼叫 ask_user
  2. SSE type: ask_user → 前端互动区
  3. 使用者回复 → POST /api_v1/ask_user_response
  4. 结果喂回 ReAct,继续迭代

逾时约 5 分钟。探索配额、执行模式、Execute 确认等皆走此协议(Agent 时代的数据分析工作流)。


十一、Token 压缩策略

三种策略在不同时间尺度互补,可同次 ReAct 轮次内先后触发:

  • 历史截断(跨轮):长对话保留分析语境,丢弃较早无关讯息(Prompt 与 Context 工程 §十二)。
  • Mid-turn compaction(单轮内):一轮多次 tool 后 token 逼近上限,压缩本轮 tool 结果,保留 step_id、快取名等关键栏位(同篇 §十三)。
  • Auto-continuation:模型输出因 length 截断时,在仍有余量下追加续写请求(§4.3);与 context window discovery 联动。

十二、前端串流(可选)

streamStateMachine 将 SSE 分派为 thought / tool_call / tool_result / message 等 Segment,以 mutable draft + requestAnimationFrame 节流 flush,避免每 token 触发 React re-render;结束/错误/abort 路径 forceFlush。


十三、SQL 执行工具(与统一查询层对齐)

工具 作用
run_sql_tab 执行持久分页,物化快取
source_run_sql_tab Source Run DAG
sql_tab_result 读取分页快取结果(支援以分页标题解析)
validate_query 探索:仅验证;SQL Server 估计 >500k 列可回 warning_required
run_query 预览列(≤200);条件物化;大结果须 large_remote_warning_id

工具回传的品质讯号也会进入 runner 判定:complexity_hint 代表需要拆小步骤;optimization_hint 只是建议可考虑 cache,不阻挡分析。Release smoke 的 hard gate 聚焦在 plan → todo → report、无明显错误回圈与报告品质讯号;DAG / Source Run 则是 soft signal,用来观察可追溯能力是否被模型自然使用。


十四、External MCP Agent runtime

Lantide 除 Built-in ReAct 外,亦作 本机 MCP Server 供 Cursor 等外部 client 连入(USER_GUIDE §13)。

维度 Built-in Agent External MCP Agent
对话面 Lantide AI 面板 外部 client
工具面 内建 tool registry compact core + capability search/read/write invokers;底层仍由 MCP ToolPolicy + adapters 执行
Writer 互斥 — active Execute/Admin writer session 时内建 Agent 暂停
导览 直接 UI playbook resources(external_agent_playbook、recommended_next_steps)
Plan 核准 GUI Approve & Execute Execute 同左;Admin 单开可 claim_plan_approved
Config 交付 — 具名 mcpServers entry(lantide-quick-<workspace>/lantide-<alias>);client 端合并而非整档覆写
原生 Reference ProjectFocused/PlanPlanning,受可信对话确认治理 Draft/Execute/Admin 可用 add_reference;Observe 不暴露,与 Internal AgentState 正交

外部 Agent 的 UICommand 与 mutation 仍写入同一 workspace artifact、Activity 与 audit。Cloud folder/SQL Server 管理走 MCP admin_* 工具;在 Execute connection 上,需密文的 Admin 操作经 GUI 审批后转 Connections 补凭证(Approve all 遇 handoff 暂停)。查询语意与 Built-in 共用 统一查询层 §9。HTML 产出应走 skill + content_warnings 路径(§7.4)。

Initialize 后 unbound 的 All-workspaces profile(Observe/Execute/Admin):第一次 tools/list 回传依 Access Mode 固定的 compact session catalog;core 优先直接呼叫,长尾能力由 search_capabilities 回传 stable capability id、schema/policy digest、availability、data access 与 workspace read scope,再由分离 invoker 送入同一 canonical executor。种类相符的 invoker 亦接受 core capability 作为 host routing 相容路径,但不改变其 schema、权限或 lifecycle。compact core 的公开 schema 避免 oneOf/not 等部分 host 会静默省略的组合;add_plan 对 external session 只公开 inline verification,互斥与 legacy receipt 相容由 server 处理。搜寻使用单一动作的英文 action + object query;搜寻本身不执行能力,一般探索维持 side_effect=any,而 domain 是 optional single enum filter,不是 tool activation。外部 Agent 不暴露或呼叫任何 activate_*:HTML 与 Execute/Admin 的 11 个统计能力都直接搜寻,其中统计 formal execution 走 write invoker 与参数确认。invoker 不绕过原 ToolPolicy、mode、confirmation、evidence、Activity 或 audit。select_workspace(仅 Admin 可 create_workspace_and_select)只解除 workspace-bound execution precondition,不改变 catalog,也不发出 notifications/tools/list_changed;成功 response 直接内嵌 analysis_context,只有 refresh trigger 或需要最新状态时才再呼叫 get_analysis_context。analysis-context.v2 的 Knowledge manifest 只揭露 metadata,正文由 read_applicable_knowledge 按需读取已核准的 User/focused Project Knowledge。未绑定时呼叫 workspace-bound 工具会 fail closed 为 WORKSPACE_SELECTION_REQUIRED。Observe 不取得 writer ownership。Execute/Admin 为单线:一次一个选定 writer 工作区;切换沿用 owner_key 并保留原区 Plan 版本核准与待审纪录;实际执行中或待恢复操作须先完成,返回时重新取得 writer 并检查版本。已绑定后可用 invoke_read_capability(target_workspace_id=…) 对其他 Workspace 做 default-deny、snapshot-safe artifact read,不切 GUI/writer,也不撤销现有 grant/review;live source、query、GUI handoff 与 write 不在此平面。Playbook 版本见 runtime PLAYBOOK_VERSION(现行 s4.40)。 Managed Workspace 与 External Delivery: 外部 Execute/Admin Agent 可用 durable operations 准备、暂存、储存、inspect、规划及套用单一 Workspace bundle;Execute 需 GUI approval,Admin 可留下 warning/Activity/audit 后 direct apply,加密输入只接受 GUI-issued opaque access。Report 的 External Delivery 则由 list/link/update/unlink_external_delivery 管理 P4/KM/URL/Other pointer metadata;跨 Workspace 只允许 list,不会自动抓取或验证外部内容,HTTP/HTTPS location 可由使用者主动开启。


十五、工程决策总览

决策 原因
自研 ReAct SSE + 状态 + UICommand
探索 ask_user 续跑 人类确认而非硬停
条件 HTML 工具 降预设 schema 噪音
max_iterations 100 长链分析可完成
UICommand 真实 IDE 副作用
Release gate 重分析品质 不让快取形状取代可信报告

十六、结语

Agent 架构是工作流与 Context 的执行引擎:ReAct 回路把分层 prompt 变成 SSE 事件、工具呼叫与 IDE 副作用(UICommand),Harness 与聊天沙箱的差异在于执行绑定真实工作区。

若模型「一直 validate 却不 run_query」,请同时检查 Prompt 与 Context 工程 的 QEM 说明与本文探索预算;查询物化与血缘语意见 统一查询层。