Karakeep 高级工作流实战:规则引擎、API 与 Webhook 自动化指南
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
Karakeep(原 Hoarder)是一款可自托管的"收藏一切"应用(书签、笔记与图片),而真正让它从"存储工具"进阶为"自动化枢纽"的,是文档 docs/versioned_docs/version-v0.30.0/04-using-karakeep/advanced-workflows.md 所描述的三大进阶能力:规则引擎(Rule Engine)、API 与 Webhook。读完本文,你将掌握如何用 if-this-then-that 规则自动打标签、收藏、归档、路由书签到列表;如何用与 App 同源的 API 编写脚本与定时任务;以及如何订阅书签事件,把 Karakeep 与自己的系统(写作队列、团队聊天、通知机器人等)无缝打通,构建端到端自动化。
规则引擎:if-this-then-that 式的自动化
规则引擎是 Karakeep 内置的"条件动作"系统:当某个事件发生时,若书签满足条件,则自动执行一系列动作——自动打标签、收藏、归档,或把书签路由进列表。它的典型用途是保持收件箱整洁:自动归档新闻通讯、按域名自动打标签、标记视频类书签等。
规则由三部分构成(定义见 packages/shared/types/rules.ts):
- 事件(Event):触发规则的时机;
- 条件(Condition):书签必须满足的匹配规则(可为空,即"总是为真");
- 动作(Action):匹配成功后执行的操作,可同时配置多个。
可触发的事件
规则可以绑定以下 7 类事件(zRuleEngineRuleEventSchema,见 rules.ts):
| 事件类型 | 说明 | 附加字段 |
|---|---|---|
bookmarkAdded | 新书签被添加 | 无 |
tagAdded | 书签被添加了某个标签 | tagId |
tagRemoved | 书签被移除了某个标签 | tagId |
addedToList | 书签被加入列表 | listIds(可多个) |
removedFromList | 书签被移出列表 | listIds(可多个) |
favourited | 书签被收藏 | 无 |
archived | 书签被归档 | 无 |
可用的条件
条件既可以是单一条件,也可以是用and/or组合的嵌套表达式(zRuleEngineConditionSchema,允许递归,最大嵌套深度为 10):
| 条件类型 | 语义 |
|---|---|
alwaysTrue | 恒真(不设条件) |
urlContains/urlDoesNotContain | URL 包含 / 不包含指定子串 |
titleContains/titleDoesNotContain | 标题包含 / 不包含指定子串 |
importedFromFeed | 书签来自指定 RSS 订阅源(feedId) |
bookmarkTypeIs | 书签类型为link/text/asset |
bookmarkSourceIs | 书签来源为指定渠道(如 API、CLI、浏览器扩展等) |
hasTag | 书签带有指定标签(tagId) |
isFavourited | 书签已被收藏 |
isArchived | 书签已被归档 |
and/or | 条件组合,可嵌套,深度上限 10 |
条件在真实书签数据上的求值逻辑见 packages/trpc/lib/ruleEngine.ts 的doesBookmarkMatchConditions:例如urlContains实际执行link.url.includes(str),titleContains会同时匹配书签自身标题与 link 抓取到的页面标题,importedFromFeed通过书签关联的rssFeeds判断,hasTag则检查tagsOnBookmarks关联表。
可执行的动作
| 动作类型 | 效果 |
|---|---|
addTag/removeTag | 为书签添加 / 移除指定标签(tagId) |
addToList/removeFromList | 把书签加入 / 移出指定列表(listId) |
downloadFullPageArchive | 触发低优先级爬虫队列,为书签生成整页归档(archiveFullPage) |
favouriteBookmark | 将书签标记为收藏 |
archiveBookmark | 将书签标记为归档 |
动作的实际执行在executeAction中完成(ruleEngine.ts):addTag通过onConflictDoNothing幂等插入tagsOnBookmarks;downloadFullPageArchive会把任务投入LowPriorityCrawlerQueue,并设置groupId、低优先级与基于载荷的幂等键buildCrawlIdempotencyKey,保证同一请求不会重复入队。
规则的校验与生命周期
一条规则包含id、name(非空)、description、enabled、event、condition与actions(至少一个)。创建和更新时会经过superRefine校验(rules.ts):事件与条件、动作引用的标签 / 列表必须存在(由 routers/rules.ts 的ensureTagListOwnership中间件在创建 / 更新时逐一校验所有权),条件嵌套深度超过 10 会被拒绝,and/or至少需要一个子条件。规则的增删改查(create/update/delete/list)均通过 tRPC 暴露,并带有规则所有权检查(ensureRuleOwnership)。
规则引擎的底层运行机制
从源码结构看,规则求值并不在请求链路内同步完成,而是异步队列化处理:
- 书签发生变更(创建、打标签、加列表、收藏、归档等)时,业务代码调用
RuleEngine.triggerOnEvent(ruleEngine.ts); - 该方法先通过
matchesAnyRule快速判断该用户是否存在"事件匹配"的已启用规则,仅当匹配时才把{ bookmarkId, events }投入RuleEngineQueue,避免无谓的队列开销; - apps/workers/workers/ruleEngineWorker.ts 中的
RuleEngineWorker以serverConfig.ruleEngine.numWorkers并发度消费队列,为书签构建RuleEngine.forBookmark,对每个事件调用onEvent求值并执行动作,结果会以结构化日志输出(含matched_count等指标)。
事件匹配的判定在doesEventMatchRule(ruleEngine.ts):对于addedToList/removedFromList采用"规则声明列表是否包含该列表"的包含式匹配,其余事件则做严格深度相等比较。worker 的并发数、轮询间隔(1000ms)与超时(10s)均由serverConfig.ruleEngine控制。
实战配置示例:自动整理收件箱
以下三个规则覆盖文档提到的典型场景(在 Dashboard 的设置界面创建):
规则一:自动归档新闻通讯
- 事件:
bookmarkAdded - 条件:
urlContains,值为substack.com(可再加一个or分支mailchi.mp) - 动作:
archiveBookmark+addTag(标签如newsletter)
规则二:按域名自动打标签
- 事件:
bookmarkAdded - 条件:
urlContains,值为youtube.com - 动作:
addTag(video)+addToList(Watch later列表)
规则三:高价值内容自动收藏并整页归档
- 事件:
bookmarkAdded - 条件:
and→ [titleContains(如tutorial),bookmarkTypeIs(link)] - 动作:
favouriteBookmark+downloadFullPageArchive
API:与 App 同源的脚本化能力
Karakeep 的 API 面与前端 App 使用的是同一套 tRPC 路由,因此脚本、cron 任务或其他服务可以用与 App 完全相同的能力读写数据。API 的正式契约以 OpenAPI 规范维护在 packages/open-api/karakeep-openapi-spec.json,每个端点均有对应的.api.mdx文档(见 docs/docs/api,例如 create-bookmark.api.mdx、search-bookmarks.api.mdx)。
认证方式
API 支持两种认证(实现见 packages/api/middlewares/apiKeyScopes.ts 与 packages/api/middlewares/auth.ts):
- API Key:用于脚本与服务集成,可附加作用域(scope)限制,避免使用主账号密码;
- 用户 Cookie / Session:浏览器端 App 的认证方式。
API Key 的 scope 由 tRPC 路由的createScopedAuthedProcedure("bookmarks")等调用点声明(如rules、webhooks、bookmarks、lists、tags等),这意味着你可以按最小权限原则为不同脚本签发不同的 Key。
典型用法
- 脚本化导入 / 同步:调用书签创建、更新、删除端点,实现批量导入或与外部系统双向同步;
- 自定义工具:用 API 查询书签、标签、列表,构建自己的统计看板或检索工具;
- 与 cron 搭配:编写定时任务定期调用 API 检查、清理或归档书签;
- 与 CLI 结合:仓库还提供官方 CLI(apps/cli),适合在终端或脚本中直接操作。
搜索端点支持完整的查询语言(解析实现见 packages/shared/searchQueryParser.ts),可组合标签、列表、收藏状态、类型等过滤条件,也支持语义(向量)搜索。对结果的混合排序逻辑见 packages/trpc/lib/searchRanking.ts 的reciprocalRankFusion。
Webhook:订阅书签事件并触发你的系统
Webhook 允许你订阅书签事件,当书签被添加、更新、抓取、AI 打标或被删除时,Karakeep 会向你的端点发送 HTTP POST 请求。与 API 配合即可构建端到端自动化——例如把新保存的内容推送进写作队列或团队聊天。
可订阅的事件
事件类型定义在 packages/shared/types/webhooks.ts 的zWebhookEventSchema:
| 事件 | 触发时机 |
|---|---|
created | 书签被创建 |
edited | 书签被编辑 |
crawled | 书签内容被抓取完成 |
ai tagged | AI 自动打标完成 |
deleted | 书签被删除 |
创建 Webhook 的约束
由zNewWebhookSchema(webhooks.ts)可见:
url:必须是合法 URL,长度上限 500 字符;events:至少订阅一个事件;token:可选,长度上限 100 字符,用于鉴权;配置后,Karakeep 会在请求头携带Authorization: Bearer <token>,你可以据此验证请求确实来自你的 Karakeep 实例。
Webhook 的增删改查由 packages/trpc/routers/webhooks.ts 暴露,token 不会在响应中回传(仅返回hasToken布尔值,见toPublicWebhook)。
投递机制与重试语义
Webhook 的投递由 apps/workers/workers/webhookWorker.ts 异步执行:
- 事件发生时,
WebhooksService(packages/trpc/models/webhooks.service.ts)把{ bookmarkId, operation }投入WebhookQueue; - worker 取出任务后,查出该用户的所有 webhook,过滤出订阅了该事件的端点;
- 对每个匹配端点并发发送
POST请求,正文为 JSON,包含jobId、bookmarkId、userId、url(书签链接)、type(书签类型)与operation(事件名);若配置了 token 则附加 Bearer 头; - 请求使用
AbortSignal.timeout设置超时(默认serverConfig.webhook.timeoutSec),失败会按retryTimes自动重试,每次重试间隔由队列控制,整体超时预算为timeoutSec × (retryTimes + 1) + 1秒; - 所有端点投递完成后,日志记录
matching_count、delivered_count与failed_count指标。
一个值得注意的细节:deleted事件的书签已被删除,worker 允许在书签不存在时仍投递该事件(canDeliverWebhookWithoutBookmark),因此你可以放心用deleted事件做下游清理。
实战示例:把新保存推送到团队聊天
假设你要在每次新书签保存时通知团队聊天:
- 在 Karakeep 设置中创建 webhook,
url填聊天机器人的接收端点,events勾选created; - 若聊天平台支持,配置
token,服务端校验Authorization: Bearer <token>; - 在接收端解析 POST 正文中的
url与type,拼成消息发送。
再进一步:在接收端把收到的bookmarkId通过 get-bookmark.api.mdx 拉取完整内容(标签、摘要、正文)写入自己的写作队列——这就是文档所说的"用 API 构建端到端自动化"的典型形态。
把三者组合成完整的自动化管线
规则引擎、API 与 Webhook 是互补的三层能力:
- 规则引擎负责"内部自动化":事件发生后在 Karakeep 内部完成打标签、归档、路由、整页归档等动作,且无需任何外部系统参与;
- Webhook负责"对外广播":把创建、编辑、抓取、AI 打标、删除等事件推送给你自己的系统;
- API负责"反向操作":你的系统收到事件后,可以用 API 查询书签详情、批量修改、或把数据同步回 Karakeep,形成闭环。
例如一个完整的"文章收集 → 整理 → 推送"管线可以是:RSS 订阅的文章保存进 Karakeep(bookmarkAdded)→ 规则引擎按域名自动打标签、归档并整页归档 → Webhook 把created事件推送到写作队列 → 写作队列用 API 拉取书签详情与正文,进入草稿流程。
补充说明与运维提示
- 规则引擎与 Webhook 都依赖队列 worker:规则由
ruleEngineWorker处理,webhook 由webhookWorker处理,两者在 Docker 部署中均随 worker 容器启动(参见 docker-compose.yml 与 charts/README.md); - 相关配置项(并发数、超时、重试次数)集中在 packages/shared/config.ts 的
serverConfig.ruleEngine与serverConfig.webhook中,可在部署时通过环境变量调整; - API 端点的完整请求 / 响应示例请查阅 docs/docs/api 下的各
.api.mdx文档,OpenAPI 规范见 packages/open-api/karakeep-openapi-spec.json; - 规则引擎与 webhook 路由的单元测试分别在 packages/trpc/routers/rules.test.ts 与 packages/trpc/routers/webhooks.test.ts,可作为理解行为边界的参考。
以上能力与本文提到的全部源码、配置和 API 文档均位于本仓库内,你可以按需深入阅读对应文件,把 Karakeep 从"收藏箱"改造成真正属于你的自动化数据管道。
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考