Skip to main content
Glama
lidicn

AutoFlow Gateway

by lidicn
README.md
<div align="center">

# AutoFlow

### 对着 AI 说一句话,你家就多一个自动化。

不用打开 Node-RED,不用查实体 ID,不用担心 AI 半夜把你家门锁打开。

**完整版(Docker 网关 + WebUI + 安全闸)** · **核心版(零依赖 Python 库,给 AI agent 直接用)**

[快速安装](#三安装五分钟) · [接上你的 AI](#四让你的-ai-接上-autoflow) · [第一个自动化](#五你的第一个自动化完整走一遍) · [四种做法对比](#二四种做法横向对比) · [核心版](#九核心版轻量-node-red-操作工具)

</div>

---

## 一、这东西到底解决什么问题

如果你在用 Home Assistant,大概率经历过这三件事。

**第一件:加一个自动化,比想象中麻烦得多。**

你想要「书房电脑一开机,就把显示器挂灯打开」。听起来 30 秒的事。实际上:打开 Node-RED
→ 拖一个触发节点 → 想不起来电脑的实体叫什么 → 切到 HA 开发者工具搜 → 复制出
`switch.d4f0eaeab731_switch` 这么个东西 → 回来粘贴 → 再拖一个判断节点 → 再去搜挂灯
→ `light.yeelink_cn_555003624_lamp22_s_2` → 拖 call service 节点 → 连线 → 部署 →
去书房开一次电脑测试。

半小时过去了。而你脑子里那句话,只有 15 个字。

**第二件:让 AI 帮你写,它会一本正经地编。**

你把需求丢给 ChatGPT/Claude,它很流畅地给你一段 flow JSON,里面写着
`light.study_desk_lamp`。看起来特别合理 —— 但你家没有这个实体。真实的 ID 是
`light.yeelink_cn_555003624_lamp22_s_2`,AI 不可能猜出来。

要命的是**它不会报错**。导入 Node-RED,部署成功,绿灯,一切正常。然后它永远不触发。
你三天后才发现,还以为是自己哪里没配对。

**第三件:真让 AI 连上 HA,你会睡不着。**

要让 AI 真正能干活,你得把 HA 长期访问令牌给它。那一刻它就拥有了你家所有设备的完整控制权
—— 灯、窗帘、门锁、水阀。它不需要恶意,只需要一次幻觉、一个手滑的批量操作。

**AutoFlow 就是插在你和 AI 之间的那一层。**

它拿着钥匙,AI 没有。AI 想干什么,得先跟它说;它检查完、在虚拟环境里试跑过、确认没问题,
再送到你手机上让你点一下「同意」,才真的落到你家里。

---

## 二、四种做法横向对比

还是那个需求:**「书房电脑一开机,就把显示器挂灯打开」**。看四种做法分别会发生什么。

### 做法 A:自己在 Node-RED 里拖

打开浏览器 → 翻 HA 开发者工具找两个实体 ID → 拖 4 个节点 → 连线 → 配置每个节点 →
部署 → 跑去书房开电脑验证。

**结果**:能成,但花了 30 分钟,而且你得懂 Node-RED 的节点模型。想加第 20 个自动化时,
你已经不想加了。

### 做法 B:把 HA 令牌给 AI,让它直接写

你说需求,AI 生成 flow,直接调 Node-RED 接口部署。

**结果**:10 秒完成,看起来很爽。但实体 ID 是编的,flow 静默失效。而且 AI 现在握着你家
所有设备的控制权 —— 它下一次「顺手帮你优化一下」,可能就把 12 个自动化全改了。
**你没有任何刹车。**

### 做法 C:给 AI 配一份 skill 文档,它照着规范写

比 B 好一些 —— AI 知道你的命名习惯、知道该用哪些节点、输出格式更规整。

**结果**:格式对了,**实体 ID 照样是编的**。skill 是一份静态文档,它不知道你家此刻有哪些
设备、哪个灯叫什么、开关现在是开还是关。它也验证不了写出来的东西能不能跑。
安全问题一点没变:令牌还在 AI 手上。

> 这是很多人当前的状态 —— 以为加了 skill 就解决了,其实只解决了「格式」,
> 没解决「事实」和「安全」这两个真问题。

### 做法 D:AutoFlow

你在聊天框说:「书房电脑开机就把显示器挂灯打开」。

背后发生的事:

1. AI 问网关:「书房有个叫『显示器挂灯』的东西,实体 ID 是啥?」
   网关回:`light.yeelink_cn_555003624_lamp22_s_2`,当前 `off`,可能状态 `on/off`。
   —— **实体 ID 不再靠猜,是查出来的。**
2. AI 写 5 行 DSL(不是 200 行 JSON):

   ```
   场景: 书房电脑开机则开显示器挂灯
   触发: switch.d4f0eaeab731_switch on
   动作: light.turn_on(light.yeelink_cn_555003624_lamp22_s_2)
   预期:
     light.yeelink_cn_555003624_lamp22_s_2 = on
   ```

   注意最后那个 `预期:` —— AI 得**先声明「跑完之后灯应该是亮的」**。
   这是它给自己立的军令状。

3. 网关编译成真正的 Node-RED flow,**在一个虚拟的 HA 副本里把它跑一遍**,
   然后对照那句 `预期:` 检查灯是不是真的亮了。
   对不上就打回去让 AI 改,**你根本不会看到废品**。
4. 通过了才进「待批准」队列,你手机上收到通知。
5. 你点「同意」,它才落到你家 Node-RED 上。

**结果**:一句话,1 分钟,产出的 flow 干净可读(不是一坨 function 节点),
而且从头到尾 AI 都没碰过你的 HA 令牌。

### 汇总

| | A. 自己拖 | B. AI 直连 | C. AI + skill | **D. AutoFlow** |
|---|---|---|---|---|
| **你要会什么** | Node-RED 节点模型 | 会审 flow JSON | 会审 flow JSON | **会说话** |
| **加一个自动化要多久** | 20–40 分钟 | 1 分钟 | 1 分钟 | **1 分钟** |
| **实体 ID 从哪来** | 你手动查 | AI 猜(常错) | AI 猜(常错) | **网关实时查真实设备** |
| **AI 编错实体会怎样** | — | 静默失效,几天后才发现 | 静默失效 | **闸门当场拦下,打回重写** |
| **上线前验证过吗** | 你手动跑一次 | 没有 | 没有 | **虚拟环境重放 + 断言** |
| **AI 能直接动你家设备吗** | — | **能,随时** | **能,随时** | **不能,必须你点同意** |
| **你的 HA 令牌谁拿着** | 你 | **AI** | **AI** | **只有网关** |
| **能撤销吗** | 手动改回去 | 靠 NR 自己的备份 | 同左 | **一键下线 + 每次部署存快照** |
| **产出的 flow 好维护吗** | 取决于你 | 常是一坨 function | 好一些 | **编译产出,结构统一** |
| **换个 AI 模型要重做吗** | — | 要重配令牌 | 要重写 skill | **换一个身份码就行** |
| **AI 能自己批准自己吗** | — | **能** | **能** | **永远不能**(批准入口只在网页端) |

一句话总结这张表:**A 累,B 危险,C 是把 B 包装得好看了一点,D 才真正解决了「事实」「验证」「刹车」三个问题。**

### 什么情况下你不需要 AutoFlow

诚实地说:

- 你家总共就 3 个自动化,写完再也不动 —— 不值当为它多跑一个服务。
- 你没有 Docker,也不想装 —— AutoFlow 目前推荐容器部署。
- 你享受手动拖节点的过程 —— 那是另一种乐趣,AutoFlow 帮不上忙。

AutoFlow 的价值随「你想让家里变聪明的野心」增长。自动化越多、越常改、越怕出事,
它越划算。

---

## 三、安装(五分钟)

### 前置条件

- 一台常开的机器:NAS、软路由、树莓派、旧电脑都行(跟 HA 同一个局域网)
- 上面装了 **Docker**(没有的话脚本能帮你装,见下)
- 你已经在用 **Home Assistant** 和 **Node-RED**

### 第 1 步:一条命令装好

**安装到当前目录(推荐,NAS 用户常用):**

```bash
curl -fsSL https://raw.githubusercontent.com/lidicn/AutoFlow/main/install.sh | bash -s -- -d "$(pwd)"
```

**安装到默认目录(Linux `/opt/autoflow`,macOS `~/autoflow`):**

```bash
curl -fsSL https://raw.githubusercontent.com/lidicn/AutoFlow/main/install.sh | bash
```

脚本会自动:检查 Docker → 下载代码 → 构建镜像 → 启动 → 等待服务就绪。

> 安装完成后,代码和数据都在你指定的目录里。进入该目录可以看到 `docker-compose.yml`、`data/`、`.env` 等文件。
> 以后更新:在安装目录下执行 `bash install.sh --update`(**保留**你的数据和配置)。

- 想换目录:`bash install.sh -d /volume1/docker/autoflow`
- 机器上没 Docker(仅 Linux):`bash install.sh --install-docker`
- 中国大陆网络慢:`export GITHUB_PROXY=https://ghproxy.com/` 后再执行安装命令

### 第 2 步:拿到控制台钥匙

**⚠️ 这一步最容易卡住,请务必看。**

出于安全考虑,AutoFlow 首次启动会自动生成一个访问令牌。**不带令牌从局域网访问网页端会被
403 拒绝** —— 很多人以为装失败了,其实只是缺钥匙。

拿钥匙:

```bash
docker exec autoflow_gateway cat /data/.webui_token
```

(或者直接看宿主机上的挂载文件:`cat /opt/autoflow/data/.webui_token`;如果装到了别的目录,路径跟着改)

**想一步到位**(直接打印可点击的链接,把 IP 换成你机器的):

```bash
TOKEN=$(docker exec autoflow_gateway cat /data/.webui_token)
echo "http://&lt;NAS_IP&gt;:8000/?token=$TOKEN"
```

> 容器名不是默认的 `autoflow_gateway`?先 `docker ps | grep autoflow` 看实际名字,命令里替换掉即可。

拿到形如 `3dX-0KNWrdMk_8aNmjk926J9IC9MZ0Xg` 的一串字符,然后用它开门:

```
http://<你这台机器的IP>:8000/?token=<刚才那串字符>
```

> 建议把这个完整网址存成手机书签 —— 以后批准自动化就靠它,在被窝里点一下就行。

### 第 3 步:告诉它你家在哪

网页端打开后,进 **⚙️ 设置 → 连接配置**,填两组信息:

| 填什么 | 说明 |
|---|---|
| **Home Assistant 地址** | 如 `http://&lt;LAN_IP&gt;:8123`。<br>⚠️ 如果 HA 跟 AutoFlow 在**同一台机器**上,要写 `http://host.docker.internal:8123`,**不能写 localhost** |
| **HA 长期访问令牌** | HA 里:左下角头像 → 安全 → 长期访问令牌 → 创建 |
| **Node-RED 地址** | 如 `http://&lt;LAN_IP&gt;:1880` |
| **Node-RED 账号密码** | 如果你的 NR 开了登录 |

保存后立即生效,不用重启。

**这些凭证从此只存在于网关里,任何 AI 都读不到。** 这是整个设计的地基。

---

## 四、让你的 AI 接上 AutoFlow

### 第 1 步:给 AI 发一张身份证

进网页端 **🤖 Agents** 面板 → 输入一个名字(比如 `我的Claude`)→ 点「创建」。

会弹出一串 `af_` 开头的身份码。**只显示这一次,立刻复制。**

> 为什么要发身份证?因为每个 AI 干过什么都会独立记账 —— 谁提的方案、谁改的东西,
> 全都可追溯。匿名连接一律拒绝。哪天某个 AI 不靠谱了,点一下「吊销」,它立刻失去所有能力。

### 第 2 步:在 AI 客户端里配 MCP

统一填这三样:

- **传输方式**:Streamable HTTP
- **地址**:`http://<你的机器IP>:8000/mcp`
- **请求头**:`Authorization: Bearer <刚才那串身份码>`

几种常见客户端的写法:

**Claude Desktop / WorkBuddy 等(JSON 配置)**

```json
{
  "mcpServers": {
    "autoflow": {
      "type": "streamableHttp",
      "url": "http://&lt;LAN_IP&gt;:8000/mcp",
      "headers": {
        "Authorization": "Bearer af_你的身份码"
      }
    }
  }
}
```

> 不同客户端字段名略有差异(`type` 有的叫 `transport`,值可能写作
> `streamable-http`/`http`)。照着你客户端的文档填,**只要保证是
> Streamable HTTP + 那个 URL + 那个请求头就行**。

**浏览器扩展类客户端(如 DeepSeek++)**

界面里填 URL 和 Bearer 字段即可。如果扩展跑在浏览器里、报跨域错误,
在 `.env` 里把扩展的 origin 加进白名单:

```
AF_MCP_CORS_ORIGINS=chrome-extension://xxxxxxxx
```

**只支持 SSE 的老客户端**

地址换成 `http://<IP>:8000/sse`。

### 第 3 步:验证连上了

对 AI 说一句:

> 帮我看看书房都有什么设备

如果它能列出你家书房的真实设备(带真实实体 ID 和当前状态),就通了。

### 不用手动给 AI 装说明书

网关里内置了一份完整的使用指南。AI 连上后自己调用 `autoflow_get_skill` 就能取到 ——
你不需要复制粘贴任何 prompt。指南更新了,AI 下次自动拿到新版。

---

## 五、你的第一个自动化(完整走一遍)

### 你说

> 书房电脑一开机,就把显示器挂灯打开

### AI 做(你不用管,但知道它在干嘛会更放心)

1. **查设备** —— 问网关「书房的显示器挂灯是哪个实体」。
   网关返回该区域所有沾边的实体,带域、当前状态、可能状态,让 AI 自己挑。

   > 这里有个细节体现设计用心:AI **不需要提前知道**「挂灯」是 `light` 还是 `switch`。
   > 很多设备名字看着像灯,实际是开关。网关把候选全给它,让它按用途挑,而不是逼它猜。

2. **写 DSL** —— 就是本文开头那 5 行。不是 200 行 JSON。
3. **提交编译** —— 网关做四件事:
   - 语法检查
   - 实体校验(ID 是否真实存在)
   - 节点校验(用到的节点类型在你的 Node-RED 上装了没)
   - **虚拟重放**:在一个 HA 数字孪生里真的执行一次,断言灯确实变成了 `on`

   任何一环挂了都会打回给 AI,附带具体原因。**AI 自己修,修好再提。**

### 你批准

网页端 **🛡️ 安全闸** 面板出现一条待批准。你能看到:

- 这个自动化叫什么、哪个 AI 提的
- 完整 DSL(人话,看得懂)
- 编译出的 flow 结构
- 虚拟环境的验证结果

点 **同意** —— 落到你家 Node-RED,立即生效。
点 **拒绝** —— 什么都不会发生。

> 配了 Bark 推送的话,待批准会直接推到手机(**⚙️ 设置**里填)。

### 出问题了怎么办

**🚀 已部署** 面板列出所有经 AutoFlow 部署的自动化,点一下就能**下线**。

这里有个贴心的设计:它**只能下线自己部署的东西**。你手工在 Node-RED 里搭的那些 flow,
AutoFlow 认都不认,更别说删了 —— 想误伤都做不到。

每次部署还会自动存一份快照,需要追溯「上周那版是什么样」时可以翻。

---

## 六、网页端有什么

手机、平板、电脑自适应。九个面板:

| 面板 | 干什么 |
|---|---|
| **▣ 概览** | 现在有多少自动化在跑、有没有待办 |
| **🛡️ 安全闸** | **最常用**。AI 提的东西在这儿批准或拒绝 |
| **✨ 提案** | AI 沉淀的经验/建议。你可以把好的升格成公用知识,反哺所有 AI |
| **🚀 已部署** | 所有已上线的自动化,可查看、可一键下线 |
| **🔗 子流程** | 可复用的能力积木(推送、历史查询等),可启用/停用 |
| **🤖 Agents** | 发身份码、重置、吊销 |
| **🩺 诊断** | 出问题时看这里:执行链路、失败原因 |
| **📝 笔记** | 你的想法暂存区。「哪天该弄个……」记下来,不进流程 |
| **⚙️ 设置** | 连接配置、推送、安全选项 |

**一条不可动摇的规矩**:批准和升格**只能在网页端做**,MCP 接口里根本没有这两个能力。
AI 不可能自己批准自己 —— 这不是靠自觉,是接口层面就不给。

---

## 七、常见问题

**Q:网页打不开 / 一直 403?**
八成是没带令牌。回到[第 2 步](#第-2-步拿到控制台钥匙)拿钥匙,用
`http://IP:8000/?token=xxx` 访问。

**Q:连接配置填了,但连不上 HA?**
HA 跟 AutoFlow 在同一台机器时,地址要写 `http://host.docker.internal:8123`,
写 `localhost` 一定失败 —— 容器里的 localhost 是容器自己。

**Q:AI 说它连不上 / 401?**
身份码错了或被吊销了。去 **🤖 Agents** 面板重置一个新码,更新到 AI 客户端。
身份码只在创建时显示一次,丢了就重置,找不回来。

**Q:AI 提交的东西总被打回?**
看打回原因(AI 通常会告诉你)。最常见两种:
① 实体不存在 —— 你说的设备名网关找不到,换个说法或去 HA 里确认名字;
② 节点类型未注册 —— 你的 Node-RED 缺某个插件。

**Q:能让它不用每次都问我吗?**
能,但**默认不建议**。测试环境可以设 `AF_AUTO_APPROVE=true`。
接真实设备的环境请保持人工确认 —— 这是最后一道刹车。

**Q:AI 会不会偷偷改我已有的自动化?**
不会。网关不提供「全量替换」「批量删除」这类操作 —— 不是靠规则禁止,是**接口里压根没有**。
另外还有爆炸半径上限、受保护流标签、所有权隔离(AI 动不了别人建的东西)。

**Q:门锁、水阀这种危险设备呢?**
属于高危域,需要额外的升级确认,不能跟开灯走同一条路。

**Q:AutoFlow 挂了,我家自动化会停吗?**
不会。自动化跑在你自己的 Node-RED 上,AutoFlow 只是「制造和管理」它们的工具。
网关挂了只是暂时不能加新的,已有的照常运行。

---

## 八、安全边界一览

| 这件事 | 在哪做 | 谁能做 |
|---|---|---|
| 查设备、写方案、提交提案 | MCP(带身份码) | AI |
| **批准部署** | 网页端 | **只有你** |
| **升格公用知识** | 网页端 | **只有你** |
| **管理 AI 身份** | 网页端 | **只有你** |
| 拿到 HA / Node-RED 令牌 | — | **只有网关**(AI 永远看不到) |
| AI 批准自己提的东西 | — | **接口层面不存在** |

---

## 九、核心版(轻量 Node-RED 操作工具)

如果你不需要完整的网关、WebUI 和安全闸,只是想让 AI 能安全地读写 Node-RED,可以用**核心版**。

### 什么是核心版

核心版是一个零依赖的 Python 库(`nr_client.py`)+ Skill 文档,封装了 Node-RED 的认证、flow 读写、节点操作等能力。AI agent 通过 Skill 调用它,可以:

- 查询 Node-RED 中的 flow、tab、节点
- 创建、更新、删除 flow
- 触发 inject 节点、读取 debug 输出
- 批量操作节点

**与完整版的区别:**

| | 完整版(网关) | 核心版(轻量工具) |
|---|---|---|
| 部署方式 | Docker 容器 | 单个 Python 文件 |
| WebUI | ✅ 有 | ❌ 无 |
| 安全闸 | ✅ 有 | ❌ 无(AI 直接操作 NR) |
| MCP 服务器 | ✅ 有 | ❌ 无(通过 Skill 调用) |
| 凭证管理 | 网关独占 | 环境变量配置 |
| 适合场景 | 日常使用、多 AI 管理 | 高级用户、特定任务自动化 |

### 给 AI Agent 的安装提示词

把下面这段话发给你的 AI agent(Claude、DeepSeek、Cursor 等),它会自动完成核心版的安装和配置:

```
请安装 AutoFlow 核心版到当前目录,步骤如下:

1. 创建目录并下载核心文件:
   mkdir -p autoflow_core && cd autoflow_core
   curl -fsSL https://raw.githubusercontent.com/lidicn/AutoFlow/main/core/skill/scripts/nr_client.py -o nr_client.py
   curl -fsSL https://raw.githubusercontent.com/lidicn/AutoFlow/main/core/skill/SKILL.md -o SKILL.md

2. 配置环境变量(在 .env 或 shell 中设置):
   NR_URL=http://<你的Node-RED地址>:1880
   NR_USER=<Node-RED用户名>
   NR_PASS=<Node-RED密码>

3. 阅读 SKILL.md 了解可用的工具和调用方式。

4. 先运行 dry-run 模式验证连接,确认无误后再执行写操作。
```

### 核心版使用示例

```python
from nr_client import NodeREDClient

client = NodeREDClient()

# 列出所有 flow
flows = client.list_flows()
for f in flows:
    print(f["id"], f.get("label", ""))

# 获取单个 flow
flow = client.get_flow("flow_id_here")

# 触发 inject 节点
client.trigger_inject("node_id_here")
```

> ⚠️ 核心版没有安全闸,AI 可以直接操作 Node-RED。建议在测试环境使用,或配合 `--dry-run` 模式先预览变更。

---

## 十、给开发者

- **架构与设计**:[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
- **本地开发 / 容器部署**:[DEPLOY.md](DEPLOY.md)
- **白盒验证循环**:[WHITEBOX_VERIFY_LOOP.md](WHITEBOX_VERIFY_LOOP.md)

一句话概括技术形态:一个 Python 网关,独占 HA/Node-RED 凭证,对外暴露
MCP(Streamable HTTP)+ 网页控制面。AI 侧只写语义 DSL,网关负责编译、静态校验、
虚拟孪生重放自证、人工确认闸、部署与快照。AI 可随时更换,凭证不动。

## 许可

[MIT](LICENSE)