我最近做了一个简单的 AI Agent,实现了以下的功能:
结合我的日常饮食习惯,每日上午 10 点自动发消息,推荐今天午饭吃什么;每日下午 5 点自动发消息,推荐今天晚饭吃什么
每周日晚上 10 点向我发送本周饮食周报
我可以主动告诉它我今天实际吃了什么,它帮我记录
如果你对饮食有一定讲究,比如健康减脂、营养搭配、食物多样性等,但同时又经常纠结要吃什么的时候,不妨尝试做一个 AI Agent 来帮你规划饮食,终结你的饮食选择困难症。
本文将详细描述从零到一通过 n8n 平台低代码开发饮食助手的 AI Agent,内容偏向基础和细节,希望能对适宜的读者有所帮助。
01
—
安装 n8n
n8n (https://n8n.io)是一个工作流自动化平台,在 AI Workflow 方面与 Dify(https://dify.ai)类似。n8n 的名字来源是 nodemation (node + automation)。
进入官网点击右上角进入 n8n 的 Github 项目主页,找到安装方式,推荐使用 Docker 方式安装启动:
docker volume create n8n_datadocker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
如果是在本地开发的话,需要先安装 Docker Desktop,并且在 Docker Engine 是开启状态时再执行上述命令。容器启动成功后访问 http://localhost:5678 即可打开本地 n8n 的工作台主页。
n8n 的许可协议是 Fair-Code License(公平代码许可证)或 Sustainable Use License(可持续使用许可证),对个人和小型团队自托管部署完全免费且无限制。在本地的 n8n 的登录页以邮箱注册后,接收验证码并激活,个人即可永久使用,在页面中显示为已注册的社区版。如下图所示:
02
—
新建 Agent 节点
新建一个空白工作流 workflow,添加一个 AI Agent 节点。每个 Agent 包含三部分组件:对话模型(Chat Model)、记忆(Memory)和工具(Tool)。
首先配置模型,可以选择市面上任何一种大语言模型(LLM, Large Language Model),并创建好相应的 API Key 后即可。我们以 DeepSeek 为例,在 DeepSeek 开放平台(https://platform.deepseek.com/)中创建 API Key,然后再在 n8n Agent 节点的 Chat Model 点击➕,选择 DeepSeek Chat Model,然后填入这个 API Key 即可。(注意,以 API 的方式每次调用 Agent 的 Chat Model 都会消耗 tokens,好在目前几乎所有平台都为新用户赠送一定量免费 tokens 额度,而且 tokens 本身费用也很便宜,用来做测试完全不用担心。)
n8n 里目前没有直接添加阿里千问 Qwen 模型的节点,但是没关系,只要添加一个 OpenAI Chat Model 节点即可,因为这些模型的 API 都是与 OpenAI 兼容的,设置好对应的 Base URL 和 API Key 即可。
然后配置 Memory,配置记忆后才能将对话上下文存储并让模型访问到,否则每次对话都是全新的 Session。配置记忆最简单的方式就是直接使用 n8n 内置实现的 Simple Memory,无需额外配置,当然如果想保存到本地的数据库,则可以选择其他,例如 PostgreSQL 等。
这里我们选择保存到本机 PostgreSQL 数据库,顺便看一下它保存记忆的数据是什么样的。(注意由于 n8n 是在 Docker 中启动,它不能通过 localhost 或 127.0.0.1 访问到主机,而是需要用 host.docker.internal 来访问主机,在配置 PostgreSQL 连接的时候要注意)
当 Agent 首次运行后,这个记忆数据库将会自动创建表结构,只有一张表 n8n_chat_histories,字段为 id, session_id, message,如下示例所示:
然后增加一个 Chat Trigger 节点,并连接到 AI Agent 节点,这样就可以通过对话入口访问到 Agent 便于调试。同时将该对话入口设置公开后可以在线访问,下文会提到。
点击 Chat Trigger 节点旁边的 Open Chat 按钮,即可打开聊天界面,在这里可以测试该 Agent 是否运行正常。
Tool 是 Agent 最主要的也是最灵活的部分。下一节将会详细讲述最核心的 MCP Client Tool,这里我们点击 Tool 下面的➕,先添加一个日期工具 Date & Time Tool,来让模型能够获取到当前时间,用于后续在不同时间点推荐午餐/晚餐,或者发送饮食周报,毕竟 LLM 自身是不具备获取实时信息能力的。
03
—
配置 MCP
大模型自身并不具备调用外部接口和获取外部数据的能力,需要为它配置 Tools 以增强 LLM 的扩展能力。MCP(Model Context Protocol)就是大模型与外部工具实现通信的统一协议。例如,我如果要让 LLM 访问外部数据库,那么就需要一个实现 MCP 协议的可以操作数据库的 MCP Server。这里我们以 DBHub 为例来演示如何为 Agent 配置 MCP Client。
DBHub(https://github.com/bytebase/dbhub)是一个实现了 MCP 协议的数据库 MCP Server,能够让各种 MCP Clients 拥有访问各类数据库的能力。
(摘自 DBHub Github 主页)
这里同样推荐使用 Docker 来启动 DBHub,具体命令可参见文档。启动时需要指定数据库连接地址,我这里使用的是 MySQL,那么地址应该为如下格式:
"mysql://root:password@host.docker.internal:3306/eat_what_today"启动成功后会打印如下图案:
此时我们记录下这个 MCP Server 的地址,把 0.0.0.0 改为 host.docker.internal,即 http://host.docker.internal:8080/mcp 。然后回到 workflow 中点击 Agent 节点 Tool 的➕,添加一个 MCP Client Tool,将上述地址填入 Endpoint 栏中。
然后在 Chat 中问一下 Agent 能调用哪些工具,即可得到回答。
实际上模型可调用的不止这一个 execute_sql 工具。因为 MCP Server 的规范是要具备三种能力:Resources、Tools、Prompts。但是我发现在 n8n 里这么询问只能得到 Tools 的结果,而得不到其他两类的结果。于是我在 Dify 平台也尝试配了一下 DBHub MCP 并询问同样的问题,得到的就是完整的回答。如下图所示:
可以把这段回答保存下来,用来后续喂给 Agent 让它更高概率具备调用这些工具的能力。
04
—
编写提示词
做 AI Agent 开发,有时候最重要的不是编码能力,而是编写提示词 Prompts 的能力。对于每日饮食推荐这个功能,并不需要多准确,也不需要编写算法对各种饮食进行权重排序等,而是直接用自然语言告诉它需要怎么做即可。
在 Agent 节点的 Options 里添加一个 System Message 项,填入用来描述和约束 AI 要做的事情及注意事项。比如,告诉它你是谁,你需要做什么。提示词参考如下:
你是一个 AI 饮食助手,根据用户的候选菜谱和每日饮食记录,科学地推荐今日适合吃什么?你需要遵循以下的原则和要求:1、不要推荐用户在当天已经吃过的的食物2、尽量确保食物多样性,不要和近期内已经吃过的重复3、可以适当推荐一些同类型的其他蔬菜或肉类然后组合成炒菜4、人都有懒的时候,外卖或外出就餐可以适当推荐,但推荐权重不要超过 50%5、尽量不要在晚餐推荐炒面,因为不易消化6、用户有忌口:三文鱼等生食、动物内脏。不要推荐这些
我们可以根据自己的需求,在本地数据库中建立两张表 candidate_food 和 my_dietary_record,分别存放一些自己的候选菜谱和每日饮食记录,这样让 AI 在做推荐的时候可以参考这些数据。
为了让 Agent 能有效通过 MCP 访问数据库,最好在提示词中详细的说明,尽量减少工具调用的不确定性。提示词参考如下:
你具备 MCP Client 中的所有工具,其中:1、execute_sql 工具,用来通过 SQL 查询数据库。其中 "candidate_food" 表存储了候选菜品,"my_dietary_record"表存储了用户的每日菜谱(表字段:id/food_name/lunch_or_dinner/date)。你需要从这两个表中查询相关数据然后按照上面的要求进行食物推荐。2、资源读取工具:resource__schemas - 读取数据库中的模式列表resource__tables_in_schema - 读取指定模式中的表列表resource__table_structure_in_schema - 读取指定模式中表的结构resource__indexes_in_table - 读取指定表的索引信息resource__procedures_in_schema - 读取指定模式中的存储过程列表resource__procedure_detail_in_schema - 读取指定存储过程的详细信息3、提示模板工具:prompt__generate_sql - 从自然语言描述生成SQL查询prompt__explain_db - 获取数据库表、列和结构的解释
然后就可以通过 Chat 做测试了,不出意外的话,应该就可以结合你的候选食物和历史记录为你推荐一道适合今日吃的饭菜。
但是意外出现了,你有可能会遇到下面的错误提示:
解决办法在本文最后一章节「n8n 常见问题解答」中有详细描述。解决后再次尝试即可成功执行。如下图所示:
在调试的过程中可以观察 AI 在执行时都调用了哪些节点,如果发现有些节点没有被访问到,则需要分析下原因。
05
—
配置消息推送
当你计算出适合推荐的食物后,调用 Send notice to user 工具告知用户。$fromAI(key, description, type, defaultValue)06
—
保存饮食记录
这个 DBHub MCP 的 execute_sql 工具通常只能执行查询 select,并不能执行 insert / update / delete 等修改操作。而且通常考虑到风险,也不建议直接让 Agent 通过 SQL 对数据库拥有完全访问权限。所以,对于数据变更等操作,建议单独提供接口供 AI 调用以确保流程可控。
在本文中,变更数据库的操作目前就是新增饮食记录。现在基本不需要亲自写代码了,借助主流 AI 编码工具(ChatGPT、Cursor、Claude、Gemini 等),可以在几十秒内快速生成高质量代码。我这里使用 Cursor 工具生成了一段 Python + Flask + MySQL 的简单程序,运行后即可接收 HTTP 请求用于将饮食信息存储入库。
为 Agent 添加一个名为 HTTP Request 的 Tool,可以改名为"Save the food",填入 Description、URL 和 JSON 参数等信息。
最后再告知一下 Agent 具备这个能力:
如果用户提出让你记录一下TA的饮食, 请调用 Save the food 工具存储到用户的饮食记录中。这样,当用户通过 Chat 方式向 AI 说“我今天中午吃的 xxx,帮我记录一下”,AI 就会调用该接口存储该记录。
07
—
配置定时任务
在自动化工作流平台中,通常都会配置定时任务,让任务按固定频率触发。在本案例中,我想让 AI 为我推荐午饭和晚饭,那么就可以设定提前 2 小时左右触发,分别为上午 10 点和下午 5 点。
在 n8n 中新增 Schedule Trigger 节点,配置好触发间隔,连接到 AI Agent 节点后,同时将该 Workflow 设置为 Active 后,定时任务将自动开启。当然也可以在 workflow 中手动触发执行用于测试。
对于上午 10 点和下午 5 点,可以只添加一个 Schedule 节点,创建两个规则,也可以创建两个 Schedule 节点,各设置一个规则。我这里为了看得更直观,设置了两个 Schedule。最后再添加一个节点,在周日的晚上为我发送本周饮食周报。相应的需要再添加一个 HTTP Request 工具用于通过 pushplus 发送周报。
为了让 Agent 知道不同时间点触发时做的工作不一样,需要给 Agent 配置 Prompt,例如在 User Message 中配置如下 Prompt:
如果当前时间在中午 12 点之前,则推荐午饭。如果在晚上 7 点之前,则推荐晚饭。并将推荐结果直接发通知给我,不需要我的确认。如果当前时间是周日晚上 10 点,则向我发送本周饮食周报。
在运行时,Agent 会调用到 Date & Time 工具获取当前时间,之后再根据提示词做出相应的逻辑。
08
—
线上环境部署 n8n
定时任务需要在 n8n 一直启动的状态下才可以触发。让本机 24 小时开机不太现实,因此需要将 n8n 的 workflow 在云服务器上部署才合适。这里我使用的是阿里云,在 Linux Server 上安装好 docker-ce + n8n + dbhub,并同步一下本机所需要的数据库及 Python 程序等。最后添加公网域名解析、SSL 证书、Nginx 反向代理等相关配置后,即可通过 https +公网域名访问线上 n8n 工作台主页。
如果在线上 n8n 工作流编辑时看到 “Connection Lost” 提示,那就需要进行额外的配置,具体可参见本文最后一节「n8n 常见问题解答」中的描述。
需要注意的是,在 Linux 环境下的 Docker 默认并不会解析 host.docker.internal 域名,如果想让其生效,需要手动配置一下。例如在 docker 命令或 docker-compose.yml 中增加如下配置:
// for docker run--add-host=host.docker.internal:host-gateway// for docker-compose.ymlextra_hosts:- "host.docker.internal:host-gateway"
或者不使用这个域名,而是使用该服务器主机的内网 IP 也是可以的。
将本地 workflow 点击 Download 导出为 json 文件,再在服务器 workflow 中导入该文件即可完成同步。但是需要注意的是,LLM 的 API Key 等密钥信息并不会随着 json 文件导出,需要手动再配置一遍这些 Credentials 信息。
将 Chat Trigger 节点的 Make Chat Publicly Available 打开后,即可得到一个可公开访问的 Chat URL。将 workflow 设置为 Active 后,访问该 URL 即可打开 Chat 界面。另外可以选择 Hosted Chat(直接网页访问)或 Embedded Chat(嵌入页面内的小组件)的方式使用该对话。也可以设置会话的初始消息,即 AI 向用户说的的欢迎语。
下图就是 Hosted Chat 模式下打开链接的效果:
可以在手机浏览器中打开这个链接,并将这个链接在桌面创建图标,实现更快捷的访问入口。
如果想用 Embedded 的方式在其他网页中嵌入 Chat,可以参考官方提供的资源来实现,链接为 https://www.npmjs.com/package/@n8n/chat,这里不做展开。
09
—
n8n 常见问题解答
在做这个 Agent 的过程中,我也踩了不少坑,这里整理出一些 Q&A,便于大家查阅。
1、如果不小心把 Workflow 给 Archive 了,怎么恢复?
国外的产品(例如 ChatGPT)通常有一个 Archive(归档)操作,跟删除操作不同,删除前通常有确认,而归档操作没有确认直接将该条记录消失。实际上并没有删除,只是被隐藏了,需要在 workflow 列表页,右侧点击 Filter 按钮,勾选 Show archived workflows 即可看到被归档的记录。然后将该记录设为 Unarchive 即可恢复正常。
2、Agent 在执行时经常报错:Cannot read properties of undefined (reading 'nodeName')
Google 了一下这个问题,原因不明。但有人说把 Agent 节点的版本降低到 2.2 后正常,目前默认版本为 3。经测试,确实可行。具体步骤为,将该 workflow 进行 Download 导出为 json 文件,用编辑器打开该 json 文件,修改其中 AI Agent 节点的 typeVersion 为 2.2 后保存,然后再回到 n8n 中新建 workflow,选择 Import from URL 上传这个 json 文件即可。
(参考链接:https://github.com/n8n-io/n8n/issues/21518)
3、Date & Time 工具获得的当前时间不是北京时间
需要修改时区。在 Workflow settings 中,将 Timezone 设置为 Asia/Shanghai 即可。
4、HTTP Request 工具中当 JSON 参数内容包含 $fromAI 等动态表达式时,可能会出现 JSON 解析错误
例如,在发送饮食周报的 HTTP 接口中的参数,在 JSON Body String 中的双引号内插入动态表达式 $fromAI ,如果该表达式最终解析的内容包含双引号等特殊字符,就会导致 JSON 语法解析错误,请求将会失败。此时可以改变设置参数的方式,将 Specify Body 从 Using JSON 改成 Using Fields Below,然后在下方依次分别填写每个参数的 key 和 value。
这样做的好处是可以让 n8n 为每个参数值自动进行 URLEncode,使得最终 JSON 请求体变为安全文本。但是它的缺点就是只支持一层结构的 JSON,不支持二级以上的嵌套 JSON 格式。
(参考链接:https://community.n8n.io/t/invalid-json-format/214326)
5、线上部署的 n8n Chat 入口的 Public URL 中出现了 5678 端口,而不是走默认的 443 或 80,导致无法正常使用 Chat 页面
需要在启动 n8n 时指定一个环境变量 N8N_EDITOR_BASE_URL,用来设置 n8n Chat 入口的 URL 前缀。如果不指定,则会在 URL 中默认拼接本地端口 5678。在 docker-compose.yml 中添加以下内容:
environment:- N8N_EDITOR_BASE_URL=https://your.n8n.public.domain
6、线上部署 n8n 后,在工作流编辑页面出现 Connection Lost 提示
这个问题的原因是 n8n 工作台前端页面会通过 WebSocket 协议保持与服务端的连接,在线上部署时需要在 Nginx 反向代理配置一下 WebSocket 相关的 headers。具体配置可参考如下:
location / {proxy_pass http://127.0.0.1:5678/;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header Host your.n8n.public.domain;proxy_set_header Origin https://your.n8n.public.domain;}
(参考链接:https://community.n8n.io/t/connection-lost-you-have-a-connection-issue-or-the-server-is-down-n8n-should-reconnect-automatically-once-the-issue-is-resolved/80999/13)
(全文完)