概览

聊天钩子

Docsbook 聊天钩子是属于您的 HTTPS 端点,AI 聊天 会在每次回答前后调用它们。您可以使用它们来强制执行合规团队制定的规则,将只有您的系统知道的事实提供给模型,或将每个问题和答案镜像到您自己的存储中——无需分叉聊天功能。

您将获得#

三个钩子,每个都有自己的 URL,且可独立设置:

钩子 运行时机 能否更改答案? 用途
前置钩子 模型调用前,以阻塞方式运行 可以 — 阻止请求,或将上下文注入提示词 拒绝问题;添加读者的套餐、地区或功能标志
后置钩子 答案完成后 不可以 将问题/答案对记录到您自己的存储中
流式钩子 与后置钩子同时运行 不可以 为实时仪表板或告警渠道提供数据

只有前置钩子会更改任何内容,因为它是 Docsbook 唯一会等待的钩子。其他两个钩子会在读者已经获得答案后才被调度,并且系统永远不会读取它们的响应 — 它们无法对已显示的内容进行删减、重写或重新格式化。

所有套餐均可使用钩子,调用钩子不会消耗您的余额。URL 必须是 https://;保存时,http:// URL 会被拒绝。

问题如何被拦截或增强?#

设置一个预钩子 URL。Docsbook 会将读者的问题以 JSON 形式 POST 到该 URL 并等待响应,然后根据回复中的两个可选字段执行相应操作。

Docsbook 发送的内容:

{
  "question": "What's the price for team@acme.com?",
  "session_id": "sess_YOUR_SESSION_ID",
  "workspace_id": 42
}

Docsbook 能够理解的返回内容:

{
  "block": true,
  "reason": "Ask your account manager for account-specific pricing",
  "inject_context": "The reader is on the Acme account, locale en-GB."
}
  • block: true会停止请求。不会调用模型,也不会消耗 token。数据流会携带一个 blocked_by_hook 错误以及你的 reason ——但请注意下面关于读者实际看到内容的限制。
  • inject_context会作为一条额外的系统消息添加到提示词中,仅对本次问题有效,位于你自己的系统提示词之后、问题本身之前。实时信息应放在这里:读者的套餐、所在地区、功能开关。
  • 其他任何情况——非 2xx 状态、无法解析的 JSON、空响应正文,或在超时时间内没有回复——聊天都会继续,效果与未设置钩子时完全相同。钩子故障会降低聊天体验,但不会导致聊天中断。

三个钩子共享5 秒超时,超时通过中止请求来强制执行。预钩子的超时会让读者额外等待这几秒;另外两个钩子不会让读者付出任何等待时间,因为答案已经完成流式传输。

后置钩子接收的内容#

一次 POST,此时读者已经看到了答案:

{
  "question": "How do I rotate an API key?",
  "answer": "Rotate an API key in Workspace settings…",
  "tool_calls": [{ "tool": "read_page", "path": "guides/keys.md" }],
  "latency_ms": 2840,
  "workspace_id": 42,
  "session_id": "sess_YOUR_SESSION_ID"
}

tool_calls 是服务器针对这个问题实际获取的每个页面各对应一项,顺序与读取顺序一致——也就是读者以 Reading <page> 行形式看到的同一列表。这是检索记录,而不是模型自身工具调用的记录。

流式钩子接收 event: "message"questionanswerrefs(经过筛选后保留的引用)、workspace_idsession_idlatency_ms。它携带 tool_calls;负责执行此操作的是后置钩子。

哪种钩子适用于哪种任务#

场景 钩子 原因
拒绝回答有关其他客户账户的问题 前置钩子 只有前置钩子可以阻止请求
向模型提供读者的方案和区域设置 前置钩子 (inject_context) 模型需要在回答前获取这些信息
将每次交互镜像到你自己的分析存储中 后置钩子 需要已完成的答案,但不会更改任何内容
当回答耗时过长时向频道发出警报 流式或后置钩子 两者都携带 latency_ms
对两种提示语措辞进行 A/B 测试 前置钩子 逐个问题修改提示语
确保某个字符串永远不会到达读者那里 前置钩子或系统提示 后置钩子会在读者获得该字符串后才运行

聊天钩子是否经过签名?#

否。Docsbook 发送的是一个普通的 POST,其中包含 Content-Type: application/json,且没有 HMAC 标头,因此你的端点不得将该负载视为来源证明。请对 URL 保密,在其路径或查询字符串中放置令牌,将其限制为仅接受来自 Docsbook 出站流量的请求,并将正文视为不受信任的输入。

Docsbook 的网络钩子是另一种机制,确实经过签名:对 X-Docsbook-Signature-256 中的原始正文使用 HMAC-SHA256,具体如 sha256=<hex> 所示。不要将网络钩子的验证代码照搬到聊天钩子中,并假定它可以验证任何内容——对于任何人都可以发送的正文,该代码也会验证通过。

从 MCP 客户端管理钩子#

三个工具可从 Claude Code、Cursor 或任何 MCP 客户端配置钩子:

set_chat_hooks          # register pre / post / streaming hook URLs
test_chat_hook          # send a test ping to one hook and report its status
get_chat_system_prompt  # inspect the current system prompt

set_chat_hooks 传递空字符串即可清除单个钩子。test_chat_hook 会发送 { test: true, hook_type, workspace_id, timestamp, message },并报告状态码和往返时间,使用与实时路径相同的 5 秒超时设置。管理面板中也可以编辑相同的字段。

为什么这是正确的方式(证据)#

规则 有效原因 来源
通过预钩子注入实时事实,而不是让模型回忆这些事实 检索增强生成产生的语言“比最先进的仅参数模型基线更加具体、多样且符合事实”——放入提示词中的事实有依据;回忆出的事实则没有 Lewis 等,2020 — RAG
在预钩子处进行阻止,而不是通过后处理 仅靠指令并不能可靠地阻止模型回答:普通调优会“强制模型完成句子,无论模型是否掌握相关知识”。能够保证的拒答,是根本不会传达到模型的拒答 Zhang 等,2023 — R-Tuning
将未签名的钩子负载视为不可信 签名可以证明来源:“为了确保你的服务器只处理由 GitHub 发送的 Webhook 交付,并确保交付内容未被篡改,你应验证 Webhook 签名”。聊天钩子不带签名,因此需要自行对其进行身份验证 GitHub — 验证 Webhook 交付
以恒定时间比较 Docsbook 的 Webhook 签名 “绝不要使用普通的 == 运算符。相反,应考虑使用诸如 secure_comparecrypto.timingSafeEqual 这样的方法” GitHub — 验证 Webhook 交付

限制#

  • 读者看不到你的阻止原因。 reason 字符串会在响应流中传递,但随附的 docs-site 小组件会将其替换为通用提示“出了点问题。请重试。”问题在于:该值会在线路上传输,自定义前端可以读取它,但开箱即用的小组件不会显示它。请将 reason 视为日志所用的值,并将读者必须看到的任何内容放入系统提示中。
  • 匿名预览路径不会运行钩子。 在仓库拥有项目记录之前对其进行预览时,系统会在没有工作区的情况下回答问题,并跳过预钩子以及所有其他按项目执行的分支。
  • 没有重试,也没有投递日志。 后置钩子和流式钩子只会分发一次,其结果不会被记录。如果你需要带重试的至少一次投递,以及可见的投递历史记录,请使用Webhooks,它们同时具备这两项功能。
  • 没有签名,并且在复用 Webhooks 的方案之前没有添加签名的计划。 请参阅上文。
  • set_chat_hookstest_chat_hook 仍将自身描述为需要 Pro。 它们检查的功能在所有套餐中均已开放,因此过时的是工具描述,而不是实际行为。在这些字符串得到修正之前,该问题仍存疑。
  • 缓慢的预钩子由读者承担等待时间。 上限为五秒,并且发生在第一个令牌之前。请保持端点快速响应,或者不返回任何内容,让聊天继续进行。
  • AI 聊天 — 钩子接入的契约。
  • 回答质量 — 流水线中每个钩子所处的位置。
  • 来源 — 向助手提供其不了解的事实的另一种方式。
  • Webhooks — 经签名、可重试、事件驱动的传递。
  • MCP 服务器 — 从编辑器远程配置钩子。

Updated

此页面对您有帮助吗?