触发器
定时或接收 webhook,启动已发布的脚本或工作流。
触发器把“何时执行”与脚本、工作流的内容分开。
执行本页前,先在同一个 Bash 会话完成快速开始第 1–3 步:设置 PRAXIS_API_URL 与 PRAXIS_API_KEY、定义 SOURCE 并临时运行、定义并调用 read_result 辅助函数。该函数检查结果是否为 42,与本页的加一示例对应。再完成第 4–5 步:保存并发布脚本、设置 TARGET。TARGET 必须指向这个接收 n、返回 answer 的已发布脚本。
定时执行
每个 schedule 只能选择一种规则:
| 规则 | 用途 |
|---|---|
cron: "0 9 * * *" | 每天当地时间 09:00;五段,分钟精度,支持 L、W、#。 |
every: "PT5M" | 每隔五分钟;最短一分钟,按经过的时长计算。 |
at | RFC 3339 绝对时间,必须带时区偏移或 Z;不能早于现在或晚于一年后。 |
timezone 使用 IANA 名称,API 默认 UTC。当地时间 cron 在夏令时春季跳过不存在的时刻,秋季重复的时刻只运行一次。every 按时长、at 按绝对时间执行,不使用这条 cron 夏令时规则。
先预览下次时间:
curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/triggers/preview" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"schedule":{"cron":"0 9 * * *"},"timezone":"Asia/Shanghai"}' \
| jq -e '{next_fire_times} | select(.next_fire_times | length == 5)'期望:输出五个未来时间,例如:
{
"next_fire_times": [
"2026-10-13T01:00:00.000Z",
"2026-10-14T01:00:00.000Z",
"2026-10-15T01:00:00.000Z",
"2026-10-16T01:00:00.000Z",
"2026-10-17T01:00:00.000Z"
]
}日期随预览时间变化。末尾的 Z 表示 UTC。例如 2026-10-13T01:00:00.000Z 换算为上海时间(UTC+8)10 月 13 日 09:00。timezone 决定 cron 按哪个当地时区计算,返回的时间统一用 UTC 表达。
再创建触发器,并立即触发一次检查目标:
TRIGGER=$(curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/triggers" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' \
--data "$(jq -n --arg target "$TARGET" '{
name:"daily-hello",target:$target,kind:"schedule",input:{n:41},
schedule:{cron:"0 9 * * *"},timezone:"Asia/Shanghai",
overlap:"skip",catchup_window_seconds:300
}')")
SCHEDULE_ID=$(jq -er '.id' <<< "$TRIGGER")
jq -e '.state == "enabled" and (.next_fire_times | length == 5)' <<< "$TRIGGER"
FIRING=$(curl --fail-with-body -sS -X POST \
"$PRAXIS_API_URL/automation/v1/triggers/$SCHEDULE_ID/fire" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' --data '{}')
jq -e '.outcome == "started"' <<< "$FIRING"
read_result "$(jq -er '.run_id' <<< "$FIRING")"期望:三次断言输出 true。started 只表示启动成功;read_result 用返回的 run_id 读取运行,确认终态成功且结果为 42。
target 写 @1.0.0 固定版本,写 @latest 跟随标签;每条触发记录保存实际版本。创建和修改时检查静态输入,触发时再次检查,避免新版本不再接受原输入。
重叠、延迟与有效时间
默认 overlap: "skip":上一次运行未结束时,本次记录为 skipped_overlap;allow 允许重叠启动,仍受运行并发限制。没有排队补齐、取消旧运行或历史 backfill 策略。
catchup_window_seconds 默认 300。调度延迟超过窗口记为 missed,不会启动;这不是恢复后重放所有错过任务的承诺。暂停期间不执行,恢复后继续未来调度。
用 start_at 与 end_at 设置有效时间范围(RFC 3339)。一次性 at 执行后、或达到结束时间后变为 expired。连续 5 次触发失败会自动暂停。通过暂停和恢复控制后续触发。
暂停上面创建的触发器,再恢复:
curl --fail-with-body -sS -X POST \
"$PRAXIS_API_URL/automation/v1/triggers/$SCHEDULE_ID/pause" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' --data '{}' \
| jq -e '.state == "paused" and (.next_fire_times | length == 0)'
curl --fail-with-body -sS -X POST \
"$PRAXIS_API_URL/automation/v1/triggers/$SCHEDULE_ID/resume" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' --data '{}' \
| jq -e '.state == "enabled" and (.next_fire_times | length == 5)'期望:两次请求都输出 true;恢复后返回这个每日计划的下五次执行时间。
工作流 YAML 中的 cron/every schedule 在发布为 latest 时管理一个 source=definition 触发器;修改要重新发布定义,不能直接 PATCH 这个触发器。可以暂停或恢复它。schedule.after 与 schedule.on 暂不支持。
Webhook
创建时选 input_mode: "body",收到的 JSON 就是运行输入;非 JSON 请求体作为字符串。以下示例把 n:41 传给快速开始的脚本:
HOOK=$(curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/triggers" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'Content-Type: application/json' \
--data "$(jq -n --arg target "$TARGET" '{
name:"webhook-hello",target:$target,kind:"webhook",webhook:{input_mode:"body"}
}')")
WEBHOOK_ID=$(jq -er '.id' <<< "$HOOK")
WEBHOOK_URL=$(jq -er '.webhook_url' <<< "$HOOK")
curl --fail-with-body -sS "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-H "webhook-id: hello-$(date +%s)-$RANDOM" \
--data '{"n":41}' | jq -e '.id | startswith("frg_")'期望:HTTP 202,断言输出 true,响应含触发记录 ID。异步启动结果需要再查触发历史。
完整 URL 只在创建或轮换时返回;其中的 token 是凭据,无需 API Key,不要公开。旧 URL 在轮换后失效。错误 token、暂停或不存在的触发器都返回 404。请求体最多 1 MiB;相同 webhook-id 在 24 小时内去重。
签名头与 envelope
当前 webhook 入口验证 secret URL,不自动验证 Standard Webhooks、GitHub 或 Stripe 的 HMAC 签名。传入 webhook-signature 不代表它已经通过验签。
若目标需要读取头部,创建时使用 webhook: {input_mode:"envelope"},并让目标的输入 schema 接受下列形状(这不是快速开始的 n 输入):
{
"body": { "n": 41 },
"headers": { "content-type": "application/json", "webhook-id": "delivery-1" },
"webhook_id": "delivery-1",
"received_at": "2026-10-11T12:00:00.000Z"
}webhook_id 未提供时为 null。只保留以下头:content-type、user-agent、webhook-id、webhook-timestamp、webhook-signature、x-github-event、x-github-delivery、x-hub-signature-256、stripe-signature;Authorization、Cookie 不会转交。
JSON body 会先被解析,envelope 不包含独立的原始请求字节。对于必须签署原始字节的协议,不能用 JSON.stringify(body) 代替原文验签。需要这种验证时,在你接收原始请求的服务中按发送方协议先验证,再转发到 secret URL。当前没有可直接套用到此 JSON envelope 的通用验签示例。
查看触发记录与清理
curl --fail-with-body -sS \
"$PRAXIS_API_URL/automation/v1/triggers/$WEBHOOK_ID/firings" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
| jq -e '.data | length > 0'
curl --fail-with-body -sS \
"$PRAXIS_API_URL/automation/v1/triggers/$WEBHOOK_ID/firings" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
| jq '.data[] | {outcome,run_id,resolved_version,error}'期望:第一个请求输出 true,第二个列出记录。若异步处理尚未完成,稍后重新读取。started 表示已启动,failed 看 error,missed 表示超过窗口,skipped_overlap 表示前次未结束,deduped 表示命中去重。按 run_id 继续查看运行终态,记录保留 30 天。
测试完成后删除本页创建的两个触发器,避免继续定时执行:
for id in "$SCHEDULE_ID" "$WEBHOOK_ID"; do
curl --fail-with-body -sS -X DELETE \
"$PRAXIS_API_URL/automation/v1/triggers/$id" \
-H "Authorization: Bearer $PRAXIS_API_KEY"
done期望:curl 均退出 0。删除不影响已经启动的运行。