API Prompt
面向 AI 优先工作流的自然语言 HTTP 触发器。
API Prompt 触发器暴露一个 HTTP 端点,接受自然语言提示(以及可选的结构化上下文和元数据),并以这些字段作为块输出来运行工作流。当你希望 API 的使用体验更像"与工作流对话"而非"填写 JSON 表单"时,这就是合适的触发器。
请求契约
POST /api/webhooks/prompt/{path}
Content-Type: application/json
{
"prompt": "Summarize these PDFs and email me the result",
"context": { "pdf_ids": ["abc", "def"] },
"metadata": { "request_origin": "internal-app-v2" }
}prompt(字符串,必填)— 自然语言指令。上限为maxPromptLength(默认 10 000 字符,硬限制 50 000)。context(对象,可选)— 任意 JSON。用于随提示一起传递结构化引用(ID、文件路径、用户信息等)。metadata(对象,可选)— 调用方提供的标识符,用于路由/日志记录。
任何其他顶级字段均会被忽略。context 和 metadata 中的嵌套 JSON 会被完整保留。
块输出
通过 <apiprompt1.*> 在下游块中可用:
| 输出 | 类型 | 描述 |
|---|---|---|
prompt | string | 调用方的提示,已去除首尾空格并完成长度验证 |
context | json | null | context 对象,未提供时为 null |
metadata | json | null | metadata 对象,未提供时为 null |
requestId | string | 服务器生成的 ID — 传播至日志/追踪 |
caller | string | 推导出的调用方身份(bearer-hash / header-hash / hmac-hash / IP) |
timestamp | string | ISO-8601 格式的服务器接收时间 |
guardrailsTriggered | boolean | 如果匹配到任何已知的提示注入模式则为 True |
matchedInjectionPatterns | array | 匹配到的模式名称列表(无匹配时为空) |
认证
支持与通用 Webhook 触发器相同的 4 种模式:
| 模式 | 发送的请求头 | 适用场景 |
|---|---|---|
none | — | 公开端点、位于其他网关后面的内部工具 |
bearer | Authorization: Bearer <token> | 程序化 AI 调用方 — 推荐默认值 |
custom_header | <configured-name>: <token> | 匹配旧有约定 |
hmac_sha256 | X-Signature: <hex>(基于原始请求体) | 最高安全保障 — 无状态、防重放 |
签名示例(bash / Node / Python)请参阅 Webhooks → 认证。
调用方快速入门 — HMAC
当你配置 HMAC-SHA256 认证时,平台期望收到用共享密钥对请求体原始字节进行签名所生成的十六进制摘要,并通过 X-Signature 请求头(或你在签名请求头中设置的自定义名称)发送。
签名必须覆盖你实际在网络上发送的字节。如果你的 HTTP 客户端对 JSON 进行了重新序列化(重新排序键、删除空白符、以不同方式转义 Unicode),签名将不匹配。请构建一次请求体字符串,对该字符串签名,再发送该字符串。在 curl 中使用 --data-raw;在 Python 中用 json.dumps(...).encode() 预编码并传入 data=body;在 Node 中构建字符串并将其作为 fetch 的 body 传入。
curl
WEBHOOK_URL="https://staging-app.mybotbox.com/api/webhooks/prompt/<path>"
SECRET="<your HMAC secret>"
BODY='{"prompt":"Summarize last week of standup notes","context":{"team":"platform"}}'
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
curl -X POST "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-H "X-Signature: $SIGNATURE" \
-H "X-Timestamp: $TIMESTAMP" \
--data-raw "$BODY"注意事项:
- 当触发器的重放窗口启用时(默认 300 秒),
X-Timestamp(Unix 秒或 ISO-8601)为必填项。缺失时将返回401 — timestamp outside replay window。 sha256=前缀可被接受,但非必须 — 服务器会以不区分大小写的方式将其去除。X-Idempotency-Key: <your-request-id>为可选项,但建议添加,以便重试时返回200 { "status": "duplicate" }而非重新触发工作流。
Python
import hmac, hashlib, json, time, requests
WEBHOOK_URL = "https://staging-app.mybotbox.com/api/webhooks/prompt/<path>"
SECRET = b"<your HMAC secret>"
body = json.dumps(
{"prompt": "Summarize last week of standup notes", "context": {"team": "platform"}},
separators=(",", ":"),
).encode()
sig = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
resp = requests.post(
WEBHOOK_URL,
data=body,
headers={
"Content-Type": "application/json",
"X-Signature": sig,
"X-Timestamp": str(int(time.time())),
"X-Idempotency-Key": "req-2026-05-17-001",
},
)
print(resp.status_code, resp.text)Node.js / TypeScript
import { createHmac } from 'node:crypto'
const WEBHOOK_URL = 'https://staging-app.mybotbox.com/api/webhooks/prompt/<path>'
const SECRET = process.env.MBB_HMAC_SECRET! // never hardcode
const body = JSON.stringify({
prompt: 'Summarize last week of standup notes',
context: { team: 'platform' },
})
const sig = createHmac('sha256', SECRET).update(body).digest('hex')
const res = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Signature': sig,
'X-Timestamp': Math.floor(Date.now() / 1000).toString(),
},
body,
})
console.log(res.status, await res.text())接入第三方调用方
当你向第三方开放某个 API Prompt 触发器时,请只共享以下四项内容:
- Webhook URL —
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> - HMAC 密钥 — 你在"HMAC secret"字段中填写的值
- 签名请求头名称 —
X-Signature(默认)或你设置的自定义名称 - 请求体契约 —
{ prompt: string, context?: object, metadata?: object }的结构,以及你配置的maxPromptLength和是否启用了requireContext
如何安全共享密钥
HMAC 密钥对每次调用进行认证。一旦泄露,任何人都可以用任意提示触发你的工作流。请像对待数据库密码一样对待它。
请勿:
- 通过邮件或 Slack 以明文发送
- 粘贴到共享文档中(Notion、Confluence、Google Docs)
- 提交到任何仓库,即使是私有仓库
- 在测试环境和生产环境中复用同一个密钥
推荐做法(按优先级排序):
- 1Password / Bitwarden 共享条目 — 限定接收方邮箱并设置到期时间。大多数团队已具备此条件。
- 加密消息 — 使用 Signal,或通过
gpg --encrypt --recipient <them@…>加密后,将密文通过任意渠道发送。 - 一次性密钥链接 —
https://onetimesecret.com或自托管同类服务。单次查看,几分钟后自动销毁。 - 视频通话中口头告知 — 接收方当场粘贴到自己的密钥存储中,之后双方同时关闭共享。不留任何书面记录。
运营规范
- 生成强密钥:
openssl rand -hex 32(256 位)。1234567890这类占位符仅适合初次冒烟测试,对外共享前请务必轮换。 - 每 90 天轮换一次,或在调用方下线时立即轮换。在触发器 UI 中更新密钥并保存,然后通知调用方。保存的瞬间旧签名即失效 — 如需过渡期,可在切换期间并行运行两个触发器。
- 告知调用方密钥的存放位置:密钥管理器(AWS Secrets Manager / GCP Secret Manager / HashiCorp Vault / Doppler)或 CI 环境变量存储。切勿放在源码中。
- 轮换后关注日志:突然出现大量 401 错误,通常意味着某个调用方没收到轮换通知。
触发器 UI 当前显示的 URL 是规范端点:/api/webhooks/prompt/<path>。旧版 /api/webhooks/trigger/<path> 路径(早期版本中所有触发器类型均使用此路径)仍可使用以保持向后兼容 — 两条路由共享相同的 HMAC 验证和安全防护机制。在记录集成文档时,请优先使用 /prompt/ 路径。
重放保护、幂等性与速率限制
- 重放窗口(仅 HMAC 模式):拒绝
X-Timestamp与服务器时间相差超过 N 秒的请求。默认 300 秒,设为0可禁用。 - 幂等性:启用后,重复请求(通过
X-Idempotency-Key、请求体id或请求体哈希进行匹配)将返回200 { status: "duplicate" },不会重新运行工作流。去重窗口为 7 天。 - 调用方速率限制:默认每分钟 20 次请求,以推导出的调用方身份为键。超限时触发
429,并返回Retry-After请求头。
提示注入防护
启用后(默认开启),平台会将提示与一份常见注入模式的拒绝列表进行比对(ignore previous instructions、system: 前缀、聊天模板标记等),并将结果体现在 guardrailsTriggered 和 matchedInjectionPatterns 中。防护机制为非阻断式 — 工作流仍会继续运行 — 因此你可以按工作流自行决定是拒绝请求、路由至人工审核,还是直接继续执行。
防护机制是一种尽力而为的预过滤手段,不能替代 LLM 侧的防御措施。在下游块中始终将提示视为不可信输入。对于高风险操作(发送邮件、执行代码、调用付费 API),请添加明确的确认步骤,或在 guardrailsTriggered 为 true 时路由至审核流程。
典型工作流结构
- API Prompt 触发器(本块)— 调用方发送
{ prompt, context }。 - Agent / LLM 块 — 接收
<apiprompt1.prompt>和<apiprompt1.context>,通过工具调用规划后续操作。 - 下游操作块(邮件、数据库、第三方 API)— 执行计划。
- Response 块 — 将 Agent 的摘要返回给原始调用方。
示例 — PDF 摘要生成器
curl -X POST https://staging-app.mybotbox.com/api/webhooks/prompt/abc123 \
-H 'Authorization: Bearer $MBB_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"prompt": "Summarize these PDFs into bullet points and email to team@example.com",
"context": {
"pdf_gcs_paths": [
"gs://my-bucket/docs/report-2026-q1.pdf",
"gs://my-bucket/docs/report-2026-q2.pdf"
]
}
}'工作流配置:
- API Prompt 块 → Agent(Claude Haiku) 块,配置工具
[gcs_read_file, gmail_send],系统提示为"Follow the user's instructions. Use tools as needed."。 - Agent 的用户消息:
<apiprompt1.prompt>\n\nContext: <apiprompt1.context>。
使用内置脚本进行验证
# Bearer token mode (recommended default).
bun apps/sat/tests/staging/triggers/api_prompt/verify.ts \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--secret=<bearer-token>
# Or HMAC mode.
bun apps/sat/tests/staging/triggers/api_prompt/verify.ts \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--hmac=<hmac-secret>python3 apps/sat/tests/staging/triggers/api_prompt/verify.py \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--secret=<bearer-token>源码:apps/sat/tests/staging/triggers/api_prompt/。
何时使用 API Prompt vs 通用 Webhook
| 使用 API Prompt 的场景… | 使用通用 Webhook 的场景… |
|---|---|
| 请求体为提示 + 上下文 | 请求体为具有固定字段的结构化 JSON |
| 第一个块是负责规划的 LLM/Agent | 第一个块是条件判断或数据库操作 |
| 调用方是 AI 系统或聊天机器人 | 调用方是发送事件的服务 |
| 开箱即用地需要防护机制和调用方速率限制 | 需要提供商风格的 HMAC 和去重功能 |
当请求体字段与工作流变量一一对应时,通用 Webhook 更简单、更高效。如果你希望由 LLM 充当路由器,请使用 API Prompt。