Entropic 2.14.3
Local-first agentic inference engine
Loading...
Searching...
No Matches
hooks.h File Reference

Hook point enum and callback types for engine lifecycle hooks. More...

#include <stddef.h>
Include dependency graph for hooks.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef int(* entropic_hook_callback_t) (entropic_hook_point_t hook_point, const char *context_json, char **modified_json, void *user_data)
 Hook callback function type.
 

Enumerations

enum  entropic_hook_point_t {
  ENTROPIC_HOOK_PRE_GENERATE , ENTROPIC_HOOK_POST_GENERATE , ENTROPIC_HOOK_ON_STREAM_TOKEN , ENTROPIC_HOOK_PRE_TOOL_CALL ,
  ENTROPIC_HOOK_POST_TOOL_CALL , ENTROPIC_HOOK_ON_LOOP_ITERATION , ENTROPIC_HOOK_ON_STATE_CHANGE , ENTROPIC_HOOK_ON_ERROR ,
  ENTROPIC_HOOK_ON_DELEGATE , ENTROPIC_HOOK_ON_DELEGATE_COMPLETE , ENTROPIC_HOOK_ON_CONTEXT_ASSEMBLE , ENTROPIC_HOOK_ON_PRE_COMPACT ,
  ENTROPIC_HOOK_ON_POST_COMPACT , ENTROPIC_HOOK_ON_MODEL_LOAD , ENTROPIC_HOOK_ON_MODEL_UNLOAD , ENTROPIC_HOOK_ON_PERMISSION_CHECK ,
  ENTROPIC_HOOK_ON_ADAPTER_SWAP , ENTROPIC_HOOK_ON_VRAM_PRESSURE , ENTROPIC_HOOK_ON_DIRECTIVE , ENTROPIC_HOOK_ON_CUSTOM_DIRECTIVE ,
  ENTROPIC_HOOK_ON_LOOP_START , ENTROPIC_HOOK_ON_LOOP_END , ENTROPIC_HOOK_ON_COMPLETE = 22 , ENTROPIC_HOOK_PRE_MCP_SERVER_CONNECT = 23 ,
  ENTROPIC_HOOK_COUNT_
}
 Hook points in the engine lifecycle. More...
 

Detailed Description

Hook point enum and callback types for engine lifecycle hooks.

Consumers register callbacks at hook points to intercept, modify, inspect, and transform engine behavior without forking. Pre-hooks can modify context or cancel operations. Post-hooks can transform results. Failing hooks are logged and skipped — never crash the engine.

Version
2.0.6-rc16

Definition in file hooks.h.

Typedef Documentation

◆ entropic_hook_callback_t

typedef int(* entropic_hook_callback_t) (entropic_hook_point_t hook_point, const char *context_json, char **modified_json, void *user_data)

Hook callback function type.

Pre-hook semantics:

  • Return 0 + *modified_json == NULL: proceed unchanged
  • Return 0 + *modified_json != NULL: proceed with modified context
  • Return non-zero: cancel the operation

Post-hook semantics:

  • Return value ignored (post-hooks cannot cancel)
  • *modified_json != NULL: transform the result
  • *modified_json == NULL: no transformation

For POST_TOOL_CALL specifically (since v2.1.1, issue #2): the engine treats *modified_json as the replacement string for the tool result's Message::content — NOT as a JSON context object to be deconstructed. Mirrors POST_GENERATE's "raw text in / raw text out" semantic. Hook authors wanting to inspect the structured pre-hook context (tool_name, args, raw result, directives, result_kind) read those from the input context_json; the output is just the replacement content. When multiple POST_TOOL_CALL hooks are registered, last-write-wins per registry semantics — each hook receives the same context_json; the final *modified_json (whichever hook wrote it last) is what the engine applies. Pre-2.1.1 the engine called free() on *modified_json without applying the transform — silently breaking redaction/enrichment/normalization hooks.

For PRE_TOOL_CALL specifically (since v2.13.0, gh#168): a proceed (return 0) that writes *modified_json rewrites the ARGUMENTS of the call about to be dispatched. The payload is an OBJECT of the same shape the hook received, and only args is read:

{ "tool_name": "<must equal the call's own name, or be omitted>",
"args": { ... the complete replacement argument object ... } }

args REPLACES the call's arguments wholesale — a hook that means to add one field echoes back the others it read from context_json. The engine refuses, loudly and in full, any payload that is not valid JSON, is not an object, carries no args object, or names a different tool: a hook may enrich a call, never re-route it past per-tier allowed_tools. A refusal logs at ERROR with the reason and the verbatim payload and dispatches the call with the model's own arguments; it does NOT cancel, because cancellation has exactly one channel (a non-zero return). Bytes crossing in are sanitized to valid UTF-8 before parsing. Pre-2.13.0 the engine called free() on *modified_json without applying it, so no PRE_TOOL_CALL hook could ever change a call — the defect that closed gh#168.

The engine frees *modified_json after consuming it. The callback MUST allocate it with entropic_alloc() (not malloc, not new, not stack).

Parameters
hook_pointWhich hook point fired.
context_jsonJSON string with hook-specific context data. Owned by the engine, valid only for this call.
modified_jsonOutput: replacement JSON, or NULL for no change. Allocated by callback with entropic_alloc(), freed by engine.
user_dataOpaque pointer from registration.
Returns
0 to continue, non-zero to cancel (pre-hooks only).

@callback

Version
2.1.1

Definition at line 188 of file hooks.h.

Enumeration Type Documentation

◆ entropic_hook_point_t

Hook points in the engine lifecycle.

Each value identifies a stage where registered callbacks are invoked. Pre-hooks can cancel the operation by returning non-zero. Post-hooks can transform results via the modified_json out-param. Informational hooks fire for observation only.

New values are appended only — no renumbering (ABI stable).

The trailing ENTROPIC_HOOK_COUNT_ sentinel is NOT a valid hook point: it bounds registry validation and pins the declared cardinality.

@req REQ-TYPE-002 @req REQ-TYPE-004

Version
2.0.6-rc16
Enumerator
ENTROPIC_HOOK_PRE_GENERATE 

0: Before inference generate call

ENTROPIC_HOOK_POST_GENERATE 

1: After inference generate returns

ENTROPIC_HOOK_ON_STREAM_TOKEN 

2: Each streaming token emitted

ENTROPIC_HOOK_PRE_TOOL_CALL 

3: Before tool execution

ENTROPIC_HOOK_POST_TOOL_CALL 

4: After tool execution returns

ENTROPIC_HOOK_ON_LOOP_ITERATION 

5: Each agentic loop iteration

ENTROPIC_HOOK_ON_STATE_CHANGE 

6: Engine state machine transition

ENTROPIC_HOOK_ON_ERROR 

7: Async error occurred

ENTROPIC_HOOK_ON_DELEGATE 

8: Delegation to child tier started

ENTROPIC_HOOK_ON_DELEGATE_COMPLETE 

9: Child delegation completed

ENTROPIC_HOOK_ON_CONTEXT_ASSEMBLE 

10: Context window assembled

ENTROPIC_HOOK_ON_PRE_COMPACT 

11: Before context compaction

ENTROPIC_HOOK_ON_POST_COMPACT 

12: After context compaction

ENTROPIC_HOOK_ON_MODEL_LOAD 

13: Model loaded into backend

ENTROPIC_HOOK_ON_MODEL_UNLOAD 

14: Model unloaded from backend

ENTROPIC_HOOK_ON_PERMISSION_CHECK 

15: Permission check evaluated

ENTROPIC_HOOK_ON_ADAPTER_SWAP 

16: Adapter/LoRA swap requested

ENTROPIC_HOOK_ON_VRAM_PRESSURE 

17: VRAM pressure detected

ENTROPIC_HOOK_ON_DIRECTIVE 

18: Before processing a directive

ENTROPIC_HOOK_ON_CUSTOM_DIRECTIVE 

19: Unrecognized directive type

ENTROPIC_HOOK_ON_LOOP_START 

20: Agentic loop entry

ENTROPIC_HOOK_ON_LOOP_END 

21: Agentic loop exit

ENTROPIC_HOOK_ON_COMPLETE 

entropic.complete MCP tool called — pre-hook, can cancel.

Fires before the engine accepts a completion from the active tier. Non-zero return rejects the completion and injects the modified_json string back as a user message (citation validation feedback loop).

Guaranteed context_json schema (all fields always present):

{
"summary": "<complete text from the tool call>",
"tier": "<active tier name, e.g. \"lead\">",
"iteration": <loop iteration count at call time, integer>,
"tool_results": [
{ "name": "<tool_name>", "content": "<result text>" },
...
]
}

modified_json (rejection path): plain text feedback string, wrapped by the engine as "[CITATION VALIDATION] <text>" user message.

Version
2.0.6-rc16
ENTROPIC_HOOK_PRE_MCP_SERVER_CONNECT 

A discovered .mcp.json server is about to be launched (v2.14.0).

Fires once per discovered entry that config has neither disabled nor pre-approved (mcp.disabled_mcpjson_servers, mcp.enabled_mcpjson_servers, mcp.enable_all_project_mcp_servers). Return 0 to connect it, non-zero to refuse.

Fail-closed, unlike every other pre-hook: when NO handler is registered at this point the server is NOT connected. For other pre-hooks "nobody objected" means proceed; here it would mean a repository's .mcp.json launches processes on the host by default (gh#199), so silence is a refusal. Servers declared in mcp.external_servers never reach this hook — the operator declared them.

context_json:

{"name": "probe", "transport": "stdio", "command": "/bin/sh",
"args": ["-c", "..."], "url": "", "root": "/path/the/server/runs/in"}

modified_json is ignored: this hook approves or refuses, it does not rewrite what gets launched.

Version
2.14.0
ENTROPIC_HOOK_COUNT_ 

Sentinel — not a valid hook point.

Definition at line 39 of file hooks.h.