# 智能体运行机制

解析图数据智能体如何从问题选择证据、组织工具调用并解释结果，以及会话、技能、并行调度、审批恢复和后台作业机制。

## 从请求创建智能体

iGraph 的 Agent Runtime 承载图数据智能体，建立在 Agno AgentOS 之上。智能体负责理解用户问题、判断证据需求、选择技能和工具，并根据实际结果组织后续分析与解释；Graph Engine 负责图模式、查询、算法和训练计算；Backend 负责用户、项目和面向浏览器的接口。一次请求到达后，工厂装配本次使用的模型、数据库、图工具、技能、学习机制和领域指令。因此，模型配置和用户技能属于本次请求的运行环境，不需要为每个用户维护一个常驻智能体进程。

工厂先解析模型、推理、规划和输出选项，再使用 Backend 注入的默认工作区上下文读取模型配置。模型仍需在目录中可用，并具备匹配的提供商、协议、服务地址和凭据；这属于模型服务配置，不需要为浏览器用户分配角色或登录权限。必要配置缺失时，请求会在模型调用前失败，在问题文本中指定另一个模型名称不会改变连接配置。

| 选项 | 作用 |
| --- | --- |
| model | 选择标准模型或当前用户配置的自定义模型；未显式传入时使用服务默认模型。 |
| reasoning_mode | direct 直接处理；staged 开启分阶段推理，并要求先检查证据和工具前提。 |
| planning_mode | never 不自动生成独立计划；auto 保留会话规划能力；always 要求持续维护目标、步骤和进度，并开启推理。 |
| output_format | chat、report 和 json 是输出选项；json 关闭 Markdown 输出设置，不等于自动提供业务 JSON Schema 校验。 |

默认工作区归属与会话上下文沿服务调用链传递，工具调用还携带本次运行标识。启用执行控制后，跨服务请求会增加执行代次和操作 ID；内部接口继续使用服务凭证。Backend、Agent Runtime、Graph Engine API 与 MCP 必须使用一致的内部服务密钥；取消用户登录不影响这项要求。

除 MCP 图工具外，运行时还装配会话工作区工具：查看可见文件、执行受限命令、管理会话环境，以及把中间文件发布为 Derived 结果。工作区命令对 Uploaded、Derived 和 Environment 保持只读，计算过程写入 Ephemeral；发布操作负责生成可交付的版本。它们与 Graph Engine 的图计算工具分工不同。

## 会话、单次运行与图状态

Session（会话）是连续讨论的容器，Run（单次运行）是处理一条请求所产生的一次执行。会话可以保存多次运行、用户消息、工具结果和会话状态；一次运行可以经历多个模型回合、多个工具调用以及审批暂停。智能体创建时开启历史和会话状态注入，并将普通历史窗口设为最近 20 次运行。这个窗口用于模型上下文，不表示更早的持久化会话记录已被删除，也不保证所有历史内容都永远出现在每次模型请求中。

理解图任务时，需要分别核对“源数据已保存”“数据集已经构图”和“当前会话已经加载图”。上传 SQL、CSV 或 TXT 只说明有可用的数据源；active_dataset_id 表示活动数据集绑定，不能单独证明内存中存在可分析的图。智能体先读取 data_state 中的构图状态与版本，再用 get_graph_info 核验当前图。如果已有 ready 的构图数据集，使用 load_constructed_graph 加载保存版本即可，无需为一次新分析重复构图。

Backend 为每次运行刷新当前用户和项目的数据范围。construction_sources 对应本条消息附件中的已保存数据集；available_constructed_datasets 表示可加载或优化的构图数据集。运行时会在相关工具执行前检查 dataset_id 是否属于该范围，越界时返回 DATASET_SCOPE_REQUIRED。成功加载后，再把活动数据集、构图状态和 revision 写回会话状态，让下一轮继续使用已确认的版本。模型不能根据文件名猜测数据集 ID，也不能仅因为同属一个用户就跨项目选择数据。

例如，用户先上传订单表，再问“找出连接多个社区的关键客户”。运行时应先确认该附件的数据集及构图状态，加载可复用的图，然后取得中心性和社区结果。若当前没有活动数据集绑定，仍需核对会话图，不能直接断言没有图。最后的客户判断、可视化和报告都应引用本次核验后的图与工具结果。

## 从分析问题到下一次工具调用

分析步骤由问题、会话状态和工具结果共同决定。当前领域指令要求在图状态不明确时先核验状态，优先使用适合问题的传统图算法，并在任务定义、特征、标签及训练条件充分时才使用图机器学习。这些规则约束智能体如何取得依据；它们没有把所有请求固定为“上传—构图—训练—报告”的流水线。

| 当前情况 | 分析动作 | 继续条件 |
| --- | --- | --- |
| 对象名称不明确 | 先用 search_node / search_edge 定位候选，补充类型、端点或用户描述。 | 只有确认真实标识后，才传给依赖该对象的图操作。 |
| 问题需要结构解释 | 按关系含义选择路径、连通性、中心性、社区或局部图分析。 | 检查结果范围和算法含义；存在新证据缺口时再追加查询。 |
| 问题需要预测 | 核对任务、特征、监督信息和数据划分，再调用相应 train / infer。 | 使用真实 model_id 和已完成作业结果；解释所用评估协议。 |
| 已有充分事实，需要对外说明 | 根据问题组织文本答复；需要结构展示或综合报告时调用 visualize_subgraph / create_analysis_report。 | 指标与观察来自已取得的结果；推断及尚未验证的假设要明确区分。 |

报告工具的 source_results 按真实工具名组织前序原始返回。模型可以据此解释连接、比较指标或提出下一步，但报告生成并不是一套独立的业务正确性证明。构图 SQL 参考执行器只验证关系图模式转换对应的固定查询；因果判断、业务风险与预测有效性仍需要各自适用的数据和评估依据。

## 技能的发现、加载与审核

技能（Skill）是分析流程的组织机制，把某类问题的适用条件、操作步骤和参考资料组织成可复用的指令。技能以 SKILL.md 为入口，可以附带其他资料；Agno 按需发现和读取这些内容。例如，状态检查、路径与连通性、图可视化和统计报告技能分别指导证据获取的不同阶段，构图技能负责需要准备或优化表示的情形。技能指导智能体如何使用工具，不会因为匹配到一个技能，就把 MCP 工具定义硬裁剪为某个固定子集。

加载器组合两类可执行技能：内置技能和当前用户的活动技能。内置资源会复制到运行时技能目录，并把名称规范为小写字母、数字和连字符组成的形式。用户技能存放在独立的用户目录；候选技能则存放在另一个待审核目录。即使候选目录中的文件已经存在，也不会进入智能体的 LocalSkills 加载器，因此“已经生成一份技能草稿”和“该技能已经参与下一次任务”是两个不同阶段。

技能管理接口支持查询、创建、编辑、删除、批准和拒绝。创建时可选择直接写入用户技能，或写入 review_queue；自动形成的待审经验应保留在候选区，供用户核对适用条件、步骤和风险。批准操作将候选目录移动到活动目录，支持指定目标名称，并记录批准时间与关联的 playbook_id。目标技能已存在时返回冲突，避免无声覆盖。拒绝可删除候选文件，也可留下带有拒绝原因的记录；后者仍留在候选区，不因此成为活动技能。

> **审核改变可用指令，不替代工具授权**
> 用户审核一份技能，表示允许它进入后续任务的指令来源；清空图、持久化图优化等操作仍遵循工具自己的审批规则。技能中建议的参数也必须用当前图、数据集和模型的真实 ID 核验。

当前工作台提供技能列表、完整内容查看、.md / .zip 上传，以及候选技能的批准和拒绝。用户技能与候选技能可删除，内置技能不提供删除操作。API 还支持创建和编辑技能；文档中的 API 能力不代表每项都有对应的界面按钮。

## 记忆与学习保存什么

运行服务通过 LearningMachine 统一组织用户画像、用户记忆、会话上下文、可复用知识和决策记录。它们服务于不同时间尺度：用户画像描述稳定偏好，用户记忆保存可长期复用的事实，会话上下文保存当前任务进展和计划，可复用知识承载经过提炼的经验，决策记录帮助保留重要选择。普通聊天历史仍由会话存储管理；将一条工具结果保存在运行记录中，并不意味着它已经成为长期记忆。

可复用知识使用 PostgreSQL 的 pgvector 和混合检索，需要最终解析后的嵌入模型与凭据。EMBEDDING_API_KEY 未设置时，配置依次回退到 OPENAI_API_KEY、LLM_API_KEY、QWEN_API_KEY；服务地址也有对应回退。因此应检查实际解析的服务是否支持该嵌入模型，而不能仅凭某个环境变量是否填写判断功能状态。未获得必要配置时，可复用知识关闭，用户画像、用户记忆和会话上下文仍按各自配置工作。PROPOSE 不表示一次对话必然生成、批准并安装 SKILL.md；知识提议和技能审核是独立机制。

可复用知识需要嵌入模型与凭证，使用 PostgreSQL 的 pgvector 存储并结合混合检索。缺少这组配置时，可复用知识功能保持关闭，用户画像、用户记忆和会话上下文仍按各自配置工作。PROPOSE 表示经验以提议方式处理，不应被理解为任何一次对话都会自动生成、批准并安装一个SKILL.md。知识提议和技能目录审核是独立机制，需要分别观察各自的状态。

保存边界以稳定性和可验证性为准。用户长期偏好“报告优先给结论和指标”适合记忆；某次查询返回的完整节点列表、未经验证的猜测和临时错误不适合直接写入长期记忆。启用执行控制后，已停止的运行不再启动新的学习提取，嵌入和向量写入也纳入取消范围，迟到的记忆写入会检查停止状态。后续运行可以获得被中断任务中已确认工具结果的有限预览，但未完成的回答不能升级成结论、长期记忆或新的操作授权。

前端管理面板提供已保存记忆的列表、搜索和删除；这些是对现有记录的管理，不等同于 LearnedKnowledge 的向量检索。调试记忆问题时，应分别确认记录是否写入、当前用户是否可见，以及嵌入检索是否可用。

## MCP 工具发现与调用身份

图工具通过 MCP 从 Graph Engine 发现，并以原生工具调用形式交给模型。业务工具覆盖数据加载、构图、图分析、机器学习与报告；register_session、delete_graph_session 和 set_session_config 属于会话管理入口。实际工具集合以连接后的发现结果与功能开关为准，例如报告工具可由 MCP_ENABLE_REPORTING_TOOLS 关闭。模型依据工具名称、说明和参数定义组织请求，运行时不使用额外的文本协议替代原生调用。

工具发现和每次实际调用各自拥有连接的创建与关闭过程。发现成功后才把工具集标记为已初始化，连接失败不会留下“初始化成功但没有工具”的状态。并发工具调用使用各自的临时 MCP 会话，避免一个分支关闭连接时影响其他分支。带有后台作业的调用在查询状态时也会创建受控的临时会话；连接与取消都归属于对应的运行和操作。

内部调用上下文由运行服务注入，包括 X-User-ID、X-Session-ID、X-Run-ID 和 X-Agent-ID。X-User-ID 表示固定的默认工作区归属，不是浏览器登录凭据。启用执行控制时，还会附带 X-Execution-Generation 与 X-Operation-ID。工具结果必须留在对应会话范围，数据集也须通过项目作用域检查；模型不能通过业务参数切换归属。

工具调用的传输成功不代表业务成功。运行时会解析结构化结果中的 success 和状态，把 MCP 错误文本转换为可识别的失败结果，再交给依赖调度与会话记录。例如构图加载返回 success=false 时，后续中心性分析不会把空结果当作一张已经加载的图；最终回答应解释失败原因，给出修正数据范围、版本或参数的下一步。

## 同轮工具如何按资源依赖并行

模型可以在同一轮提交多个原生工具调用。运行时保持这些调用的相对先后关系，读取工具目录中的资源声明，构建有向无环图（DAG）。当一个调用写入的资源会被另一个读取或写入时，后者等待前者；当后一个调用要写入前一个正在读取的资源时，同样建立顺序。只有相互独立的节点才并行运行。默认最多并发 4 个工具，可通过 AGENT_TOOL_MAX_CONCURRENCY 调整，取值会限制在 1 到 32 之间。

资源不仅包括当前图，还包括数据集、构图结果、模型文件、文档和会话配置。get_graph_info、中心性、社区和路径分析主要读取图，可以并行；加载图、切换版本、清空图会写图，必须与有关分析排序。train 会写入模型资源，依赖该模型的 infer 需要等待训练完成。构图资源可以按 dataset_id 缩小到具体数据集；subgraph_extraction 只有显式传入 create_version=false 才按只读操作处理。未知工具采用保守屏障，防止未经声明的写入与其他调用发生冲突。

一个常见批次是先提交 load_constructed_graph，再提交 degree_analysis、node_centrality 和 community_detection。加载完成后，三个读取分支可以同时开始；如果最后还要切换图版本，就必须等这些读取结束。DAG 只判断资源冲突，不会替模型生成未知参数。如果 shortest_path 所需的节点 ID 要从 search_node 返回，必须先完成搜索，在下一轮使用真实 ID。训练产生的新 model_id 同样应先读取结果，再提交依赖它的推理请求。

前置调用失败、暂停待确认或仍只返回未完成作业时，依赖节点不会执行，而是收到 TOOL_DEPENDENCY_BLOCKED。已完成的独立分支仍提供有效证据。解决前置问题后，需要重新提交被阻塞的步骤，不能把“跳过”理解成系统已自动排队等待恢复。事件按实际完成时间流出，模型上下文中的工具结果则按原批次顺序整理，以兼顾及时展示和稳定的后续推理。

## 审批暂停与继续执行

需要人工确认的图操作通过 Agno 原生审批机制暂停。目前 clear_graph 与 commit_graph_optimization 进入确认流程：前者会清空当前图，后者把预览后的数据集优化持久化。只读预览与加载已保存的数据集不要求此类确认；用户明确要求训练模型时，该请求就是本次训练授权，不需要为每个训练轮次、进度查询和紧随其后的只读推理重复确认。技能审核与这里的工具审批互不替代。

暂停记录包含待执行工具的调用 ID、工具名称和拟执行参数。前端展示这些信息并提供批准、拒绝；反馈 API 另外支持 modify 决定与 patched_args。Backend 会重新读取当前会话的权威暂停记录，核对 run_id、tool_call_id 和工具名称；过期卡片、已经继续的运行或不匹配的工具会返回冲突。普通批准使用暂停记录中的参数，只有 modify 才使用替换参数，避免浏览器上的陈旧副本改变原操作。

继续执行沿用原 run_id，并保留原工具列表中的已完成结果与产物，只更新本次待确认工具的决定。启用执行控制后，仅已保存且执行者停止的 paused 阶段可以继续；执行代次会递增，使旧阶段的迟到确认不能改变新阶段。重复提交确认时，接口会返回已接受或正在处理中；遇到响应丢失，应先恢复会话状态，不能立即再次执行同一写入。当前反馈接口一次处理一个待确认操作，多个待确认要求会返回明确的冲突状态。

优化示例的顺序是：读取真实节点和 revision，预览同一批操作，说明变化，确认后提交。预览本身没有保存效果；版本冲突意味着基础图已变化，需要重新读取、预览并确认。提交完成后还要加载最新保存版本，再核验图信息或展示子图。被 DAG 阻塞的后续分析需重新提交，这样审批、保存与展示始终围绕同一份可核对的结果。

## 后台作业何时算完成

训练、推理和部分重计算可以返回 async=true 与 job_id。这个返回值表示后台作业已被接受，并不是最终业务结果。图工具包装层会持续调用 get_job_status，直到作业进入完成、失败或取消状态，才结束模型看到的这次工具调用。等待期间会发送图作业进度事件，让界面持续展示阶段、进度和消息，而模型不必重复提交同一个训练或写入请求。

进度使用独立的序号游标：after_seq 表示客户端已经读到的位置，progress_cursor 表示本次返回推进到的位置。运行时检查 job_id 是否一致、状态是否合法、序号是否严格递增，以及是否还有未取完的进度。即使后台作业已经 done，若 progress_has_more 为真，也会先读完剩余进度，随后再交付最终结果。网络传输暂时失败时，只重试同一作业、同一游标的只读状态查询，最多尝试三次，不通过重提业务任务来“恢复”。

一个后台作业也可能把最终结果交给另一个子作业。运行时继续跟踪新的 job_id，重置该作业的进度游标，并检查子作业身份是否为空或形成循环。只有链条最后一个作业交付实际结果时，工具才返回 async=false。失败或取消会形成 success=false 的工具结果，依赖它的节点随之阻塞。如果状态声称已完成却缺少可用的最终结果，运行时会报告结果不可用，不会用队列确认或进度百分比代替成功证据。

对用户而言，训练完成应能对应到工具返回的真实模型 ID、最终指标和模型文件，分析完成应能对应到真实图结果或报告产物。比较同项目的训练实验时，优先使用 Backend 核验的 project_training_summary，确认配置、指标与模型 ID 的对应关系。只有“已提交”“正在训练”或部分进度日志时，可以汇报进展，但不能给出尚未产生的精度、排名或性能比较。

工作台机器学习视图显示已有训练与推理记录、训练曲线和可用的最终指标；项目训练接口汇总同一项目的实验用于比较。报告内容可在结果视图核对，发布的文件可从工作区下载。不同数据集、任务或评估划分的指标应分开解释，不能仅因出现在同一列表就作同口径比较。

## 事件流重连与任务恢复

SSE（服务器发送事件）把文本增量、工具开始与完成、审批请求和图作业进度传给浏览器。事件流是观察单次运行的通道；浏览器断开、刷新页面或切换会话，不等于用户取消任务。运行本身由 AgentOS 持有，重连应尽量回到原 run_id 并读取已有事件。重新发送同一条用户问题可能启动新的业务工作，因此不能用它替代事件恢复。

增量恢复以原事件序号为准。恢复接口先核验用户、会话、智能体与运行的归属，再检查游标是否落在内存事件窗口内。起始游标可以是 -1；后续事件需要连续推进。缓冲区不存在、窗口已被裁剪或游标越界时，服务返回 REPLAY_UNAVAILABLE 或流内的恢复提示。此时客户端应同步已经保存的运行结果，重建消息、工具卡片和待确认状态，不能把重新编号的数据库记录接到旧事件序号后面。

事件重连只读现有事件，不需要重新创建业务智能体、重新发现图工具或再次运行模型。审批恢复则不同：它携带用户对某个具体工具的决定，通过 continue 路径推动原运行进入下一阶段。两者也不同于故障后的持久化修复：后者只补存已有运行结果。把这三类恢复分开，才能避免一次刷新触发重训、一次确认覆盖旧结果，或一次数据库重试重复执行图修改。

> **两类游标不要混用**
> SSE 的事件序号定位整个单次运行中的事件；图作业的 progress_seq 定位某个 job_id 的进度记录。子作业可以从自己的进度起点开始，但不能据此重置整个运行的 SSE 游标。

## 取消、幂等与执行代次

> **先检查部署能力**
> 最新 .env.example 将 IGRAPH_RUN_CANCEL_ENABLED 设为 true；未设置该变量时，代码回退值仍为 false。前端只有在 GET /api/capabilities 返回 run_cancel_v1 / job_cancel_v1 为 true 时才启用相应停止操作；Backend 还会核对运行服务与图服务的能力。edit_latest_turn_v1 单独决定是否允许编辑最新一轮。以下执行控制机制描述的是相关能力启用后的行为。

持久化执行控制由 IGRAPH_RUN_CANCEL_ENABLED 开启，并依赖有效的内部服务密钥。开启后，一次新请求先用 start_request_id 和请求指纹登记，再进行附件处理和智能体启动。相同 ID、相同内容的重试复用已有 run_id，不会重新提交用户问题；相同 ID 携带不同内容会返回 START_IDEMPOTENCY_CONFLICT。同一会话已有活动运行、等待确认或尚未完成状态保存时，新请求会受到并发限制，客户端应依据 can_send 和 active_run 更新输入状态。

取消请求使用独立的 cancel_request_id，并且必须精确指定 run_id 或 start_request_id 中的一个。后者允许用户在尚未拿到 run_id 时停止刚发出的请求：服务可先登记取消意图，使迟到的启动不能继续。取消 ID 与目标绑定，同一 ID 不能被复用于另一个任务。每次运行有 generation（执行代次），首次启动从 1 开始，审批继续时递增；旧代次的状态确认不会覆盖当前阶段，也不能为当前阶段登记新的后台作业。

接受取消后，运行服务会向准备阶段、智能体执行和图后台作业分别发送停止信号，不需要等待一个分支结束才通知另一个。运行内部的 RunScope 跟踪模型请求、工具调用、嵌入计算及其他异步任务；每个分支负责关闭自己持有的连接和迭代器。停止状态会在新操作前以及等待返回后检查，避免取消期间的网络错误触发新的重试工作。后台作业按父子关系登记，单独取消一个作业时也会覆盖它的后代作业。

“已收到停止请求”与“任务完全停止”是不同状态。cancel_status 从 requested 或 stopping 推进到 confirmed，需要准备阶段、智能体及相关后台作业都退出，并确认各自最终状态已持久化。接口可能先返回 202，随后再达到确认状态；仅在界面不再收到文本，不能证明计算已经停止。数据库不可用时，服务会尽力停止已有本地执行，但返回 CANCEL_NOT_CONFIRMED，而不是制造一个已经持久化的成功确认。

## 最终状态如何可靠保存

会话消息与运行结果保存在 PostgreSQL 的原生 AgentOS 会话记录中。启用持久化执行控制后，控制表另外保存运行、作业、执行代次、取消意图和退出证据，不维护第二份聊天记录。状态变更在用户与会话边界内使用短事务和 PostgreSQL 事务级应用锁（advisory lock），把登记、请求受理检查和取消意图作为原子操作处理。事务不会等待远程计算或工作进程退出，以免长时间持锁。

运行结果保存与执行者退出需要独立确认。原生写入前，运行服务捕获当前运行的已清理数据，包括已完成工具、部分回答、审批要求和取消标记，并保留可重试的本地暂存副本。暂存文件通过临时文件与原子替换写入，数据库仍是正式会话存储。发生写入失败时，控制器只把这一条运行合并到最新会话中，再读回核对完整结果；不会重新请求模型、再次训练或重放业务工具来补一条保存记录。

等待持久化期间，terminal_persisted 保持 false，新的会话请求不会越过尚未确认的结束边界。重试副本在数据库读回和控制记录确认之前保留，避免“执行已经退出，但结果丢失”被误判为正常结束。服务重启后，控制器扫描未完成记录，并结合执行者进程的存活证据与已有检查点进行核对；仅仅找不到内存中的任务对象，不足以宣布它已经停止。

已经稳定暂停的运行可以直接保存为取消状态，不需要创建业务智能体执行一次“取消回答”。确认执行者已经退出而运行未完成时，也只保留已有输入、工具事实和部分文字，将该次运行标记为中断或错误。后续讨论可据此说明哪些工作已完成、哪些没有执行，并在必要时重新读取正式产物。这样，取消和恢复保留可核对的成果，同时避免把半成品回答当作完整报告，或因保存重试重复修改图与模型。

| 客户端看到的字段 | 应如何理解 |
| --- | --- |
| run_status | 运行所处阶段，如 preparing、running、paused、completed、cancelled 或 error。 |
| execution_stopped | 停止证据是否齐备；不能单独代替结果持久化确认。 |
| terminal_persisted | 最终或稳定暂停阶段的原生记录是否已核验保存。 |
| cancel_status | 取消意图及确认进度；confirmed 表示停止和保存要求均已满足。 |
| execution_generation、revision | 分别标识执行阶段和控制状态变化；不能作为图的 construction_revision 使用。 |
| can_send | 是否允许在当前会话提交下一条请求，应优先用于界面输入状态判断。 |

服务重启后的核对旨在恢复已保存的展示状态、补存已有结果或标记中断；它不承诺从中断点自动继续模型推理或图计算。原始 SSE 回放缓存属于原进程，丢失后应使用快照和持久化记录恢复界面。
