基于 Tauri v2 + React + Rust 的 Agent 工作流编排桌面应用。在画布上拖拽「开始 / LLM 调用 / 条件分支 / 工具调用 / 人工审批 / 结束」节点,连线组成工作流,一键运行;LLM 节点通过 OpenAI 兼容 API 流式调用,token 实时回流到节点与日志面板。支持多流程管理:每个流程可独立编辑、发布、导出、单独执行;已发布流程可通过 HTTP 按 flow_id 直调,或经 MCP 暴露给任意 AI agent。支持 Human-in-the-Loop:流程跑到「人工审批」节点会挂起,人在节点上给出决策(通过 / 驳回 / 改内容)后从断点续跑,跨进程重启不丢。
本工程已通过
tsc类型检查、vite build生产构建,以及cargo test(13/13 单测)、langgraph-bridge的pytest(HITL 50/50)与cargo build --releaseRust 编译验证。直接npm run tauri:dev即可在 macOS 上启动;npm run tauri:build已验证可产出AgentFlow.app。
| 文档 | 读者 | 内容 |
|---|---|---|
| README.md(本文) | 人(首次接触) | 是什么、怎么装、怎么跑、功能与结构 |
| AGENTS.md | AI coding agent | 改哪里、硬约束、事件/数据契约、已知坑、验证清单、未决风险 |
| langgraph-bridge/README.md | 人 + agent | LangGraph 桥接服务专题:AG-UI 协议、端点、MCP 接入、实测记录 |
- 本仓库在 x86_64 环境下
tauri:build产出的AgentFlow.app为 x86_64 架构。若你的 Mac 是 Apple Silicon(arm64),请在本机重新执行npm run tauri:build,会自动编出 arm64 原生包(或跨平台需加--target aarch64-apple-darwin)。 - 默认构建为 未签名 应用。首次运行需解除 quarantine 并放行 Gatekeeper:
xattr -cr src-tauri/target/release/bundle/macos/AgentFlow.app open src-tauri/target/release/bundle/macos/AgentFlow.app
tauri:build的 DMG 打包步骤 依赖hdiutil,在无显示器的 CI/沙箱中可能失败;这仅影响发行镜像(.dmg),不影响.app本身。本地有桌面环境的 Mac 上通常可正常生成 DMG。
- 🎨 可视化编排:基于
@xyflow/react的节点画布,拖拽、连线、缩放、小地图。 - 🗂 多流程管理:左侧流程列表,可新建 / 复制 / 删除 / 切换;每个流程是独立 DAG。
- 🚀 单独发布 / 导出:每个流程可独立发布(
Draft ↔ Published,发布时版本自增),并可导出为 JSON。 - ▶ 单独执行:按
flow_id执行当前流程;所有运行事件带flowId归属,多流程互不干扰。 - 🤖 LLM 节点:调用任意 OpenAI 兼容端点(OpenAI / DeepSeek / 通义 / 自建网关),流式输出,支持节点级
model覆盖全局模型。 - 🔀 多节点类型:开始、LLM 调用、条件分支、工具调用、人工审批、结束。
- 🧩 LangGraph 外挂执行:
tool节点可把整图委托给仓库内的 langgraph-bridge(FastAPI + LangGraph)执行,结果以 AG-UI 标准协议回流,Rust 侧薄适配层翻译后前端零改动。 - 🔌 真实 MCP 接入:bridge 通过
langchain-mcp-adapters连标准 MCP server(默认内置 stdio demo server),tool节点声明mcp_tool即真实调用。 - 🔁 ReAct 工具循环:
tool节点填tools白名单后,模型在节点内部自主循环——决定调哪个工具、调几次、何时收工(max_iterations显式限轮)。循环封在节点内,图的形状不变,Rust 引擎零改动。 - ◆ 模型分支路由:
condition节点填自然语言判据(expression),候选菜单就是它的出边,由模型选出走哪条(结构化输出choose_branch+temperature=0)。判定在节点内完成、结果进 state 与执行轨迹,节点上直接回显「→ 分支名」。委托 bridge 执行时生效;Rust 原生执行器下会主动发warn提醒「不按判据选边、会走全部出边」。 - ✋ 人工审批(HITL):
human节点让流程挂起等人。执行到该节点时 LangGraph 调interrupt()存下断点,前端节点变紫并弹出审批控件(通过 / 驳回 + 可直接编辑要放行的内容);人提交后经POST /flows/{id}/resume用同一thread_id从断点续跑,已执行节点不重跑。断点落 SQLite checkpointer,实测杀掉服务进程重启后仍能用原 threadId 续跑。 - ⏱ 执行上限显式化:bridge 一律显式设置
recursion_limit(不再吃内部默认 10007),构图前做环检测,含环图自动收紧上限。实测含环流程 1.7 秒报错,而非挂死数小时。 - 🌐 HTTP 按 id 直调:
POST /flows/{flow_id}/run—— 外部系统只需一个flow_id,无需知道图结构。 - 🗨 发布即分享聊天页:点「发布」后自动生成链接
http://localhost:1420/chat.html?flowId=<id>&bridgeUrl=<bridge>—— 浏览器打开即是一个独立聊天页(聊天框 + 气泡),访客主动输入内容后页面以非流式POST /flows/{flow_id}/run拿结果回填。复用全部运行期能力(LLM / 工具 / 分支 / HITL),无额外后端状态;遇人工审批节点会显示「⏸ 等待人工审批」提示回编辑器处理。 - 🛰 MCP 入口:已发布流程经 stdio MCP server 暴露为工具(
list_published_flows/run_flow),任意 MCP client 可触发。 - 💾 持久化(SQLite):全部流程与配置存于
~/.agent-flow/agent_flow.db(rusqlite,WAL 模式)。数据目录刻意不使用系统 app 数据目录(macOS~/Library/Application Support等),而是固定在用户主目录下的.agent-flow/,一处可查、跨平台一致、可被 bridge / MCP server /sqlite3直接读取。可用环境变量AGENT_FLOW_HOME覆盖整个目录。旧版flows.json/workflow.json/config.json在首次启动时自动迁移入 SQLite,原文件改名为*.migrated保留备查。 - ⚙ API 配置:Base URL / API Key / 模型 / 温度,持久化到 SQLite 的
kv表。
- Rust 工具链:
rustup/cargo(≥ 1.70) - Node.js ≥ 18(推荐 20+)
- Xcode Command Line Tools:
xcode-select --install - macOS 10.15+(Tauri v2 要求)
- (可选,仅在用 bridge 时)Python ≥ 3.11 +
uv
cd agent-flow
npm install # 安装前端依赖 + Tauri CLI
npm run tauri:dev # 启动开发模式(自动起 Vite + 编译 Rust + 打开窗口)首次运行会自动打开 AgentFlow 窗口,并创建一个「默认流程」。点击右上角 ⚙ 设置 填入你的 API Base URL 与 Key(默认 https://api.openai.com/v1,模型 gpt-4o-mini),然后:
- 左侧 流程 面板管理流程(
+ 新建/ 复制 / 删除 / 点击切换); - 从工具栏点击 + LLM 调用 等按钮添加节点,拖动节点圆点连线;
- 选中节点在右侧属性面板编辑 Prompt、System 等;
- 点击 ▶ 运行 执行当前流程,观察节点高亮与右下角日志(保存 / 发布 / 导出 在工具栏)。
打包成独立 .app:
npm run tauri:build # 产物在 src-tauri/target/release/bundle/cd langgraph-bridge
uv run uvicorn server:app --host 127.0.0.1 --port 8010 # 本机 8000 常被占用,建议换端口
curl -s localhost:8010/health零 API key 即可跑通:LLM 走内置 MockChatModel,MCP 走本地真实 stdio demo server。详见 langgraph-bridge/README.md。
agent-flow/
├── README.md # 本文
├── AGENTS.md # 面向 AI coding agent 的工作指引(硬约束 / 契约 / 坑)
├── index.html
├── package.json
├── vite.config.ts
├── tsconfig.json
├── src/ # React 前端
│ ├── main.tsx
│ ├── App.tsx # 画布 / 多流程生命周期 / 运行编排
│ ├── styles.css
│ ├── types.ts # 节点 / 配置 / 流程(Flow)类型
│ ├── store.ts # zustand 全局状态(配置 / 日志 / running)
│ ├── lib/tauri.ts # Tauri invoke / 事件封装(含多流程 API)
│ └── components/
│ ├── FlowList.tsx # 多流程列表(新建 / 复制 / 删除 / 发布)
│ ├── Toolbar.tsx # 节点面板 + 运行 / 保存 / 发布 / 导出 / 设置
│ ├── nodes.tsx # 6 类节点渲染(含 human 内联审批控件)
│ ├── Inspector.tsx # 选中节点属性编辑
│ ├── Console.tsx # 运行日志
│ └── Settings.tsx # API 配置弹窗
├── src-tauri/ # Rust 后端
│ ├── Cargo.toml
│ ├── build.rs
│ ├── tauri.conf.json
│ ├── capabilities/default.json
│ ├── icons/ # 应用图标(已生成)
│ └── src/
│ ├── main.rs
│ ├── lib.rs # Tauri 命令入口 + SQLite 存储层 + 多流程(Flow CRUD / 发布 / 执行 / 导出 / resume_flow)
│ ├── llm.rs # OpenAI 兼容流式调用(SSE 解析)
│ ├── workflow.rs # 拓扑排序 + 节点执行 + 事件发射(带 flowId,含环路拦截 / human 节点委托)
│ └── bridge.rs # LangGraph 桥:AG-UI → wf:event 薄适配层(run / resume 共用)
└── langgraph-bridge/ # Python 子项目:LangGraph 外挂执行 + MCP 入口
├── server.py # FastAPI:/run、/flows*、/flows/{id}/resume、/mcp/tools、/health;AG-UI server
├── flow_store.py # Python 侧 SQLite 只读访问层(server 与 mcp_servers 共用)
├── tests/test_hitl.py # HITL 覆盖:挂起 / 续跑 / 人工编辑 / thread 隔离 / 落盘(50 用例)
├── pyproject.toml
├── uv.lock
├── README.md # bridge 专题文档
└── mcp_servers/
├── flows_server.py # stdio MCP:把【已发布】流程暴露为工具
└── demo_server.py # 内置 demo MCP server(add / get_time / echo)
- 前端把画布序列化写回对应流程,调用 Rust 命令
run_flow(flow_id)单独执行该流程(旧接口run_workflow仍保留做兼容)。所有wf:event都会附flowId,前端按流程归属过滤。 workflow.rs用 Kahn 算法做拓扑排序(有环直接报错退出),按依赖顺序执行每个节点:start:输出初始输入文本;llm:调用llm.rs的流式接口,token 通过app.emit("wf:event", …)实时推回前端;condition:Rust 侧为直通(会执行全部出边);委托 bridge 时由模型按expression判据在出边中选一条,选中结果随事件回流并在节点上显示。出边 ≥ 2 时 Rust 侧会发一条warn,避免误以为判据在这条路径上生效;tool:若配置了data.tool = "langgraph"/data.bridge = true/ 非空data.tools(ReAct 白名单)/ 非空data.mcp_tool(direct 单工具),就把整张图委托给langgraph-bridge执行(AG-UI 协议回流);否则为占位实现,亦可在workflow.rs直接 HTTP 调 MCP / 业务服务;human:Rust 原生执行器不做审批(静默跳过审批等于安全事故)。构图前若发现图中含human节点,会发一条warn并把整张图委托给 bridge —— 由 LangGraph 在节点内部interrupt()挂起、等人决策后续跑;end:汇聚上游输出作为最终结果。
- 前端通过
listen("wf:event")接收node:start/token/tool:start/tool:args/tool:result/node:awaiting/node:done/workflow:done事件,更新节点状态、流式填充输出、写入日志。工具调用细节会落在 Console,形如→ 调用工具 add/← add「计算 3 加 5」返回: 3 + 5 = 8。 - 委托 bridge 时协议边界是 AG-UI 标准事件:后端发出
RUN_STARTED / STEP_STARTED / TEXT_MESSAGE_* / TOOL_CALL_* / STEP_FINISHED / RUN_FINISHED / RUN_ERROR,以及 HITL 用的自定义扩展RUN_PAUSED;bridge.rs的translate_agui()翻译成内部wf:event后 emit(RUN_PAUSED→node:awaiting)—— 前端不感知 AG-UI,未来换任意 AG-UI 前端只需替换这一层适配器。 - 暂停不是结束:
RUN_PAUSED之后 bridge 会补发一条RUN_FINISHED且带paused: true,表示「本次 run 结束,但流程没结束」——这个第三态是 HITL 的关键,缺少它前端无法区分「跑完了」与「在等人」。
完整的「事件 / 数据 / 端点」契约表见 AGENTS.md § 4。
- 多流程模型:一个
Flow = { id, name, version, graph, status, updated_at },存于 SQLite 表flows(<data_dir>/agent_flow.db,默认~/.agent-flow/agent_flow.db)。Rust 命令:list_flows/get_active_flow/create_flow/save_flow/delete_flow/set_active_flow。 - 存储层:SQLite(rusqlite,bundled — 无系统依赖)。表
flows存流程、kv存active_id/ API 配置 / 兼容旧接口的单流程 graph。CRUD 为行级原子写(UPSERT),不再全量重写文件;桌面 app 与 MCP server 是两个进程并发访问,靠 WAL +busy_timeout=5000保证「读不阻塞写、写自动等锁」。 - 单独发布:
publish_flow(id, published)翻转draft ↔ published(发布时version自增)。发布是一个状态,代表该流程进入「可被独立触发」集合。 - 单独执行:
run_flow(id)取出该流程的 graph,复用同一套引擎执行;执行事件带flowId,天然支持多流程互不串联。 - 导出:
export_flow(id)把流程以 JSON 落盘到<data_dir>/exports/<name>-<id>.json(默认~/.agent-flow/exports/)。 - MCP 入口:子项目
langgraph-bridge/mcp_servers/flows_server.py把【已发布】流程暴露为标准 MCP 工具(list_published_flows/run_flow),任意 MCP client(Claude Desktop / 任意 MCP 网关 / 自研 agent)均可单独触发某个已发布流程。即:发布 = 进入 MCP 可见集;单独执行 = 外部调run_flow。 - HTTP 直调(不经 MCP):bridge 另提供
GET /flows与POST /flows/{id}/run——外部系统(CI / 业务服务 / curl)只要传一个flow_id就能执行该已发布流程,无需知道图结构:bridge 自己从 SQLite 取图,并在请求未带config时自动使用 app 里配好的 LLM 配置。默认返回流式 AG-UI SSE,stream:false返回 JSON。也就是说 MCP 不是执行流程的必要条件,它只是给 AI agent 用的可选「发现入口」(且它内部同样调这个 HTTP 端点)。详见 langgraph-bridge/README.md。
固定在 ~/.agent-flow/(刻意不用系统 app 数据目录,便于外部工具直接读取):
~/.agent-flow/
├── agent_flow.db # SQLite:flows + kv(WAL 模式)
├── agent_flow.db-wal # WAL 边车文件(运行时出现)
├── agent_flow.db-shm
├── checkpoints.db # LangGraph checkpointer:HITL 的挂起点存档(bridge 侧写)
├── checkpoints.db-wal # 同上边车(运行时出现)
├── checkpoints.db-shm
└── exports/ # export_flow 导出的流程 JSON
checkpoints.db与agent_flow.db是两回事:前者是运行期状态(谁的图停在哪一步、state 快照),后者是设计期数据(图画什么、是否发布)。分开存的好处是「删流程」不会连累别人正在等待的审批;代价是孤儿断点需要另行清理。
旧版 JSON 存储(
flows.json/workflow.json/config.json)位于旧的系统配置目录(macOS~/Library/Application Support/com.agentflow.app/)。首次启动读入 SQLite 后,这些文件在原目录被改名为*.migrated保留备查 —— 也就是说.migrated文件不在~/.agent-flow/下。若旧目录里已有agent_flow.db,会被整体复制过来(含-wal/-shm边车文件)。
flows(id PK, name, version, graph /* JSON 文本 */, status /* draft|published */, updated_at)
kv(key PK, value) -- active_id | config | legacy_workflowHITL 的挂起点不在这两张表里,而在同目录的
checkpoints.db(由 LangGraph 的AsyncSqliteSaver管理,表结构由 langgraph-checkpoint 定义)。
| 变量 | 作用 | 默认 | 读取方 |
|---|---|---|---|
AGENT_FLOW_HOME |
数据目录 | ~/.agent-flow |
Rust + Python |
AGENT_FLOW_DB |
直接指定 .db 文件(支持 ~) |
<data_dir>/agent_flow.db |
Python |
AGENT_FLOW_CHECKPOINT_DB |
HITL 断点库路径(测试必改,否则会往真实目录写) | <data_dir>/checkpoints.db |
Python |
LANGGRAPH_BRIDGE_URL |
bridge 地址(.../run 或裸 base 均可) |
http://127.0.0.1:8000 |
Rust + Python |
# 1. 看有哪些已发布流程(?all=true 含草稿)
curl -s http://127.0.0.1:8010/flows
# 2. 传 flow_id 直接执行 —— 流式(AG-UI SSE)
curl -N -X POST http://127.0.0.1:8010/flows/<flow_id>/run \
-H 'Content-Type: application/json' -d '{"input":"计算 3 加 5"}'
# 3. 传 flow_id 直接执行 —— 非流式(脚本 / CI 友好)
curl -s -X POST http://127.0.0.1:8010/flows/<flow_id>/run \
-H 'Content-Type: application/json' -d '{"input":"计算 3 加 5","stream":false}'
# → {"ok":true,"flowId":"...","steps":4,"result":"...","usedStoredConfig":true}
# 若图里含 human 节点,会在这里停下并多返回:
# → {"ok":true,...,"paused":true,"awaiting":{"nodeId":"h1","prompt":"...","actions":["approve","reject"]},
# "resumeUrl":"http://127.0.0.1:8010/flows/<flow_id>/resume"}
# 4. 【HITL】从断点续跑 —— 必须带挂起时返回的 threadId
curl -s -X POST http://127.0.0.1:8010/flows/<flow_id>/resume \
-H 'Content-Type: application/json' \
-d '{"threadId":"<挂起时返回的 threadId>","decision":{"decision":"approve"}}'
# 人工改内容后放行(value 会覆盖该节点向下游传递的文本):
# -d '{"threadId":"...","decision":{"decision":"approve","value":"发票已核验,金额 1280 元"}}'
# 驳回(可带理由):
# -d '{"threadId":"...","decision":{"decision":"reject","note":"发票缺失,请补充后重提"}}'
# 6. 【发布即分享】打开聊天页(浏览器访问,访客可主动输入内容运行流程)
open "http://localhost:1420/chat.html?flowId=<flow_id>&bridgeUrl=http%3A%2F%2F127.0.0.1%3A8010&name=<流程名>"
# 聊天页是前端 public/chat.html,由 Vite 静态资源服务提供;
# 页面从 URL 读取 flowId/bridgeUrl/name,以非流式 POST 到 bridge 的 /flows/{id}/run,
# 对 ok / paused(人工审批) / error 三态都有处理;无需额外后端状态。
# 5. 直接查库(不启动 app 也能看流程)
sqlite3 ~/.agent-flow/agent_flow.db "SELECT id,name,version,status FROM flows"错误语义:流程不存在 404 / 未发布 409 / 图为空 422 / 执行失败 500;resume 另加 缺 threadId 或 decision → 422、该 thread 上没有等待中的挂起点 → 可读错误(不是静默重跑,也不是默认放行)。
面向 AI agent 的完整改造 recipe(新增节点类型要动哪 6 处、新增 Tauri 命令三件套等)见 AGENTS.md § 5。
src/components/nodes.tsx:新增渲染组件并加入nodeTypes映射;src/components/Toolbar.tsx的PALETTE增加一项;src/App.tsx的DEFAULT_DATA增加默认data;src/types.ts的NodeType增加联合类型成员;src-tauri/src/workflow.rs的match ntype分支补充该类型的执行逻辑;- (若 bridge 也要支持)
langgraph-bridge/server.py的make_node内if/elif ntype链。
这 6 处是必改的;
human是个例外样本——它额外牵动 checkpointer、RUN_PAUSED事件、resume 端点与前端等待态,因为它的本质是「执行期要停下」,而不只是「多画一个框」。
最小可用配置:往画布加一个 人工审批 节点,把上游连进来、下游连出去,然后确保图能走 bridge(任一 tool 节点配置非空 tools 白名单 / mcp_tool / tool = "langgraph",或干脆按下面的「整图委托」方式跑)。节点属性面板可配三件事:
| 配置项 | data 键 |
说明 |
|---|---|---|
| 审批提示语 | hitlPrompt |
给审核人看的问句,如「本次报销金额 1280 元,是否放行?」 |
| 候选动作 | actions |
默认 ["approve","reject"];也可加 edit 等自定义动作 |
| 允许修改内容 | allow_edit |
默认 true;关掉则审核人只能原样通过 / 驳回 |
运行到该节点时:节点变紫、弹出审批控件(可直接编辑要放行的文本),Console 打印挂起信息。点「通过」→ 走 resume_flow 从断点续跑,前面的节点不会重跑;点「驳回」→ 向下游传递 [已驳回] <理由>。审核人手动改过的内容会成为 value,替代原输入传给下游。
tool 节点在 Rust 侧有两条路径:
- 路径 A(已落地,推荐先试):
tool节点配置非空data.tools(ReAct 白名单)/data.mcp_tool(direct 单工具)/data.tool = "langgraph"/data.bridge = true,即把整张图 POST 给子项目langgraph-bridge,由 LangGraph 编译执行。该服务已接真实 MCP——tool节点data.mcp_tool(如demo__add)即触发对标准 MCP server(默认demo,stdio)的真实调用,结果以 AG-UI 协议流式回流,Rust 薄适配层翻译为wf:event推前端,前端零改动。 - 路径 B(Rust 原生):在
workflow.rs的tool分支直接 HTTP 调你的 MCP / 业务服务(任意标准 MCP server、内部网关或 REST 服务均可),将结果写入output并沿边传递。
走路径 A 时,tool 节点有两种模式,由 data 里有没有 tools 白名单决定:
| 模式 | 配置 | 行为 |
|---|---|---|
direct |
data.mcp_tool = "demo__add" |
单工具直调:上游文本 → 调这一个工具 → 返回 |
react |
data.tools = ["demo__add","demo__get_time"](或 ["*"]) |
模型在节点内部自主循环:决定调哪个、几次、何时收工 |
ReAct 模式要点:max_iterations 显式限轮(默认 6);留空 tools 即回到 direct,旧配置完全兼容;循环封在节点内 → 对外只有一次 STEP_STARTED / STEP_FINISHED,图的形状不变,Rust 侧拓扑排序与环检测零改动(cargo test 13/13 通过,含新增的暂停事件映射与 URL 归一化用例)。
condition 节点的分支路由(走路径 A 时生效):data.expression 填自然语言判据(如「上游内容是否在询问天气」),模型在出边中选一条;出边顺序即候选编号,第 0 条为「命中」默认分支。用便宜快的小模型即可(data.model / cfg.router_model 覆盖)。详见 langgraph-bridge/README.md。
本工程 capabilities/default.json 仅含 core:default。Debug(tauri:dev)下自定义命令自动放开,可直接运行。若要做 Release(tauri:build),需在 src-tauri/permissions/ 下定义显式权限集(授予 allow-run-flow 等),再在 capability 中引用,否则自定义命令会被 ACL 拦截。
🔴 高优先级(安全性)
环路保护的路径不对称→ 已在 S2 修复。bridge 构图前做 DFS 环检测(服务端日志 +RUN_STARTED.hasCycle),并一律显式设置recursion_limit(优先级wf.recursion_limit>AGENT_FLOW_RECURSION_LIMIT环境变量 > 按图规模推算,有环时收紧到max(12, n*2)),超限转成可读的RUN_ERROR。实测含环流程 1.68 秒返回错误,而非一路跑到 10007 步(旧行为外推:真实 LLM 数小时挂死 + 等额计费)。 同时修正workflow.rs中「存在环或孤立节点」的错误文案(Kahn 下失败的只可能是环——孤立节点 in-degree 为 0,照样会被排出)。 遗留:前端onConnect仍无环校验(画环本身是合法需求,真正该拒绝的是 Rust 原生执行器,它已拦截)。详见 AGENTS.md § 7。- 正式环境化:三处
127.0.0.1落差(bridge 地址、MCP 挂载、鉴权)——当前所有调用入口均无鉴权,仅适合本机。HITL 让这条从「不方便」升级为「危险」:/flows/{id}/resume没有审批人身份校验,任何能访问端口的人都能替你「通过」一次审批。上生产前必须先补鉴权。
🟡 功能缺口
condition的跨引擎语义对齐:bridge 侧已是模型判定(S2),Rust 原生执行器侧仍是直通 +warn。若要让 Rust 侧也支持,需在同步执行器里引入模型调用,或把判定拆成独立节点;- Loop Engineering 四件套仍不齐:有「模型选边」(
condition)与「节点内 ReAct 循环」(tool),但缺迭代计数器、可配的继续/退出判据(无法表达「迭代到满意为止」)、跨节点迭代状态(累积器 / 上一轮结果); - HITL 的边界(已实现,但仍是 1.0 版):
- 审批只能在节点上做(
human节点),还不能在「任意节点执行前/后」插钩子; - 挂起态无 TTL、无超时自动决策、无待办列表 —— 挂起的 run 只能靠人回来手动续,服务重启后需要旧
threadId才能找回(前端节点上会存着,但换个客户端就断了); - 无审批人身份与鉴权:谁都能调
/resume,谁都能点「通过」。生产必须补Authorization+ 审批人白名单(这是当前最大的安全缺口); - 一个 thread 同时只能有一个挂起点(串联多审批可以,并行分支同时等人不行);
human节点在 Rust 原生执行器下不生效(会被整图委托给 bridge,见上);
- 审批只能在节点上做(
tool节点 Rust 原生接 MCP 的便捷封装(当前 MCP 接入由langgraph-bridge子项目承担);- ReAct 循环的跨节点迭代状态(累积器 / 上一轮结果)尚不可配;循环内部的中间态随 checkpointer 落盘,但尚无清理策略(
checkpoints.db会随运行次数增长); - bridge 侧
tool(langgraph)会把整图(含前驱节点)再跑一遍,属演示性「接管」;生产应改为只委托该节点之后的子图; - 流程导入(从导出的 JSON 反向导入)、节点参数校验;
- 流程重命名 UI、流程分组 / 搜索;
- 多 LLM 供应商切换与失败重试;
- bridge 进程管理:原型手动起,生产可改 Tauri sidecar 内嵌 Python(代价是包体膨胀 + 跨平台打包)。
| File | What it is |
|---|---|
| README.md | 你在这里 —— 功能总览 + 快速开始 + 运行语义 |
| AGENTS.md | AI coding agent 的权威工作指引(硬约束、文件职责表、改造 recipe、验证清单) |
| CHANGELOG.md | 版本日志(Keep a Changelog 格式) |
| SECURITY.md | 安全模型现状(无鉴权边界)+ 漏洞私报流程 |
| langgraph-bridge/README.md | bridge 子项目专题:HITL / MCP / AG-UI 协议细节 |
MIT © agent-flow contributors