{
    "format": "skillpro/v1",
    "skill_id": "lobehub-lobehub-agents-skills-agent-runtime-hooks-skill-md",
    "name": "agent-runtime-hooks",
    "version": "1.0.0",
    "description": "Use for agent lifecycle hooks, tool mocks, intervention, sub-agent calls and context compression.",
    "category": [
        "生活与工具"
    ],
    "trigger_words": [],
    "tags": [
        "agent"
    ],
    "source": "DeepseekModel",
    "source_url": "https://deepseekmodel.com/skill?id=lobehub-lobehub-agents-skills-agent-runtime-hooks-skill-md",
    "exported_at": "2026-09-17T10:10:05+08:00",
    "system_prompt": "name agent-runtime-hooks description Use for agent lifecycle hooks, tool mocks, intervention, sub-agent calls and context compression. user-invocable false Agent Runtime Hooks Lifecycle hooks for observing and intercepting agent execution. Hooks are registered per-operation via execAgent({ hooks }) and dispatched by HookDispatcher . 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 (observation only) │ │ └─ 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 sub-agent completes │ │ └─ onCallAgentError ── Sub-agent failed │ │ │ └─ afterStep ──────────── After step completes │ ├─ (next step...) │ ├─ onComplete ───────────── Operation reaches terminal state └─ onError ──────────────── Error during execution Key Files File Role packages/agent-runtime/src/types/hooks.ts Type definitions (AgentHookType, all event interfaces) apps/server/src/services/agentRuntime/hooks/types.ts Server-side types (AgentHook, re-exports) apps/server/src/services/agentRuntime/hooks/HookDispatcher.ts Registration, dispatch, dispatchBeforeToolCall apps/server/src/modules/AgentRuntime/RuntimeExecutors.ts Tool/Compact/HumanIntervention hook dispatch apps/server/src/services/agentRuntime/AgentRuntimeService.ts Step hooks + HumanIntervention resume/reject apps/server/src/services/aiAgent/subAgentRuns.ts CallAgent hook dispatch Registration Flow const hooks : AgentHook [] = [ { id : 'my-hook' , type : 'afterStep' , handler : async (event) => { ... } }, ]; await aiAgentService. execAgent ({ agentId, prompt, hooks }); // Internally: hookDispatcher.register(operationId, hooks) // Cleanup: hookDispatcher.unregister(operationId) Hook Reference Step Level beforeStep — Before each step. event: AgentHookEvent afterStep — After each step. event: AgentHookEvent (content, toolsCalling, totalCost, etc.) onComplete — Terminal state. event: AgentHookEvent (reason: done/error/interrupted/max_steps/cost_limit) onError — Error occurred. event: AgentHookEvent (errorMessage, errorDetail) Tool Call Level beforeToolCall — Before tool executes. Supports mocking via event.mock() . // event: ToolCallHookEvent { (identifier, apiName, args, callIndex, stepIndex, operationId, mock); } // Mock example: event. mock ({ content : '{\"error\":\"rate limited\"}' }); Dispatch method: hookDispatcher.dispatchBeforeToolCall() (returns mock result or null). afterToolCall — After tool completes. Observation only. // event: AfterToolCallHookEvent { (identifier, apiName, args, callIndex, content, success, mocked, executionTimeMs, stepIndex); } onToolCallError — Tool threw an exception (catch block, not just success=false ). // event: ToolCallErrorHookEvent { (identifier, apiName, args, callIndex, error, stepIndex); } Human Intervention beforeHumanIntervention — Before agent pauses for approval. // event: BeforeHumanInterventionHookEvent { operationId, stepIndex, pendingTools : [{ identifier, apiName }] } afterHumanIntervention — After approve/reject, agent resumes. // event: AfterHumanInterventionHookEvent { operationId, action : 'approve' | 'reject' | 'rejectAndContinue' , toolCallId?, rejectionReason? } onStopByHumanIntervention — User rejected, agent halted. // event: StopByHumanInterventionHookEvent { operationId, toolCallId?, rejectionReason? } Context Compression beforeCompact — Before compression starts. // event: BeforeCompactHookEvent { (operationId, stepIndex, messageCount, tokenCount); } afterCompact — After compression completes. // event: AfterCompactHookEvent { (operationId, stepIndex, groupId, messagesBefore, messagesAfter, summary); } onCompactError — Compression failed. // event: CompactErrorHookEvent { (operationId, stepIndex, tokenCount, error); } Sub-Agent (CallAgent) beforeCallAgent — Before calling sub-agent. Dispatched on parent operation. // event: BeforeCallAgentHookEvent { (operationId, agentId, instruction); } afterCallAgent — Sub-agent completed. Dispatched on parent operation. // event: AfterCallAgentHookEvent { (operationId, agentId, subOperationId, threadId, success); } onCallAgentError — Sub-agent failed. Dispatched on parent operation. // event: CallAgentErrorHookEvent { (operationId, agentId, error); } Note: CallAgent hooks require parentOperationId in ExecSubAgentTaskParams . Design Notes Fire-and-forget : All handlers return Promise<void> . Errors are non-fatal. Exception : beforeToolCall supports mock via event.mock() — uses dispatchBeforeToolCall() which returns the mock result. Sequential : Same-type hooks run in registration order. Local only : beforeToolCall mock only works in local mode (in-memory hooks). Webhook mode does not support mocking. Scoped per operation : Auto-cleaned via hookDispatcher.unregister() on completion. Sandbox/MCP : No separate hooks — they go through executeTool , so beforeToolCall / afterToolCall cover them. Use event.identifier to filter. Real-World Example: agent-evals See devtools/agent-evals/helpers/runner.ts — createEvalHooks() uses afterStep , onComplete , afterToolCall , and beforeToolCall (for mock).",
    "model_config": {
        "provider": "deepseek",
        "model": "deepseek-chat",
        "temperature": 0.7,
        "max_tokens": 4096,
        "top_p": 0.9
    },
    "examples": [
        {
            "input": "请用agent-runtime-hooks帮我处理问题",
            "output": "好的，我是agent-runtime-hooks。Use for agent lifecycle hooks, tool mocks, intervention, sub-agent calls and context compression. 我会根据你的需求提供专业帮助。"
        },
        {
            "input": "介绍一下你的能力",
            "output": "我是agent-runtime-hooks，专注于生活与工具领域。Use for agent lifecycle hooks, tool mocks, intervention, sub-agent calls and context compression."
        }
    ],
    "install_guide": {
        "coze": "在 Coze 平台创建 Bot -> 技能配置 -> 导入此 .skill 文件",
        "dify": "在 Dify 平台创建应用 -> 添加知识库 -> 导入此 .skill 配置",
        "claude": "将 system_prompt 字段内容复制到 Claude 自定义指令中",
        "custom": "将此 .skill 文件加载到你的 AI Agent 框架中，解析 system_prompt 和 model_config 即可使用"
    },
    "scripts": {
        "python": "# agent-runtime-hooks - Python extension\n# Add custom Python logic here\ndef process(input_data):\n    return input_data\n",
        "javascript": "// agent-runtime-hooks - JavaScript extension\n// Add custom JS logic here\nfunction process(inputData) {\n    return inputData;\n}\n"
    },
    "tools": {
        "mcp_servers": [],
        "api_endpoints": []
    },
    "dependencies": {
        "python": [],
        "node": []
    },
    "hooks": {
        "on_load": "echo \"Skill loaded: agent-runtime-hooks\"",
        "on_call": "",
        "on_error": "echo \"Skill error: please check logs\""
    }
}