1. 为什么我要自己搭一套 Agent 工作流平台
先说结论:我折腾 AgentFlow 这类开源零代码 AI Agent 平台,核心动机只有一个——把"能跑通"变成"能长期跑、能自己掌控"。过去一年我用过不少托管型 Agent 平台,拖拽确实爽,但一旦涉及私有知识库、内网数据、浏览器自动化这类需求,就会撞上三堵墙:数据出域、额度限制、以及最要命的——你没法改底层逻辑。
AgentFlow 这个项目的定位很清晰:开源、零代码、可自托管。它把三件事揉进了一个界面里——拖拽式工作流编排、知识库 RAG 检索、浏览器自动化。你可以把它理解成一个"自己家的 Dify/Coze",区别在于代码在你手里,数据在你机器上,想接什么模型、想改什么节点,全凭自己。
这篇文章适合三类人看:一是想给团队搭内部 AI 工具但被数据合规卡住的开发者;二是想学 Agent 编排原理、不想只当"平台用户"的技术爱好者;三是已经在用托管平台、但被额度和定制性逼到想自建的人。我会从整体设计思路讲到具体落地步骤,包括我踩过的坑和实测有效的参数配置。全文基于常见自托管实践补充细节,具体版本以你拉到的代码为准。
先说清楚它能干什么:你打开浏览器,拖几个节点连起来,配好大模型 API,上传几份文档建个知识库,再挂一个浏览器自动化节点去抓页面,点运行,一个能查资料、能上网、能回答问题的 Agent 就跑起来了。整个过程不需要写一行代码,部署用 Docker Compose 五分钟能起来。这就是它的核心价值——把 Agent 开发的门槛从"会写代码"降到"会连线"。
2. 整体架构与设计思路拆解
2.1 三层结构:编排层、能力层、运行层
AgentFlow 这类平台的架构,我习惯拆成三层来看,这样理解起来最省事。
编排层是你在界面上看到的那张画布。节点是积木,连线是数据流。每个节点有输入口和输出口,数据从上游流到下游。这一层解决的是"逻辑怎么组织"的问题。为什么用拖拽而不是写代码?因为 Agent 的逻辑本质是"步骤 + 分支 + 循环",用图形表达比用代码表达更直观,尤其是给非技术同事看的时候。
能力层是节点背后真正干活的东西。大模型调用、向量检索、HTTP 请求、浏览器操作、代码执行——这些是"原子能力"。平台把这些能力封装成节点,你拖一个"知识库检索"节点,背后其实是一整套 embedding + 向量库查询 + 重排的流程。这一层解决的是"能做什么"的问题。
运行层是引擎。它负责解析你画的图,按拓扑顺序执行节点,处理数据传递、错误重试、并发控制。这一层最容易被忽略,但恰恰是自托管和托管平台差距最大的地方——托管平台的运行层是黑盒,你不知道它怎么调度;自托管你能看到日志、能改超时、能加缓存。
提示:判断一个 Agent 平台好不好用,别只看画布漂不漂亮,重点看运行层的日志和错误处理。画布是面子,运行层是里子。
2.2 为什么选"零代码 + 自托管"这个组合
这里要解释一个关键取舍。市面上有两条路线:一条是纯代码框架(比如各种 Agent SDK),灵活但门槛高;另一条是纯托管平台,门槛低但不可控。AgentFlow 走的是第三条路——零代码的交互 + 自托管的部署。
这个组合的好处在于,它同时满足了两个看似矛盾的需求:非技术人员能上手,技术人员能掌控。我实测下来,产品经理能自己在画布上搭一个"客服问答"流程,而我能在这个流程里塞一个自定义的 Python 节点去调内部接口。两边不打架。
代价也有:自托管意味着你要自己管服务器、自己升级、自己处理模型 API 的密钥。托管平台帮你省掉这些,但也拿走了你的控制权。我的判断是,只要你的场景涉及私有数据或者需要深度定制,自托管的收益就远大于成本。
2.3 知识库 RAG 在架构里的位置
RAG(检索增强生成)不是一个节点,而是一条链路。在 AgentFlow 里,它通常表现为"文档上传 → 切分 → 向量化 → 存储 → 检索 → 重排 → 拼进 Prompt"这一串动作。平台一般会把它封装成一两个节点,但你要理解背后的每一步,否则出了问题根本不知道从哪查。
为什么 RAG 这么重要?因为大模型的知识是"死"的,训练完就固定了。你公司的产品文档、内部规范、最新政策,模型一概不知。RAG 的作用就是在提问的瞬间,把相关资料塞进模型的上下文,让它"看着资料回答"。这比微调便宜得多,也比微调更新得快——文档改了,重新索引一下就行,不用重新训练。
2.4 浏览器自动化为什么是差异化能力
大部分零代码平台只能调 API,但现实世界里大量信息不在 API 里,而在网页上。浏览器自动化节点让 Agent 能"真的打开一个浏览器,点按钮、填表单、翻页、截图"。这一下子把 Agent 的能力边界从"调接口"扩展到了"操作任何有界面的系统"。
我举个实际场景:你需要 Agent 每天去某个后台系统导出报表。如果这个系统没有 API,传统方案只能人工点。有了浏览器自动化,Agent 可以模拟登录、点导出、等下载、读文件。这就是它区别于纯 API 编排平台的核心价值。
3. 核心细节解析与实操要点
3.1 节点类型与数据流转机制
AgentFlow 的节点大致分几类,理解分类能帮你快速选型:
| 节点类别 | 典型节点 | 作用 | 使用频率 |
|---|---|---|---|
| 输入输出 | 开始、结束、用户输入 | 定义流程边界 | 每个流程必用 |
| 模型类 | LLM 对话、意图识别 | 调用大模型 | 高频 |
| 知识类 | 知识库检索、文档解析 | RAG 相关 | 中高频 |
| 工具类 | HTTP 请求、代码执行 | 调外部能力 | 中频 |
| 自动化类 | 浏览器操作、网页抓取 | 操作界面 | 按需 |
| 控制类 | 条件分支、循环、变量 | 控制逻辑 | 中频 |
数据流转是重点。每个节点的输出是一个结构化对象,下游节点通过变量引用上游的输出。比如 LLM 节点输出{text: "..."},下游节点就能引用{{llm_1.text}}。这里有个坑:不同节点的输出字段名不一样,你得点开节点看它的输出结构,不能想当然。
注意:变量引用写错是新手最常见的报错来源。建议每加一个节点就先跑一次,看它的实际输出长什么样,再往下接。
3.2 知识库构建的关键参数
知识库这块,参数选不对,检索效果天差地别。我把关键参数和我的实测建议列出来:
切分长度(chunk size):这是最重要的参数。切太短,一句话被切成两半,语义不完整;切太长,检索出来的内容太杂,模型抓不住重点。我的经验值是中文文档 300-500 字,英文 500-800 字符。技术文档可以短一点,叙述性文档可以长一点。
重叠长度(chunk overlap):相邻两个 chunk 重叠的部分,防止关键信息正好卡在切分点上被割裂。一般设成 chunk size 的 10%-20%。比如 chunk 是 400,overlap 设 50-80。
向量模型选择:中文场景优先选对中文友好的 embedding 模型。这个不能省,用错模型检索准确率能差一半。
检索条数(top_k):一次检索返回几个 chunk。设太小可能漏掉关键信息,设太大又会把无关内容塞进上下文,稀释重点。我一般从 3-5 开始调,看效果再增减。
相似度阈值:低于这个分数的检索结果直接丢弃。这个参数能有效过滤噪音,但设太高会导致"什么都检索不到"。建议先设 0.3 左右,观察实际分数分布再调。
3.3 浏览器自动化的稳定性要点
浏览器自动化是最容易"今天能跑明天挂"的环节,因为网页会变。几个实操要点:
第一,选择器要稳。别用绝对路径的 XPath,网页一改就废。优先用稳定的 id、name 或者文本内容定位。如果页面是动态渲染的,记得加等待条件,别用固定 sleep。
第二,登录态要处理。很多系统需要登录才能操作。方案有两种:一是每次跑都模拟登录(慢但稳),二是保存登录态复用(快但可能过期)。我一般用第二种,配合定期刷新。
第三,异常要兜底。网页加载失败、元素找不到、超时——这些都要有重试和降级逻辑。别指望一次成功。
提示:浏览器自动化节点建议单独调试,跑通了再接到主流程里。混在一起调,出了问题你分不清是流程逻辑错还是网页操作错。
3.4 模型接入与成本控制
自托管平台的一大好处是模型随便接。你可以接云端 API,也可以接本地部署的模型。我的建议是分层使用:简单任务(意图识别、格式转换)用便宜的小模型,复杂任务(推理、生成)用强模型。
成本控制有几个实操技巧:一是给 LLM 节点设 max_tokens 上限,防止模型话痨烧钱;二是对重复性查询加缓存,同样的输入直接返回上次结果;三是把知识库检索放在 LLM 之前,先缩小范围再让模型处理,减少 token 消耗。
4. 实操过程与核心环节实现
4.1 五分钟自托管部署
部署这块我用 Docker Compose,这是最省心的方式。整体流程是:拉代码 → 配环境变量 → 起容器 → 初始化 → 访问。
第一步,准备环境。你需要一台能跑 Docker 的机器,本地电脑或云服务器都行。配置建议至少 2 核 4G,如果要跑本地模型,内存得往上加。先确认 Docker 和 Docker Compose 装好了:
docker --version docker compose version第二步,拉代码并进入目录:
git clone <项目仓库地址> cd agentflow第三步,配置环境变量。这一步最关键,配错了起不来。复制示例配置文件:
cp .env.example .env然后编辑.env,重点配这几项:
# 数据库配置 DB_HOST=db DB_PORT=5432 DB_NAME=agentflow DB_USER=agentflow DB_PASSWORD=换成你自己的强密码 # 服务端口 WEB_PORT=3000 API_PORT=8000 # 模型 API 密钥(按你用的服务填) LLM_API_KEY=你的密钥 LLM_BASE_URL=你的接口地址 # 向量库配置 VECTOR_STORE=pgvector注意:数据库密码别用默认值,自托管平台暴露在公网的话,弱密码是最大的风险点。另外
.env文件千万别提交到代码仓库。
第四步,启动服务:
docker compose up -d第一次启动会拉镜像、建表,耐心等几分钟。看日志确认没报错:
docker compose logs -f第五步,访问初始化。浏览器打开http://你的机器IP:3000,第一次进去会让你创建管理员账号。建完账号,进设置页配好模型 API,就能开始用了。
整个流程顺利的话五分钟能搞定。如果卡住,八成是环境变量或者端口冲突,往下看排查部分。
4.2 搭第一个工作流:从零到能跑
我拿一个"文档问答 Agent"举例,这是最典型也最实用的场景。
第一步,建知识库。进知识库页面,新建一个,上传你的文档(PDF、Word、TXT 都行)。上传后平台会自动切分和向量化。这里等它处理完,处理时间取决于文档大小。处理完可以测试检索,输入一个问题,看能不能召回相关段落。如果召回不准,回去调 chunk size 和 top_k。
第二步,拖节点。在画布上拖出这几个节点并连线:
- 开始节点(自动有)
- 知识库检索节点——选中你刚建的知识库
- LLM 节点——配好模型
- 结束节点
连线顺序:开始 → 知识库检索 → LLM → 结束。
第三步,配变量。这是核心。在 LLM 节点的 Prompt 里,你要把检索结果和用户问题拼进去。典型写法:
你是一个知识库助手。请根据以下资料回答用户问题。 如果资料里没有答案,就说"资料中未找到相关信息",不要编造。 资料: {{knowledge_retrieval_1.result}} 用户问题: {{start_1.query}}注意{{}}里的变量名要和你实际节点的输出字段对上。点开节点看输出结构,别猜。
第四步,测试。点运行,输入一个问题,看输出。如果答非所问,先检查检索结果对不对;如果检索对但回答错,检查 Prompt 写法;如果报错,看日志。
第五步,发布。测试通过后,可以发布成 API 或者一个分享链接,让其他人用。
4.3 加一个浏览器自动化节点
在上面流程基础上,我加一个"抓取网页最新信息"的能力。
拖一个浏览器自动化节点,配置步骤:
- 打开页面:填目标 URL
- 等待元素:填你要抓的内容的选择器,确保页面加载完
- 提取内容:选提取文本还是属性
- 关闭浏览器
然后把提取到的内容接到 LLM 节点,和知识库结果一起作为上下文。
这里有个实操细节:浏览器节点很吃资源,如果并发高,机器内存会爆。建议给浏览器节点设并发上限,或者用队列串行处理。
4.4 参数计算实例:chunk 和 top_k 怎么定
很多人问这两个参数到底怎么算。我给个实操方法。
假设你的文档平均每段 200 字,你想让每个 chunk 包含 2-3 段的完整语义,那 chunk size 就设 400-600。overlap 设 chunk 的 15%,也就是 60-90。
top_k 的算法:假设你的 LLM 上下文窗口是 8K token,中文大概 1 字 ≈ 1.5 token,那 8K token 约等于 5000 字。你要留一半给回答和 Prompt 模板,剩 2500 字给检索内容。如果每个 chunk 500 字,那 top_k 最多 5。设 3-5 比较稳妥。
这套算法不精确,但能给你一个起点。实际还是靠测试调优。
5. 常见问题与排查技巧实录
5.1 部署阶段的高频问题
| 现象 | 可能原因 | 排查方法 | 解决 |
|---|---|---|---|
| 容器起不来 | 端口被占用 | docker compose logs看报错 | 改.env里的端口 |
| 数据库连不上 | 密码或主机名错 | 检查.env的 DB 配置 | 确认容器名和密码一致 |
| 页面打不开 | 防火墙或端口没映射 | curl localhost:端口 | 检查端口映射和防火墙 |
| 镜像拉取慢 | 网络问题 | 看拉取日志 | 配置镜像加速 |
我踩过最坑的一次是数据库密码里有特殊字符,导致连接串解析出错。后来学乖了,密码只用字母数字,省心。
5.2 知识库检索不准的排查
检索不准是最常见的问题,排查顺序建议这样:
先看切分结果。进知识库详情,看文档被切成了什么样。如果切得乱七八糟,先调 chunk size。再看检索测试。输入问题,看返回的 chunk 和分数。如果相关 chunk 分数很低,可能是 embedding 模型不合适。如果相关 chunk 根本没被召回,可能是 top_k 太小或者阈值太高。
最后看Prompt。有时候检索是对的,但 Prompt 没把资料用好。检查变量引用对不对,指令清不清楚。
提示:调 RAG 是个迭代过程,别指望一次调好。我的习惯是准备 10 个测试问题,每次改参数都跑一遍,看命中率变化。
5.3 浏览器自动化失败的排查
浏览器节点失败,先分清楚是"没打开"还是"打开了但操作失败"。
没打开:检查 URL 对不对、网络通不通、浏览器依赖装没装。容器里跑浏览器经常缺依赖,看日志里有没有缺库的报错。
打开了但操作失败:八成是选择器问题。用浏览器的开发者工具重新确认选择器,注意页面可能是 iframe 嵌套的,要切进去。还有可能是页面加载慢,元素还没出来就去找了,加等待条件。
5.4 性能与稳定性优化
跑一段时间后,你会发现几个性能瓶颈:
向量检索慢:数据量大了之后,向量检索会变慢。解决办法是给向量字段建索引,或者换更高效的向量库。
LLM 调用慢:这是外部依赖,你控制不了。能做的是加缓存、设超时、做降级(主模型挂了切备用)。
内存泄漏:长时间运行后内存涨。浏览器节点是重灾区,确保每次用完关闭。定期重启服务也是个土办法。
并发控制:别让所有请求同时打进来。用队列限流,保护后端。
5.5 我的独家避坑清单
最后分享几条文档里不会写、但实际很要命的经验:
第一,先跑通最小闭环再扩展。别一上来就搭复杂流程,先用"开始→LLM→结束"跑通,确认模型通了,再加知识库,再加浏览器。每加一层测一次。
第二,变量命名要规范。节点多了之后,llm_1、llm_2这种名字会让你疯掉。改成intent_llm、answer_llm这种有意义的名字。
第三,日志级别调对。调试时开 debug,生产时开 info。debug 日志量大,会拖慢性能。
第四,备份配置。工作流配好了导出成 JSON 存一份。平台升级或者误删的时候,能救命。
第五,模型 API 密钥用环境变量,别硬编码在节点里。换密钥的时候你就知道好处了。
这套平台我用了几个月,最大的感受是:零代码不等于零思考。拖拽降低了操作门槛,但流程设计、参数调优、异常处理这些"脑力活"一点没少。工具帮你省的是敲代码的时间,不是思考的时间。把架构想清楚,把参数调明白,把异常兜住,这套东西才能真正在生产里跑起来。