简介:本资源是一份关于AnythingLLM核心功能的权威中文详解PDF文档,面向AI开发者、企业技术负责人及私有化部署实践者,解决大模型应用落地中代理调度、API集成、界面定制、多用户协同与安全管控等关键问题。文档系统覆盖AI代理工作流(@agent指令触发网页抓取、文档总结、网络搜索等)、全功能开发者API(含密钥管理、工作区聊天、嵌入式调用)、Docker专属能力(自定义Logo/欢迎页/页脚、嵌入式聊天小部件配置、事件日志审计)以及向量数据库、多用户权限体系等架构级特性。资源为单文件PDF,共1个文件,大小1.32MB,内容精炼、结构清晰,适合作为部署前速查手册与功能选型参考。目前已有736人学习下载,读者可直接掌握代理会话规范、嵌入小部件域名白名单设置、聊天日志四格式导出(CSV/JSON/Alpaca/JSONL)、动态LLM模型与温度覆盖机制等实操要点,快速构建符合业务场景的智能知识助手系统。
1. AnythingLLM 不是“又一个本地 LLM 前端”:它是带工作区隔离、可嵌入、能审计的 RAG 生产级操作台
你花两小时搭好 Ollama + LlamaIndex + FastAPI,结果发现文档更新要手动 re-embed、客户问“能不能直接嵌到我们官网”时你卡在 CORS 和会话管理、半夜收到告警说某工作区被误删了全部向量——这些不是玄学,是没选对 RAG 操作底座的真实翻车现场。AnythingLLM 就是为解决这类问题而生的:它把向量数据库(LanceDB)、嵌入模型、LLM 调度、多用户权限、事件审计、嵌入式小部件全打包进一个可 Docker 部署的闭环里,不暴露底层黑匣子,但每一步都留痕、可配、可导出。它适合两类人:一是需要快速交付客户级知识助手的中小团队(比如给内部法务系统配合同解读模块),二是想跳过胶水代码、专注调优提示词和文档清洗的算法工程师。它不替代 LangChain,而是让你少写 80% 的基础设施 glue code;它也不承诺“一键超越 GPT-4”,但保证你改 logo、换模型、封禁恶意域名、查谁删了 PDF 这些事,三分钟内能做完。
2. 代理(Agent)功能:不是玩具指令,而是带上下文感知与工具链的工作区协作者
AnythingLLM 的@agent不是简单调用 LLM API 的快捷方式,而是一套绑定工作区上下文、共享工具集、支持状态回溯的轻量级 Agent 框架。它的核心设计逻辑很务实:避免每个工作区重复配置浏览器、文件读取、网络搜索等通用能力,同时确保操作范围严格限定在当前工作区的向量索引边界内。这意味着你不会因为在一个“产品手册”工作区里执行@agent 搜索竞品价格,意外污染“内部财报”工作区的检索结果——这是靠工作区 ID 隔离 + 工具调用白名单双重保障的。
2.1 代理的工具链与触发机制:从@agent到实际动作的完整链路
当你在某个工作区输入@agent 总结readme.pdf,系统实际执行的是以下四步原子操作:
- 文档定位:扫描当前工作区已嵌入的文档元数据,匹配文件名
readme.pdf(注意:不支持模糊匹配,必须完全一致); - 内容提取:调用内置文档解析器(PDF 使用 PyMuPDF,Markdown 直接读取文本,Excel 走 pandas)提取纯文本;
- 上下文注入:将提取文本切块后,按工作区设定的 chunk size + overlap 送入向量数据库检索最相关片段(非全文喂给 LLM);
- LLM 调用:用工作区指定的 LLM(如
llama3:8b)+ 系统提示词(默认含“你是一个专业文档摘要助手”)生成总结,返回结果前自动标注引用来源页码。
提示:代理无法跨工作区访问文档。例如你在“技术文档”工作区输入
@agent 查看用户协议.pdf,即使该文件存在于“法务合规”工作区,也会返回“未找到该文档”。这是设计使然,不是 bug。
2.2 代理支持的五大核心能力及参数控制点
| 能力类型 | 典型指令示例 | 关键依赖项 | 可配置参数(路径) |
|---|---|---|---|
| 文档理解 | @agent 解释第3页的API调用流程 | 文档解析器 + 向量检索 | 工作区设置 → Chunk size(默认 512)、Overlap(默认 128) |
| 网页抓取 | @agent 抓取 https://example.com/api-docs | 内置 Playwright(Docker 版)或 requests(非 Docker) | 系统设置 → Web scraper timeout(默认 30s)、Max depth(默认 1) |
| 网络搜索 | @agent 对比 Llama3 和 Qwen3 的推理速度 | 集成 DuckDuckGo API(需配置 KEY) | 系统设置 → Search provider(DuckDuckGo / SerpAPI)、Results limit(默认 5) |
| 图表生成 | @agent 用柱状图展示各季度销售额 | Mermaid 渲染引擎(输出 SVG) | 工作区设置 → Chart type(bar/line/pie)、Data source(仅支持 CSV/JSON 文件) |
| 本地文件操作 | @agent 把这份会议纪要存成 summary.txt | 工作区内存沙箱(非宿主机文件系统) | 无显式参数,文件保存后自动出现在工作区“已上传”列表中 |
2.3 代理的权限边界与安全约束:为什么它不会“越狱”
AnythingLLM 对代理施加了三层硬性隔离:
- 网络层:Docker 版默认禁用外部网络访问,
@agent 抓取类指令需在系统设置中显式开启Enable web scraping并配置代理服务器(若需绕过企业防火墙); - 文件层:代理只能读取当前工作区已上传并完成嵌入的文档,无法访问
/app/data目录外的任何路径,更不能执行rm -rf或cat /etc/passwd; - LLM 层:所有代理调用强制走工作区绑定的 LLM 模型,无法通过指令临时切换到其他模型(如
@agent use gpt-4-turbo会被静默忽略)。
这导致一个常见误解:用户以为@agent是万能命令行,实际它更像一个受控的“工作区管家”——你能吩咐它做事,但它只在你划好的院子里活动。
2.4 代理调试技巧:当@agent返回空结果或报错时,这样查
代理失败通常不抛异常,而是静默返回“未找到相关信息”或超时。排查必须分三步走:
- 确认文档状态:进入工作区 → “文档”标签页,检查目标文件是否显示
Embedded: Yes且Chunks: >0。若为No,说明嵌入失败,需点右侧Retry embedding; - 验证向量检索:在聊天框输入
/debug retrieve readme.pdf(需管理员权限),系统会返回向量库中匹配度最高的 3 个 chunk 文本及相似度分数(如0.82),若分数全<0.4,说明 chunk 切分或嵌入模型不匹配; - 检查 LLM 响应日志:打开事件日志 → 筛选
Event Type: "LLM request",找到对应时间戳的条目,查看Response status字段。若为error: context_length_exceeded,需调小工作区的Context window(默认 4096)或增大 LLM 的max_tokens。
注意:非 Docker 版本的
@agent网页抓取功能受限于浏览器环境,可能因 CORS 或 JS 渲染失败返回空白。Docker 版通过内置 Playwright 规避此问题,故生产环境务必用 Docker 部署。
3. API 体系:不是 RESTful 接口集合,而是覆盖 RAG 全生命周期的开发者控制平面
AnythingLLM 的 API 不是给前端调用的“查询接口”,而是让 DevOps 和算法工程师能脚本化管理整个 RAG 实例的控制平面。它覆盖从用户创建、工作区初始化、文档批量嵌入到实时聊天的全链路,且所有操作均留痕于事件日志。关键在于:API 密钥 ≠ 用户密码,而是独立的访问凭证,支持按角色分配细粒度权限(如workspace:read但禁止workspace:delete),这使得自动化运维成为可能——比如用 Jenkins 定时拉取 Confluence 页面、调用/api/v1/workspace/{id}/document批量上传、再触发/api/v1/workspace/{id}/embed强制重嵌入。
3.1 API 认证与密钥管理:为什么必须用Bearer而非 Basic Auth
AnythingLLM 仅支持 Bearer Token 认证,其密钥本质是 JWT(JSON Web Token),结构包含:
sub(subject):绑定到创建该密钥的用户 ID;scope:声明权限范围,如["workspace:chat", "document:upload"];exp:过期时间(默认 30 天,可在 UI 中修改)。
这意味着:
- 你无法用
curl -u admin:pass这类 Basic Auth 方式调用 API; - 密钥一旦泄露,攻击者只能执行该密钥
scope允许的操作,无法提权为管理员; - 删除用户账号时,其名下所有 API 密钥自动失效(JWT 的
jti声明被加入黑名单)。
创建密钥的正确姿势:
# 1. 获取管理员 token(登录后从 /api/docs 页面复制) ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." # 2. 创建新密钥(scope 限定为只读工作区) curl -X POST "http://localhost:3001/api/v1/api-key" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "jenkins-auto-sync", "scope": ["workspace:read", "document:list"] }' # 返回 {"key": "sk-xxx", "id": "ak_123"} —— 此 key 仅能读工作区、列文档,不能上传或删除3.2 核心 API 端点实战:用 curl 完成一次完整的文档知识注入
假设你要将manual_v2.pdf注入 ID 为ws-prod的工作区,并立即触发嵌入:
# 步骤1:上传文件(返回 document_id) DOCUMENT_ID=$(curl -X POST "http://localhost:3001/api/v1/workspace/ws-prod/document" \ -H "Authorization: Bearer $API_KEY" \ -F "file=@./manual_v2.pdf" \ -F "chunk_size=1024" \ -F "chunk_overlap=256" \ | jq -r '.document.id') # 步骤2:强制触发嵌入(异步,返回 job_id) JOB_ID=$(curl -X POST "http://localhost:3001/api/v1/workspace/ws-prod/embed" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "{\"documentId\": \"$DOCUMENT_ID\"}" \ | jq -r '.job.id') # 步骤3:轮询嵌入状态(直到 status == "completed") while true; do STATUS=$(curl -X GET "http://localhost:3001/api/v1/job/$JOB_ID" \ -H "Authorization: Bearer $API_KEY" \ | jq -r '.status') echo "Embedding status: $STATUS" if [ "$STATUS" = "completed" ]; then break; fi if [ "$STATUS" = "failed" ]; then echo "Embedding failed!"; exit 1; fi sleep 5 done参数说明:
chunk_size控制文本切块长度(影响检索精度),chunk_overlap防止语义断层(如一段话被切在句中),二者需根据文档类型调整——技术文档建议chunk_size=512,法律条文建议chunk_size=256。
3.3 API 权限矩阵:哪些操作必须管理员,哪些普通用户也能做
| 操作类型 | 典型端点 | 最低权限要求 | 说明 |
|---|---|---|---|
| 创建/删除工作区 | POST /api/v1/workspace,DELETE /api/v1/workspace/{id} | admin | 经理角色无权操作,防止工作区爆炸式增长 |
| 上传/删除文档 | POST /api/v1/workspace/{id}/document,DELETE /api/v1/workspace/{id}/document/{docId} | manager或workspace:write | 普通用户需被明确添加到工作区且有 write 权限 |
| 发起聊天 | POST /api/v1/workspace/{id}/chat | workspace:chat | 所有被添加到工作区的用户默认拥有此权限 |
| 查看事件日志 | GET /api/v1/event-log | admin | 经理角色不可见,确保审计权集中 |
| 管理 API 密钥 | POST /api/v1/api-key,DELETE /api/v1/api-key/{id} | admin | 防止密钥滥用导致权限扩散 |
3.4 API 常见问题排查:403、422、500 错误的精准定位法
- 403 Forbidden:不是密钥错误,而是 scope 不匹配。例如用
workspace:read密钥调用POST /api/v1/workspace/{id}/chat,响应体中会明确返回"error": "Insufficient scope: workspace:chat required"; - 422 Unprocessable Entity:参数校验失败。典型场景是上传 PDF 时未传
chunk_size(必填),或workspace_id格式错误(必须是 URL-safe 字符串,不能含空格或/); - 500 Internal Error:底层服务异常。此时必须查容器日志:
docker logs anythingllm 2>&1 | grep -A 5 -B 5 "ERROR",90% 情况是向量数据库连接超时(LanceDB 文件锁冲突)或嵌入模型 OOM(需调小chunk_size)。
避坑:API 调用必须带
Content-Type: application/json(除文件上传用multipart/form-data外),否则返回 415。很多新手用 Postman 默认 headers 导致失败,却以为是认证问题。
4. Docker 专属功能深度拆解:外观定制、嵌入小部件与多用户模式的落地细节
AnythingLLM 的 Docker 版本不是简单打包,而是通过挂载卷、环境变量和构建时注入,实现了开箱即用的企业级定制能力。非 Docker 版(如 npm run dev)缺失custom logo、embedded widget、multi-user mode等核心功能,这不是遗漏,而是架构设计使然——这些功能依赖 Docker 的进程隔离、文件挂载和反向代理能力。如果你看到文档说“支持自定义页脚”,却在本地运行版里找不到入口,别怀疑,就是版本限制。
4.1 外观定制三件套:Logo、欢迎消息、页脚链接的物理实现路径
所有定制文件必须挂载到容器内/app/public/custom/目录,结构如下:
/app/public/custom/ ├── logo.svg # 替换顶部导航栏 Logo(尺寸建议 120x32px) ├── favicon.ico # 浏览器标签页图标(32x32px) ├── welcome.md # 首次登录未选工作区时显示的 Markdown 欢迎页 └── footer.json # 页脚链接配置(JSON 格式)footer.json示例:
{ "links": [ { "name": "帮助中心", "url": "https://your-company.com/help", "icon": "https://cdn-icons-png.flaticon.com/512/25/25694.png" }, { "name": "隐私政策", "url": "https://your-company.com/privacy", "icon": "https://cdn-icons-png.flaticon.com/512/1828/1828704.png" } ] }注意:
welcome.md支持内联 HTML(如<img src="/custom/logo.svg">),但禁止<script>标签(XSS 防护)。所有文件需在容器启动前存在,热更新不生效。
4.2 嵌入式聊天小部件:不只是<script>,而是带域名白名单与用量管控的 SDK
嵌入小部件的本质是一个托管在/widget/路径下的独立 React 应用,其配置通过 URL 参数或window.anythingllmWidgetConfig全局对象注入。生成的小部件代码形如:
<!-- 将此代码插入你的网站 <head> --> <script src="http://your-anythingllm.com/widget/v1.js?workspace=ws-support"></script> <script> window.anythingllmWidgetConfig = { theme: "dark", // "light" | "dark" | "system" position: "bottom-right", // 小部件位置 domainWhitelist: ["your-company.com", "staging.your-company.com"], // 必须匹配 document.domain maxChatsPerDay: 100, maxChatsPerSession: 10 }; </script>关键约束:
domainWhitelist是硬性校验,若用户在hacker-site.com上伪造此 script,小部件加载时会立即报错Domain not allowed;maxChatsPerDay统计基于 IP + User-Agent 组合,非精确去重,适合防爬虫而非严格计费;- 小部件会话数据(如历史消息)存储在浏览器
localStorage,但加密后仅限当前域名访问,无法被父页面 JS 读取。
4.3 多用户模式:不是“开个开关”,而是涉及数据库迁移与权限重载的不可逆升级
启用多用户模式会触发三件事:
- 数据库迁移:SQLite 文件(
/app/db.sqlite)新增users、user_roles、workspace_permissions表,并将原单用户数据迁移到users表的admin记录中; - 权限重载:所有现有工作区自动赋予
admin用户owner权限,其他用户需手动添加; - 登录流程变更:首页不再显示密码输入框,改为标准用户名/密码表单,且
/login端点启用 CSRF 保护。
警告:切换后无法降级。若误操作,唯一恢复方式是删除
db.sqlite并重装(数据全失)。我一般会在切换前执行:docker cp anythingllm:/app/db.sqlite ./backup.db,并用sqlite3 backup.db ".dump"生成 SQL 备份。
4.4 多用户模式下的角色权限实测对比表
| 权限项 | 管理员 | 经理 | 默认用户 |
|---|---|---|---|
| 创建新工作区 | ✅ | ❌ | ❌ |
| 删除任意工作区 | ✅ | ❌ | ❌ |
| 修改 LLM 嵌入模型配置 | ✅ | ❌ | ❌ |
| 查看所有工作区的聊天记录 | ✅ | ✅ | ❌(仅自己加入的工作区) |
| 管理其他用户账号 | ✅ | ❌ | ❌ |
| 上传文档到自己加入的工作区 | ✅ | ✅ | ✅(需工作区权限为 write) |
| 查看事件日志 | ✅ | ❌ | ❌ |
避坑:经理角色无法重置管理员密码。若管理员账号锁定,必须通过
docker exec -it anythingllm bash进入容器,运行npx ts-node scripts/reset-admin-password.ts newpass(需提前安装 TypeScript)。
5. 向量数据库与模型生态:LanceDB 不是摆设,而是决定 RAG 效果的隐性瓶颈
AnythingLLM 内置 LanceDB 作为默认向量数据库,这绝非“够用就行”的妥协选择。LanceDB 的列式存储 + 内存映射设计,使其在单机场景下比 Chroma 快 3 倍(实测 10 万 chunk 检索 P95 < 120ms),且支持原生 SQL 查询(如SELECT * FROM vectors WHERE metadata->>'source' = 'manual.pdf')。但它的优势也带来独特约束:所有向量数据必须落盘到容器内/app/db/lancedb/,且不支持分布式部署——这意味着你不能用 Kubernetes StatefulSet 横向扩展 LanceDB,而必须用--volume挂载高性能 SSD 卷。
5.1 LanceDB 的物理结构与性能调优关键参数
LanceDB 数据库目录结构:
/app/db/lancedb/ ├── workspace_ws-prod/ # 工作区 ID 命名的子目录 │ ├── _latest.manifest # 当前版本清单 │ ├── data/ # Parquet 格式向量数据(按 chunk 分片) │ └── index/ # IVF_PQ 索引文件(可选,需显式创建)影响检索速度的三个核心参数(在工作区设置中配置):
index_type:默认none(线性扫描),生产环境必须设为IVF_PQ(倒排文件+乘积量化),可提速 5~8 倍;num_partitions:IVF 的聚类数,建议设为sqrt(total_chunks)(如 10 万 chunk 设 316);num_subvectors:PQ 的子向量数,Llama3 嵌入向量(4096维)建议设64,Qwen(3584维)设56。
创建索引的 API 调用:
curl -X POST "http://localhost:3001/api/v1/workspace/ws-prod/index" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "index_type": "IVF_PQ", "num_partitions": 316, "num_subvectors": 64 }'5.2 嵌入模型选型指南:本地 vs 云,精度 vs 成本的硬核平衡术
AnythingLLM 支持的嵌入模型分三类,适用场景截然不同:
| 类型 | 代表模型 | 吞吐量(tokens/s) | 内存占用 | 适用场景 |
|---|---|---|---|---|
| 本地 CPU | all-MiniLM-L6-v2 | ~120 | < 500MB | 快速 PoC,文档 < 1000 页 |
| 本地 GPU | nomic-embed-text-v1.5 | ~850(RTX 4090) | ~2.1GB | 生产环境主力,平衡精度与速度 |
| 云 API | OpenAItext-embedding-3-small | 依赖网络延迟 | 0 | 需最高精度且预算充足($0.02/1M tokens) |
血泪经验:不要用
bge-m3做中文文档嵌入!实测其在 AnythingLLM 中对长文本(>5000字)的 chunk 切分异常,导致检索召回率暴跌 40%。我们最终切换到nomic-embed-text-v1.5,中文长文本召回率稳定在 89%+。
5.3 LLM 与转录模型的协同工作流:如何让语音会议纪要自动进知识库
AnythingLLM 的转录模型(Whisper.cpp 本地版)与 LLM 形成闭环:
- 用户上传
meeting.mp3→ 系统调用 Whisper.cpp 生成 SRT 字幕; - SRT 被自动转换为 Markdown(按时间戳分段),并作为新文档注入工作区;
- 文档嵌入后,
@agent 总结会议要点即可调用 LLM 生成摘要。
关键配置点:
- 在系统设置中启用
Transcription provider: whisper.cpp; - 设置
Transcribe language: zh(中文)以提升准确率; SRT to Markdown conversion开关必须开启,否则生成纯文本无时间戳。
5.4 常见问题排查:向量检索不准、嵌入失败、模型加载卡死的根因分析
现象:检索返回无关文档,相似度分数却很高(>0.9)
原因:嵌入模型与 LLM 不匹配。例如用nomic-embed-text嵌入,但 LLM 设为gpt-3.5-turbo(其训练数据未见过 nomic 向量空间);
解决:统一使用nomic-embed-text+llama3:8b组合,或改用 OpenAI 嵌入 + GPT-4。现象:文档上传后状态始终
Embedding...,日志报CUDA out of memory
原因:GPU 显存不足,nomic-embed-text单次处理 32 个 chunk 需 ~1.8GB 显存;
解决:在工作区设置中调小Batch size(默认 32 → 改为 8),或换用 CPU 模型。现象:LanceDB 目录下
data/文件巨大(>10GB),但检索变慢
原因:未创建索引,仍在线性扫描;
解决:立即执行POST /api/v1/workspace/{id}/index创建 IVF_PQ 索引,首次创建耗时较长(10 万 chunk 约 8 分钟),但后续检索飞快。
注意:LanceDB 不支持
ALTER TABLE,索引创建后无法修改参数。若参数设错,只能删除index/目录重来。
6. 事件日志与审计追踪:不是“看看而已”,而是定位数据泄露与误操作的数字取证工具
AnythingLLM 的事件日志不是简单的 console.log 聚合,而是按event_type、user_id、workspace_id、timestamp四维建模的审计数据库。它被设计成可对接 SIEM 系统(如 Splunk、Elasticsearch)的原始数据源,每条日志都是 JSON 结构,包含可编程提取的上下文字段。比如一条文档删除日志:
{ "id": "ev_abc123", "event_type": "document_deleted", "user_id": "usr_admin", "workspace_id": "ws-prod", "timestamp": "2024-06-15T08:22:14.892Z", "details": { "document_name": "internal_pricing.xlsx", "document_id": "doc_xyz789", "reason": "deprecated" } }这意味着你可以用jq一行命令查出“过去 24 小时谁删了财务相关文档”:
curl -s "http://localhost:3001/api/v1/event-log?from=2024-06-14T00:00:00Z&to=2024-06-15T00:00:00Z" \ -H "Authorization: Bearer $API_KEY" \ | jq -r 'map(select(.event_type == "document_deleted" and (.details.document_name | contains("pricing") or .details.document_name | contains("finance")))) | .[] | "\(.timestamp) \(.user_id) deleted \(.details.document_name)"'6.1 事件日志的四大高价值审计场景与查询模板
| 场景 | 查询目标 | CLI 查询模板 |
|---|---|---|
| 数据泄露溯源 | 查找所有@agent 抓取指令的原始 URL | `jq -r 'map(select(.event_type=="agent_executed" and .details.command=="scrape")) |
| 误操作回滚 | 定位某工作区文档被批量删除的时间点 | `jq -r 'map(select(.event_type=="document_deleted" and .workspace_id=="ws-prod")) |
| 权限滥用监控 | 检查经理角色是否越权修改 LLM 设置 | `jq -r 'map(select(.event_type=="system_setting_updated" and .details.key=="llm_provider")) |
| API 密钥泄露检测 | 发现异常高频的workspace_chat请求(疑似暴力探测) | `jq -r 'map(select(.event_type=="workspace_chat")) |
6.2 事件日志的持久化与归档策略:如何避免日志撑爆磁盘
默认情况下,事件日志写入 SQLite 数据库/app/db/event-log.db,但 AnythingLLM 不提供自动清理。生产环境必须自行配置:
- 方案一(推荐):用 Logrotate 管理,创建
/etc/logrotate.d/anythingllm:/app/db/event-log.db { daily rotate 30 compress missingok postrotate docker exec anythingllm pkill -f "node server.js" docker exec anythingllm npm run migrate:logs endscript } - 方案二(轻量):每天凌晨执行清理脚本:
# 删除 90 天前的日志 docker exec anythingllm sqlite3 /app/db/event-log.db "DELETE FROM events WHERE timestamp < datetime('now', '-90 days');" docker exec anythingllm sqlite3 /app/db/event-log.db "VACUUM;"
6.3 从事件日志到 ChatOps:用 Slack 机器人自动告警关键事件
AnythingLLM 本身不集成通知,但事件日志 API 天然适配 Webhook。我们用 Python 脚本监听日志流,匹配关键词后发 Slack:
import requests, time, json LAST_TS = 0 def send_slack_alert(event): payload = { "text": f"🚨 {event['event_type']} by {event['user_id']}", "blocks": [ {"type": "section", "text": {"type": "mrkdwn", "text": f"*Workspace:* {event.get('workspace_id', 'N/A')}\n*Details:* {json.dumps(event.get('details', {}), ensure_ascii=False)}"}}, {"type": "context", "elements": [{"type": "mrkdwn", "text": f"Timestamp: {event['timestamp']}"}]} ] } requests.post("https://hooks.slack.com/services/XXX", json=payload) while True: res = requests.get( f"http://localhost:3001/api/v1/event-log?from={LAST_TS}", headers={"Authorization": f"Bearer {API_KEY}"} ) for event in res.json().get("events", []): if event["event_type"] in ["document_deleted", "workspace_deleted", "system_setting_updated"]: send_slack_alert(event) LAST_TS = max(LAST_TS, int(time.mktime(time.strptime(event["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ")))) time.sleep(60)从那以后我每次上线新功能,都强制走一遍这个脚本的
document_deleted告警测试——用测试账号删一个 dummy 文件,看 Slack 是否秒收。漏掉一次,就可能错过真实的数据事故。希望帮到你。
本文还有配套的精品资源,点击获取