跳到正文
cccskills
免费在 GitHub 公开中文介绍

agent-runtime-hooks

说明如何在智能体执行步骤、工具调用、人工审批、上下文压缩和子智能体调用时注册钩子。钩子可观察事件、模拟本地工具结果,也可通过 Webhook 按配置策略允许或拒绝工具调用。

原文查看原文说明

Use for agent lifecycle hooks, tool mocks, intervention, sub-agent calls and context compression.

lobehub/lobehub星标 83,504(GitHub 83,504 + cccskills 0)

实测评分 未实测

查看安装方法

适用场景

  • 记录智能体步骤和错误
  • 测试时模拟工具结果
  • 通过 Webhook 允许或拒绝工具调用
  • 追踪审批和子智能体流程

中文介绍

功能

这份指南介绍如何为智能体的执行生命周期注册钩子,并处理不同阶段的事件。可观察的事件包括步骤开始与完成、工具调用及错误、人工审批、上下文压缩、子智能体调用和最终运行状态。本地处理函数可以模拟工具结果;Webhook 可以发送事件通知,也可以在配置了决策处理时允许或拒绝工具调用。指南还说明事件上下文中包含的运行 ID、工具信息和结果,以及 Webhook 的请求内容与投递错误行为。

适用场景

如果要监控智能体运行过程或在运行中介入,可以参考这份指南。它也适用于测试时替换工具结果,以及追踪包含人工审批和子智能体的处理流程。

使用示例

  • “请设置一个在工具运行前检查权限的 Webhook 钩子。”
  • “请添加记录这个智能体步骤和错误的钩子。”
  • “请在测试中用本地处理函数模拟工具结果。”

注意事项

配置和使用 Webhook 需要目标 URL。若请求头使用环境变量,必须指定允许列表;秘密值只在发送时展开,不会在保存配置时展开。仅通过 Webhook 配置注册的钩子在进程重启后无法恢复函数处理程序。

本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。

文档检查

AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。

安全性发送数据、删除文件、执行命令等是否有说明
B部分不足Webhook 可允许或拒绝执行,但失败处理涉及多项配置。
安装难易度所需工具和 API 密钥是否少且有说明
B部分不足资料说明 Webhook 需要目标 URL 和环境变量允许列表。

不计入评分。 由 AI(OpenAI Codex)于 2026年10月26日 评估。仅供参考,安装前请同时查看原文。

如果您认为评估有误,请申请复核

请写明哪一项有误以及原因。无需登录。我们会对照 SKILL.md 重新评估,并在此处更新结果。

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

包含的文件(1)

  • SKILL.md15.9 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Agent Runtime Hooks

Register lifecycle hooks through execAgent({ hooks }). HookDispatcher stores them per operation and dispatches them in registration order.

Hook Types

16 hook types across 5 categories:

execAgent({ hooks })
  │
  ├─ beforeStep ──────────── Before each step executes
  │     │
  │     ├─ [call_llm]        LLM inference
  │     │
  │     ├─ [call_tool]
  │     │     ├─ beforeToolCall ── Before tool executes (supports mocking)
  │     │     ├─ (tool execution)
  │     │     ├─ afterToolCall ─── After tool completes (optional result control)
  │     │     └─ onToolCallError ─ Tool threw an exception
  │     │
  │     ├─ [request_human_approve]
  │     │     ├─ beforeHumanIntervention ── Before agent pauses
  │     │     ├─ afterHumanIntervention ─── After approve/reject + resume
  │     │     └─ onStopByHumanIntervention ── User rejected, agent halted
  │     │
  │     ├─ [compress_context]
  │     │     ├─ beforeCompact ──── Before compression starts
  │     │     ├─ afterCompact ───── After compression completes
  │     │     └─ onCompactError ─── Compression failed
  │     │
  │     ├─ [callAgent] (via execSubAgentTask)
  │     │     ├─ beforeCallAgent ── Before sub-agent starts
  │     │     ├─ afterCallAgent ─── After creation/start returns
  │     │     └─ onCallAgentError ── Sub-agent failed
  │     │
  │     └─ afterStep ──────────── After step completes
  │
  ├─ (next step...)
  │
  ├─ onComplete ───────────── Operation reaches terminal state
  └─ onError ──────────────── Error during execution

Key Files

FileRole
packages/agent-runtime/src/types/hooks.tsEvent types and required/optional fields
apps/server/src/services/agentRuntime/hooks/types.tsRegistration and webhook types
apps/server/src/services/agentRuntime/hooks/HookDispatcher.tsRegistration, dispatch, local mocks, HTTP/QStash delivery
apps/server/src/services/agentRuntime/hooks/webhookPayload.tsEvent projection and email enrichment
apps/server/src/modules/AgentRuntime/adapters/toolCallHookContext.tsShared tool-event context builder
apps/server/src/modules/AgentRuntime/adapters/ServerToolTransport.tsTool notifications and execution results
apps/server/src/modules/AgentRuntime/RuntimeExecutors.tsTool, compression and human-intervention execution
apps/server/src/services/agentRuntime/AgentRuntimeService/ (executeStep/, intervention.ts)Step events and human-intervention continuation
apps/server/src/services/agentRuntime/CompletionLifecycle/index.tsTerminal events
apps/server/src/services/aiAgent/subAgentRuns.tsSub-agent events

Registration

const hooks: AgentHook[] = [
  {
    id: 'observe-step',
    type: 'afterStep',
    handler: async (event) => {
      console.log(event.operationId, event.stepIndex);
    },
  },
];
await aiAgentService.execAgent({ agentId, prompt, hooks });

Completion cleans up registrations through hookDispatcher.unregister(operationId).

Webhook Hooks

Webhook-only hooks deliver in both local and queue modes. For hooks with both handler and webhook, local dispatch calls the handler; queue dispatch uses the serialized webhook. Only webhook configuration is persisted, so functions are unavailable after a process restart.

const hook: AgentHook = {
  id: 'tool-notification',
  type: 'afterToolCall',
  matcher: '^fs/readFile$',
  webhook: {
    url: 'https://example.com/hooks',
    delivery: 'fetch',
    timeout: 5, // seconds; default 30
    headers: { Authorization: 'Bearer ${HOOK_TOKEN}' },
    allowedEnvVars: ['HOOK_TOKEN'],
  },
};
  • matcher is a regex against ${identifier}/${apiName}, supported only on tool events. Omitted, empty, or * matches all tools.
  • Header environment templates resolve only at send time from allowedEnvVars; persist templates, never resolved secrets.
  • Notifications ignore response content and may return HTTP 204.
  • beforeToolCall with responseHandling: 'toolCall' awaits an optional HTTP decision before tool execution. Return HTTP 2xx JSON with { "decision": "allow" } or { "decision": "deny", "reason": "禁止执行该操作" } to intervene. The type is { decision: 'allow' } | { decision: 'deny'; reason?: string }; a deny with an omitted or empty reason uses Blocked by beforeToolCall hook.. Denials preserve the reason in the tool result/card with classification hook_denied.
  • afterToolCall also accepts responseHandling: 'toolCall'. It synchronously checks the full request/result before archival and model consumption; deny replaces the original result with the receiver's optional reason in both content and blocked state. A deny with an omitted or empty reason uses Blocked by afterToolCall hook., following the same Blocked by ${type} hook. rule as beforeToolCall. The reason enters model context and the tool card, as with beforeToolCall. It does not undo tool side effects, retries, or charges. See the result-control contract for deferred completions and runtime boundaries.
  • Environment response modes are ignore (default notifications) and toolCall (optional decisions for both before and after). Only subscribed events are enabled. Replace removed toolResult/toolCallAndResult values with toolCall; use the events list to select after-only checking. Existing after responses with a valid decision now control results.
  • HTTP 204, empty successful bodies, invalid JSON, and JSON without a top-level decision (including arrays, scalars, null, or only the old nested hookSpecificOutput) are notification responses, even with onError: 'block'. Continue checking subsequent hooks; do not treat a notification as permission to skip later policies. Explicit invalid decisions, non-2xx status, oversized bodies, invalid UTF-8, network failures, and timeouts follow onError: 'continue' | 'block' (default continue); blocking uses hook_control_error as the tool-result content and reason for both before and after hooks. Cancellation never grants permission.
  • Extra response fields are allowed and discarded. Only decision and a deny's optional string reason are consumed; updatedInput/additionalContext do not change tool arguments or conversation context.
  • Configuration: packages/types/src/agentHook.ts; response parsing: packages/types/src/agentHookResponse.ts; HTTP delivery: apps/server/src/services/agentRuntime/hooks/httpWebhook.ts.

Hook configuration lifetime

  • Environment hooks (AGENT_HOOK_WEBHOOK_*) always come from the executing worker's current environment, including after human approval and deferred completion. Never persist their configuration or restore a previous environment's hooks.
  • Code-supplied webhook hooks (execAgent({ hooks })) retain the existing per-operation serialization and persistence. Recover these caller hooks from the runtime snapshot or durable operation record; preserve environment-variable templates without expanding secrets into storage.
  • Evaluate each operation's recovered caller hooks in order, then evaluate current environment hooks once in the final round. Do not deduplicate caller hook IDs across operations. Environment-only hooks do not require durable operation storage. Removing an environment hook stops it from controlling subsequent results; when no matching result control remains, allow the result. Do not freeze a previous environment policy across an approval or restart.
  • Deferred completion publishes into its empty placeholder once; duplicate callbacks retain that first final result, including a denial. Propagate caller-policy storage errors rather than treating failed reads as an empty hook list. Do not extend default allow to configured-hook delivery failures: those follow onError.
  • Cover environment removal/addition across approval and snapshot expiry, publication without review markers, and continued enforcement of persisted caller hooks in regression tests.

Publish after the result hook

  • Await result control before archival, message content/state writes, streaming, and model consumption. Persist the allowed result or the sanitized denial directly; do not add toolResultControl pending/allowed/blocked metadata or hide raw output through history projections.
  • Human approval sources claim the decision and retain the answer in their private resolution/outbox. MessageModel.resolveHumanApproval defaults to claim-only; only the runtime calls it with publishResult: true after result control. Stop/rejection receipts can publish directly because they contain no executed tool output.
  • Recover original caller hooks through the existing intervention operation identity or deferred callback's parent operation. Keep the in-memory hook verdict separate from tool-owned state; a tool returning type: 'blocked' is not a hook verdict.
  • Every deferred backfill, including a member that fails to start, follows the same hook-before-write order. Use the existing empty placeholder to arbitrate duplicate final writes; do not introduce a replacement review state machine.
  • When a thread has a sub-agent or group-member completion bridge, that bridge exclusively publishes its tool result. Thread lifecycle hooks update thread metadata only; never prefill the tool message with an ungated summary, including after approval recovery.
  • Cover an answer held while a hook runs, atomic publication and rollback, duplicate callbacks after policy removal, and partial member startup failure. History readers should need no result-review logic.

Events

EventTiming and payload
beforeStepBefore a step; AgentHookEvent
afterStepAfter a step; content, tool calls/results and usage totals
onCompleteTerminal state; reason such as done, error, interrupted, max_steps or cost_limit
onErrorOperation error; errorMessage, errorDetail and available error metadata
beforeToolCallBefore tool execution; shared tool context and local mock() callback
afterToolCallAfter tool execution; structured result and mocked
onToolCallErrorTool execution throws; shared tool context and error
beforeHumanInterventionBefore approval; pendingTools, operationId, stepIndex
afterHumanInterventionApproval decision and continuation; action, optional toolCallId and rejectionReason
onStopByHumanInterventionHuman rejection stops the run; optional toolCallId and rejectionReason
beforeCompactBefore compression; messageCount, tokenCount, stepIndex
afterCompactAfter compression; groupId, messagesBefore, messagesAfter, summary
onCompactErrorCompression error; error, tokenCount, stepIndex
beforeCallAgentBefore sub-agent creation; agentId, instruction
afterCallAgentCreation/start returns; agentId, subOperationId, success, optional threadId
onCallAgentErrorSub-agent call fails; agentId, error

CallAgent events dispatch on the parent operation identified by parentOperationId. An isolated child supplies threadId; shared group members use the shared conversation. Child completion is reported by the child's onComplete event.

Tool Context

Use buildToolCallHookContext() for the three tool events.

  • Required fields: native toolCallId, assistantMessageId, identifier, apiName, effective args, callIndex, stepIndex, operationId and executor.
  • Optional associations come from the run context: agent, topic, session, thread, group, task, workspace, document, source/tool message and parent operation IDs.
  • userId uses runtime.userId ?? origin.userId.
  • toolSource identifies the tool's origin; executor identifies the server/client dispatch route. executionTarget and activeDeviceId describe the run's execution plan and device selection.
  • afterToolCall.result carries content, success, optional executionTime and error/state data such as state.type: 'blocked'. mocked marks results supplied by a local hook.

Sandbox and MCP tools use the same event path. Filter with identifier, apiName or toolSource.

Local Mocking

dispatchBeforeToolCall() exposes event.mock(result). The first accepted mock wins and short-circuits the remaining mock handlers. The method returns { isMocked: true, result } for a mock, or null to continue execution.

event.mock({ content: '{"items":[]}', success: true });

Tool observation payloads use BeforeToolCallObservationEvent; the callback belongs to the in-memory handler event. dispatchBeforeToolCall() does not deliver webhooks.

Webhook Payloads

createWebhookPayloadBuilder() selects eventFields, adds hookId/hookType, then merges webhook.body. The body determines the final value of overlapping fields. Tool-result notification payloads use redactResultForEvents() to trim raw skill Work data; controls receive the full result. Work registration retains the full in-process result. finalState is available to local handlers; serialized payloads carry the event's data fields.

When email is selected, the builder resolves userEmail from the final effective userId, replacing supplied email values. Email-only projections use the event ID. An explicit invalid ID, missing email or lookup error leaves email omitted.

Email queries share a per-dispatcher cache of up to 1,000 users for five minutes. Query timeouts belong to the database layer. The builder's optional fourth { signal } argument lets a waiter cancel independently; cancellation returns undefined so the caller can stop delivery. Fetch and QStash use the enriched payload.

Delivery Errors

Dispatch awaits each handler or webhook. Ordinary errors are logged and dispatch continues. Webhooks with fallback: 'none' accumulate a CriticalHookDeliveryError, which is thrown after sibling hooks have run. QStash delivery defaults to a fetch fallback; use fallback: 'none' for QStash-signed endpoints.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

acceptance

免费有简介

通过实际操作产品验证交付内容,记录用户可查看的证据,并发布验收报告。可检查已有验证计划或创建检查项,选择合适的操作界面,并使用 `lh` CLI 发布结果。

  • 实际检查更改后的产品行为
  • 收集截图或其他验证证据
  • 编写验证计划和报告
lobehub/lobehub8.4万2026年10月26日 更新

add-model-provider

免费有简介

本技能指导在 LobeHub 中接入 AI 模型提供商,涵盖运行时、模型信息、设置、品牌展示、文档和验收,并帮助判断新增模型是否需要新的提供商集成。

  • 为 LobeHub 接入新的 AI 模型提供商
  • 更新提供商设置说明或介绍
  • 判断添加模型是否需要新的提供商集成
lobehub/lobehub8.4万2026年10月26日 更新

add-setting-env

免费有简介

本技能指导如何用服务器端环境变量设置用户偏好默认值,涵盖变量校验、服务器配置、写入用户状态,以及更新 `.env.example` 和自托管文档。

  • 通过环境变量设置用户偏好默认值
  • 将设置接入服务器配置和用户状态
  • 更新环境变量示例及文档
lobehub/lobehub8.4万2026年10月26日 更新

agent-signal

免费有简介

此技能用于为智能体设计事件驱动的后台工作流,划分来源、信号、动作和策略的职责,并处理异步交接、去重、执行范围、完成记录与运行观测。

  • 添加事件触发的后台任务
  • 将工作移出对话请求
  • 防止动作重复执行
lobehub/lobehub8.4万2026年10月26日 更新

agent-testing-bot

免费有简介

本技能在 macOS 桌面聊天应用中测试机器人频道:打开应用、进入频道或联系人、发送消息、等待回复并截图。支持 Discord、Slack、Telegram、微信、飞书和 QQ;iMessage 使用 BlueBubbles 桥接。

  • 检查真实 Discord 频道中的机器人回复
  • 测试 Slack 或 Telegram 的对话流程
  • 记录 macOS 应用中的操作结果
lobehub/lobehub8.4万2026年10月26日 更新

agent-tracing

免费有简介

按操作编号检查智能体运行记录,查看失败的工具调用、参数与结果、运行上下文及传给大语言模型的内容;还可查看上下文映射,并用其他模型重放记录以便比较。

  • 排查失败的工具调用
  • 确认传给大语言模型的上下文
  • 按操作追踪工具及结果
lobehub/lobehub8.4万2026年10月26日 更新

查看 lobehub 的全部技能

报告此技能的问题