Documentation Index
Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
Use this file to discover all available pages before exploring further.
For the full guide, see Hooks.
Start here after you understand the normal session/tool flow. If you are new to Meerkat overall, read Examples: Sessions first.
Observer hook (background)
A post_tool_execution background hook that logs every tool call to a file. Background hooks run asynchronously and never block the agent loop.
CLI
JSON-RPC
REST
MCP
Python
TypeScript
Run-scoped hook override flags are not currently exposed on the normal rkat run surface. Use the JSON-RPC, REST, MCP, or SDK examples below for per-run hook override testing.
{
"jsonrpc": "2.0", "id": 1,
"method": "session/create",
"params": {
"prompt": "Summarize this repo",
"hooks_override": {
"entries": [{
"id": "audit-log",
"point": "post_tool_execution",
"mode": "background",
"capability": "observe",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/log_tool.py"]
},
"timeout_ms": 3000
}]
}
}
}
curl -X POST http://127.0.0.1:8080/sessions \
-H "Content-Type: application/json" \
-d '{
"prompt": "Summarize this repo",
"hooks_override": {
"entries": [{
"id": "audit-log",
"point": "post_tool_execution",
"mode": "background",
"capability": "observe",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/log_tool.py"]
},
"timeout_ms": 3000
}]
}
}'
{
"name": "meerkat_run",
"arguments": {
"prompt": "Summarize this repo",
"enable_builtins": true,
"hooks_override": {
"entries": [{
"id": "audit-log",
"point": "post_tool_execution",
"mode": "background",
"capability": "observe",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/log_tool.py"]
},
"timeout_ms": 3000
}]
}
}
}
result = await client.create_session(
"Summarize this repo",
hooks_override={
"entries": [{
"id": "audit-log",
"point": "post_tool_execution",
"mode": "background",
"capability": "observe",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/log_tool.py"],
},
"timeout_ms": 3000,
}]
},
)
const result = await client.createSession("Summarize this repo", {
hooksOverride: {
entries: [{
id: "audit-log",
point: "post_tool_execution",
mode: "background",
capability: "observe",
runtime: {
type: "command",
command: "python3",
args: ["hooks/log_tool.py"],
},
timeoutMs: 3000,
}],
},
});
Guardrail hook (foreground)
A pre_tool_execution foreground hook that must approve each tool call before it runs. If the hook returns deny, the tool call is skipped.
CLI
JSON-RPC
REST
MCP
Python
TypeScript
Run-scoped hook override flags are not currently exposed on the normal rkat run surface. Use the JSON-RPC, REST, MCP, or SDK examples below for per-run hook override testing.
{
"jsonrpc": "2.0", "id": 1,
"method": "session/create",
"params": {
"prompt": "Delete old logs",
"hooks_override": {
"entries": [{
"id": "safety-gate",
"point": "pre_tool_execution",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/approve_tool.py"]
},
"timeout_ms": 5000
}]
}
}
}
curl -X POST http://127.0.0.1:8080/sessions \
-H "Content-Type: application/json" \
-d '{
"prompt": "Delete old logs",
"hooks_override": {
"entries": [{
"id": "safety-gate",
"point": "pre_tool_execution",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/approve_tool.py"]
},
"timeout_ms": 5000
}]
}
}'
{
"name": "meerkat_run",
"arguments": {
"prompt": "Delete old logs",
"enable_builtins": true,
"hooks_override": {
"entries": [{
"id": "safety-gate",
"point": "pre_tool_execution",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/approve_tool.py"]
},
"timeout_ms": 5000
}]
}
}
}
result = await client.create_session(
"Delete old logs",
hooks_override={
"entries": [{
"id": "safety-gate",
"point": "pre_tool_execution",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "command",
"command": "python3",
"args": ["hooks/approve_tool.py"],
},
"timeout_ms": 5000,
}]
},
)
const result = await client.createSession("Delete old logs", {
hooksOverride: {
entries: [{
id: "safety-gate",
point: "pre_tool_execution",
mode: "foreground",
capability: "guardrail",
runtime: {
type: "command",
command: "python3",
args: ["hooks/approve_tool.py"],
},
timeoutMs: 5000,
}],
},
});
In-process hook (Rust only)
Register a Rust closure directly — no subprocess, no serialization overhead. Only available in the Rust SDK.
let engine = DefaultHookEngine::new(hooks_config)
.with_in_process_handler(
"pii-guard",
Arc::new(|invocation| Box::pin(async move {
let text = invocation.tool_call.as_ref()
.map(|call| call.args.as_value().to_string()).unwrap_or_default();
let decision = if contains_pii(&text) {
Some(HookDecision::deny(
HookId::new("pii-guard"),
HookReasonCode::PolicyViolation,
"tool arguments contain PII",
None,
))
} else {
None
};
Ok(RuntimeHookResponse {
decision,
..Default::default()
})
})),
);
Hooks receive typed projections of the request, response, tool call, and tool result. They can allow, deny, or observe those facts; they cannot rewrite canonical LLM, tool, or run output.
let engine = DefaultHookEngine::new(hooks_config)
.with_in_process_handler(
"tool-audit",
Arc::new(|invocation| Box::pin(async move {
let content = invocation.tool_result.as_ref()
.map(|r| r.content.as_str()).unwrap_or("");
audit_tool_result(content).await;
Ok(RuntimeHookResponse {
..Default::default()
})
})),
);
HTTP hook
A hook that POSTs the invocation payload to a remote URL. Useful for centralized policy servers.
CLI
JSON-RPC
REST
MCP
Python
TypeScript
Run-scoped hook override flags are not currently exposed on the normal rkat run surface. Use the JSON-RPC, REST, MCP, or SDK examples below for per-run hook override testing.
{
"jsonrpc": "2.0", "id": 1,
"method": "session/create",
"params": {
"prompt": "Analyze quarterly data",
"hooks_override": {
"entries": [{
"id": "policy-server",
"point": "pre_llm_request",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "http",
"url": "https://hooks.example.com/policy",
"method": "POST"
},
"timeout_ms": 10000
}]
}
}
}
curl -X POST http://127.0.0.1:8080/sessions \
-H "Content-Type: application/json" \
-d '{
"prompt": "Analyze quarterly data",
"hooks_override": {
"entries": [{
"id": "policy-server",
"point": "pre_llm_request",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "http",
"url": "https://hooks.example.com/policy",
"method": "POST"
},
"timeout_ms": 10000
}]
}
}'
{
"name": "meerkat_run",
"arguments": {
"prompt": "Analyze quarterly data",
"enable_builtins": true,
"hooks_override": {
"entries": [{
"id": "policy-server",
"point": "pre_llm_request",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "http",
"url": "https://hooks.example.com/policy",
"method": "POST"
},
"timeout_ms": 10000
}]
}
}
}
result = await client.create_session(
"Analyze quarterly data",
hooks_override={
"entries": [{
"id": "policy-server",
"point": "pre_llm_request",
"mode": "foreground",
"capability": "guardrail",
"runtime": {
"type": "http",
"url": "https://hooks.example.com/policy",
"method": "POST",
},
"timeout_ms": 10000,
}]
},
)
const result = await client.createSession("Analyze quarterly data", {
hooksOverride: {
entries: [{
id: "policy-server",
point: "pre_llm_request",
mode: "foreground",
capability: "guardrail",
runtime: {
type: "http",
url: "https://hooks.example.com/policy",
method: "POST",
},
timeoutMs: 10000,
}],
},
});
All 8 hook points
| Hook point | Classification | When it fires |
|---|
run_started | pre | Start of Agent::run(), before any LLM call |
pre_llm_request | pre | Before each LLM streaming call |
pre_tool_execution | pre | Before each individual tool call is dispatched |
turn_boundary | pre | Between turns, after all tool results are collected |
post_llm_response | post | After the LLM response is received |
post_tool_execution | post | After each tool execution completes |
run_completed | post | After a successful run completes |
run_failed | post | After a run fails with an error |
Pre-point hooks in foreground mode halt the agent loop until they return. Pre-point hooks in background mode are limited to observe-only capability.
Disable a hook
Use the disable list to turn off hooks defined in the realm config without removing them.
CLI
JSON-RPC
REST
MCP
Python
TypeScript
Run-scoped hook override flags are not currently exposed on the normal rkat run surface. Use JSON-RPC, REST, MCP, or SDK/embedded surfaces for per-run hook override testing.
{
"jsonrpc": "2.0", "id": 1,
"method": "session/create",
"params": {
"prompt": "Quick test",
"hooks_override": {
"disable": ["safety-gate", "audit-log"]
}
}
}
curl -X POST http://127.0.0.1:8080/sessions \
-H "Content-Type: application/json" \
-d '{
"prompt": "Quick test",
"hooks_override": {
"disable": ["safety-gate", "audit-log"]
}
}'
{
"name": "meerkat_run",
"arguments": {
"prompt": "Quick test",
"enable_builtins": true,
"hooks_override": {
"disable": ["safety-gate", "audit-log"]
}
}
}
result = await client.create_session(
"Quick test",
hooks_override={
"disable": ["safety-gate", "audit-log"]
},
)
const result = await client.createSession("Quick test", {
hooksOverride: {
disable: ["safety-gate", "audit-log"],
},
});
Hook events
Hooks emit events into the session event stream. Subscribe to these to build dashboards, alerting, or audit trails.
// HookStarted -- emitted when a hook begins execution
{"type": "hook_started", "hook_id": "safety-gate", "point": "pre_tool_execution"}
// HookCompleted -- emitted when a hook finishes successfully
{"type": "hook_completed", "hook_id": "safety-gate", "point": "pre_tool_execution", "duration_ms": 42}
// HookDenied -- emitted when a hook blocks execution
{"type": "hook_denied", "hook_id": "safety-gate", "point": "pre_tool_execution", "reason_code": "policy_violation", "message": "rm -rf not allowed"}
// HookFailed -- emitted when a hook errors or times out
{"type": "hook_failed", "hook_id": "audit-log", "point": "post_tool_execution", "error": "process exited with code 1"}
Next step