Agent智能体客服:基于Dify0-1搭建部署实战复盘 - AI知识库
Agent智能体客服:基于Dify0-1搭建部署实战复盘
先说结果
我给 codex.chatgpt-plus.top 上线了一个 Dify 智能体客服。

最终效果是:
•
网站右下角出现 Dify 悬浮客服入口
•
用户可以直接问注册、充值、API Key、调用报错、余额、节点状态等问题
•
客服接入的是 Dify Chatflow
•
网站后端不需要改源码
•
Caddy 负责把 HTML 页面请求转给一个本地注入服务
•
API 和静态资源仍然走原来的后端,不影响业务请求
整个过程里,Codex 做了几件事:
•
分析现有网站架构
•
设计 Dify Chatflow 客服方案
•
生成知识库和 Prompt
•
SSH 登录服务器
•
备份 Caddy 和站点相关文件
•
写了一个本地 HTML 注入代理
•
修改 Caddy 路由
•
排查 Dify token、CSP、systemd、Python 兼容问题
•
最后完成验证和回滚方案
一句话总结:
🌐
•
不是“让 AI 给你建议”,而是让 Codex 直接参与上线。
为什么不用直接改前端源码?
🌐
因为这个网站不是一个普通静态站。
上线前先查了一下,发现 Caddy 配置不是 root /var/www/html 这种静态目录,而是:
代码块
PowerShell
reverse_proxy localhost:8080
也就是说,网站本体跑在 Docker 容器里,Caddy 只是反向代理。
进一步检查后发现:
•
Caddy 在服务器上运行
•
后端服务是 Docker 容器
•
容器镜像是类似 backend-app 的应用
•
前端 HTML 是应用动态返回的
•
容器里没有常规的 dist/index.html 可以直接改
所以如果硬改容器内部文件,会有两个问题:
容器重启或升级后改动可能丢失
不知道镜像构建链路,盲改风险很高
最后选了一个更稳的方案:
在 Caddy 和后端之间加一个本地 HTML 注入代理。
只有浏览器访问页面 HTML 时,才经过注入代理;API、静态资源、健康检查继续直连后端。
整体架构
上线后的结构大概是这样:

🌐
核心点是:
•
GET / 这种页面请求走注入服务
•
/../assets/* 静态资源不走注入
•
/api/*、/v1/* 业务接口不走注入
•
注入服务只改 HTML,不碰业务接口
•
这比“全站代理重写所有响应”安全得多。
第一步:先搭 Dify Chatflow
客服不是随便丢一个大 Prompt 就完事。
🌐
一个网站客服至少要处理这些问题:
•
注册登录
•
充值不到账
•
API Key 怎么创建
•
API 调用报错
•
余额和账单
•
服务状态
•
备用节点
•
退款、风控、封号、投诉转人工
我最开始给 Dify 设计的是一个更完整的 Chatflow:
但实际上,第一版为了快速上线,先用了最小可用流程:
代码块
PowerShell
开始 -> 知识检索 -> LLM -> 直接回复
这已经能覆盖很多基础问答。
后续再加分类器、变量、转人工节点,会更完整。
第二步:准备知识库
客服的质量很大程度取决于知识库。
🌐
我为这个客服准备了一份 knowledge-base.md,内容包括:
•
平台基本信息
•
文档入口
•
服务状态页
•
API Base URL
•
备用节点
•
创建 API Key 的步骤
•
常见 API 报错排查
•
充值不到账处理方式
最重要的是安全边界:
客服不能索要用户密码、API Key 原文、Cookie、完整支付凭证、身份证件、私钥。
这点一定要写进 Prompt 和知识库里。
第三步:设计客服 Prompt
核心系统提示词大概是这个方向:
代码块
PowerShell
你是 示例 API 平台 网站客服。
你的职责:
这类客服 Prompt 的重点不是“会说话”,而是:
知道什么能答,什么不能答。
特别是涉及支付、退款、风控、封号时,AI 不能乱承诺。
第四步:拿 Dify 嵌入代码
Dify 发布后,会给一段类似这样的代码:
代码块
XML
<script
src="https://udify.app/embed.min.js"
id="YOUR_WEBAPP_TOKEN"
defer>
这里有一个很容易踩的坑:
Dify 的嵌入 token 不一定是 。
我一开始就踩了。
最开始复制了一个 形式的值,结果网站报:
代码块
PowerShell
App with code not found
这说明:
•
token 不是 WebApp 嵌入 token
•
或者 token 和 baseUrl 不属于同一个 Dify 环境
•
或者 App 没发布
后来换成 Dify 官方“嵌入网站”里给的短 token,问题才解决。
所以这里一定要记住:
复制 Dify 发布面板里的完整嵌入代码,不要自己猜 token。
第五步:服务器部署前先备份
这是 Codex 做上线时最重要的一步。
在改服务器之前,先备份:
代码块
Bash
mkdir -p /srv/backups/customer-service/$(date +%Y%m%d-%H%M%S)
cp -a /etc/caddy/Caddyfile.example /srv/backups/customer-service/.../Caddyfile.example.bak
cp -a /srv/backend-app/deploy/docker-compose.yml.example /srv/backups/customer-service/.../docker-compose.yml.example.bak
cp -a /srv/backend-app/deploy/data/app-config.yaml /srv/backups/customer-service/.../app-config.yaml.bak
另外还打包了数据目录,但排除了日志:
代码块
PowerShell
tar --exclude='data/logs' -czf backend-data-no-logs.tgz -C /srv/backend-app/deploy data
为什么这么谨慎?
因为这次改的是线上入口层,一旦 Caddy 配错,网站首页就可能 502。
上线不是炫技,先给自己留退路。
第六步:写一个本地 HTML 注入服务
核心逻辑是:
本地监听 127.0.0.1:18080
收到 HTML 页面请求
去请求原来的 localhost:8080
如果响应是 text/html,就在
前插入 Dify 脚本
顺便补充 CSP,允许 https://udify.app
返回给浏览器
这个服务用 Python 写,部署在:
代码块
PowerShell
/srv/customer-service/html_inject_proxy.py
配置放在:
代码块
PowerShell
/srv/customer-service/customer-service.env
里面只保存 Dify WebApp token 和基础地址:
代码块
PowerShell
然后用 systemd 托管:
代码块
PowerShell
/etc/systemd/system/codex-customer-service-injector.service
启动:
代码块
PowerShell
systemctl daemon-reload
验证:
代码块
PowerShell
systemctl is-active codex-customer-service-injector.service
curl -sS -H 'Accept: text/html' http://127.0.0.1:18080/ | grep embed.min.js
第七步:改 Caddy,只让 HTML 走注入服务
Caddy 原来是:
代码块
PowerShell
reverse_proxy localhost:8080
改成:
代码块
Bash
@customer_service_html {
method GET HEAD
not path /../assets/* /api/* /v1/* /health /logo.png /favicon.ico /robots.txt /sitemap.xml
}
handle @customer_service_html {
reverse_proxy localhost:18080
}
handle {
reverse_proxy localhost:8080
}
这里非常关键。
不能让所有请求都走注入服务,否则 API 流式响应、模型调用、静态资源都有可能被误处理。
🌐
所以要把这些路径排除:
•
/../assets/*
•
/api/*
•
/v1/*
•
/health
•
/logo.png
•
/favicon.ico
改完后必须验证:
代码块
PowerShell
caddy validate --config /etc/caddy/Caddyfile.example
systemctl reload caddy
然后测试:
代码块
PowerShell
curl -k -sS https://codex.chatgpt-plus.top/ | grep embed.min.js
curl -k -sS -o /dev/null -w "%{http_code}" https://codex.chatgpt-plus.top/../assets/index-xxx.js
最终验证结果:
代码块
PowerShell
caddy_active=active
injector_active=active
public_status=200
public_has_new_token=2
public_has_embed=1
asset_status=200
这说明:
首页正常
Dify 脚本注入成功
静态资源不受影响
中间踩了哪些坑?
这部分最有价值。
坑 1:把 Dify token 搞错了
一开始用了 ,结果页面报:
代码块
PowerShell
App with code <wrong-app-code> not found
解决方式:
必须使用 Dify 发布面板给的 WebApp 嵌入 token。
不要用 API Key,不要用应用 ID,不要用 URL 里的 UUID。
坑 2:CSP 报 unpkg.com 被拦
页面出现过:
代码块
PowerShell
Connecting to https://unpkg.com/...wasm.map violates CSP
这个看起来吓人,但它不是主因。
这是 Dify iframe 里加载 wasm sourcemap 被它自己的 CSP 拦了,通常不影响客服功能。
真正导致不可用的是上面的:
App with code ... not found
排障时一定要分清楚主错误和噪音错误。
坑 3:Python 版本不支持 list[str]
服务器上的 Python 是 3.8,脚本里写了:
代码块
PowerShell
def add_csp_source(policy: str, directive: str, sources: list[str]) -> str:
结果服务启动失败:
代码块
PowerShell
TypeError: 'type' object is not subscriptable
解决:
代码块
PowerShell
这就是线上环境和本地开发环境不一致的典型坑。
坑 4:Caddy 路由一度回到了原始状态
中间发现线上首页没有注入,检查 Caddyfile.example 后发现还是:
代码块
PowerShell
reverse_proxy localhost:8080
也就是说注入路由没在当前配置里。
解决方式是重新插入:
代码块
PowerShell
然后重新:
代码块
PowerShell
caddy validate --config /etc/caddy/Caddyfile.example
systemctl reload caddy
坑 5:敏感配置不能随便打印
这次排查里有一次误把 app-config.yaml 的敏感字段输出到了终端,包括数据库凭据和应用签名密钥。
这件事要严肃处理。
上线后建议:
•
轮换数据库凭据
•
轮换应用签名密钥
•
轮换 root 密码
•
后续不要用 root 密码直连
•
改成专用部署用户 + SSH key + sudo
这也是使用 AI 上线时要特别注意的一点:
•
Codex 能干活,但你要给它安全边界。
最终回滚方案
任何线上改动都要有回滚命令。
这次回滚很简单:
代码块
PowerShell
cp -a /srv/backups/customer-service/xxxx/Caddyfile.example.bak /etc/caddy/Caddyfile.example
如果只是换 Dify token,不需要改 Caddy,只要:
代码块
PowerShell
sed -i 's/^DIFY_WEBAPP_TOKEN=.*/DIFY_WEBAPP_TOKEN=新的token/' /srv/customer-service/customer-service.env
systemctl restart codex-customer-service-injector.service
这次上线的关键经验
Codex 不只是写代码,它可以参与真实运维
这次它做的不只是“生成一段 HTML”。
🌐
它参与了:
•
服务器探测
•
Caddy 配置分析
•
Docker 架构判断
•
备份
•
写注入代理
•
systemd 服务
•
CSP 排查
•
线上验证
•
回滚方案
这已经接近一个小型 DevOps 协作流程。
不要一上来就改源码
很多时候,源码不在你手里,或者改源码成本很高。
这次用“Caddy + 本地注入服务”的方式,绕开了容器镜像和前端构建链路。
🌐
这类方案适合:
不方便重构前端
前端在容器镜像里
只是想快速加一个全站客服
需要可回滚
智能体客服的核心不是“智能”,而是“边界”
🌐
客服最怕什么?
不是答得不够花哨。
而是乱答:
所以一个好客服 Prompt,一定要写清楚:
代码块
PowerShell
哪些能回答
哪些不能回答
哪些必须转人工
哪些信息不能收集
每一步都要验证
上线过程中一直在做这些验证:
代码块
PowerShell
systemctl is-active caddy
systemctl is-active codex-customer-service-injector.service
不要凭感觉上线。
验证结果比“我觉得没问题”可靠。
给你一份可复用清单
如果你也想用 Codex 给网站上线智能体客服,可以照这个清单走:
Dify 侧
创建 Chatflow
配置知识库
配置 LLM Prompt
发布 WebApp
复制“嵌入网站”完整代码
确认 token 不是 API Key
服务器侧
备份 Caddyfile.example
备份站点配置
确认网站是静态目录还是反向代理
如果是静态站,直接加 embed 代码
如果是反向代理,考虑 HTML 注入代理
修改 Caddy 前先 validate
reload 后测试首页和静态资源
安全侧
不打印密钥
不把 API Key 放前端
不让 AI 索要用户敏感信息
操作后轮换高危凭据
保留回滚命令
最后
这次最大的感受是:
以前上线一个客服,可能要自己查文档、写代码、改服务器、排查 CSP、重启服务、看日志。
现在可以把 Codex 当成一个“能动手的搭档”:
你给目标,它做探测;
你给边界,它做修改;
你给权限,它做验证;
中间出错,它继续定位和修复。
真正的变化不是“AI 会聊天”。
真正的变化是:
AI 开始能把一个想法推进到线上。
而这,才是 Codex 最值得被认真使用的地方。