How It Works

Interception mechanism

The Faramesh plugin uses OpenClaw's before_tool_call hook to intercept every tool call before execution.

Hook registration

api.on("before_tool_call", async (event, ctx) => {
  // event.toolName — the tool being called
  // event.params — the parameters
  // ctx.agentId — the agent making the call
  // ctx.sessionKey — the session key

  const result = await checkFaramesh(event.toolName, event.params, ctx);

  if (result.blocked) {
    return { block: true, blockReason: result.reason };
  }
  return undefined; // allow
}, { priority: 1000 });
api.on("before_tool_call", async (event, ctx) => {
  // event.toolName — the tool being called
  // event.params — the parameters
  // ctx.agentId — the agent making the call
  // ctx.sessionKey — the session key

  const result = await checkFaramesh(event.toolName, event.params, ctx);

  if (result.blocked) {
    return { block: true, blockReason: result.reason };
  }
  return undefined; // allow
}, { priority: 1000 });
api.on("before_tool_call", async (event, ctx) => {
  // event.toolName — the tool being called
  // event.params — the parameters
  // ctx.agentId — the agent making the call
  // ctx.sessionKey — the session key

  const result = await checkFaramesh(event.toolName, event.params, ctx);

  if (result.blocked) {
    return { block: true, blockReason: result.reason };
  }
  return undefined; // allow
}, { priority: 1000 });

The hook runs at priority 1000, the highest priority, ensuring it runs before any other hooks.

Gateway bypass fix

OpenClaw has two tool execution paths:

  1. Agent-initiated: Tools called by the AI agent go through runBeforeToolCallHook → hooks run → tool executes.

  2. HTTP gateway: Tools called via the HTTP API (/tools/invoke) previously bypassed the hook system.

The Faramesh integration includes a fix that ensures the HTTP gateway also calls runBeforeToolCallHook (see tools-invoke-http.ts), so no tool call can bypass governance, whether from the agent or from direct HTTP invoke. Every action appears in the dashboard (Allowed / Denied / Pending) with full provenance. The integration is covered by a full E2E test suite, and the plugin implements retry behavior when the Faramesh server is temporarily unavailable (configurable).

Decision flow




Category resolution

Each tool is mapped to a category for simple policy evaluation:

Tool name

Category

bash, shell, exec, terminal

bash

read, write, edit, glob, grep

filesystem

browser, browser_navigate, browser_click

browser

web_fetch, web_search, http, curl

network

canvas, notebook

canvas

Everything else

other

The mapping happens both on the plugin side and the server side, using the same logic.

Fail-closed vs fail-open

Mode

When Faramesh is unreachable

fail-closed (default)

Tool call is blocked

fail-open

Tool call is allowed

Set fail_closed: false in the plugin configuration to use fail-open mode.

Data sent to Faramesh

Each tool call sends:

{
  "agent_id": "openclaw",
  "tool": "bash",
  "operation": "run",
  "params": { "command": "ls -la" },
  "context": {
    "session_key": "abc123",
    "source": "openclaw",
    "category": "bash",
    "runtime_id": "user@hostname"
  }
}
{
  "agent_id": "openclaw",
  "tool": "bash",
  "operation": "run",
  "params": { "command": "ls -la" },
  "context": {
    "session_key": "abc123",
    "source": "openclaw",
    "category": "bash",
    "runtime_id": "user@hostname"
  }
}
{
  "agent_id": "openclaw",
  "tool": "bash",
  "operation": "run",
  "params": { "command": "ls -la" },
  "context": {
    "session_key": "abc123",
    "source": "openclaw",
    "category": "bash",
    "runtime_id": "user@hostname"
  }
}

The runtime_id is automatically set to the current hostname, enabling fleet management across multiple machines.

Response handling

The plugin checks the response for three possible outcomes:

  • status: allowed or decision: allow or outcome: EXECUTE → tool runs

  • status: pending_approval or decision: require_approval or outcome: ABSTAIN → tool blocked, waiting for approval

  • status: denied or decision: deny or outcome: HALT → tool blocked permanently

Was this helpful?

Previous

More

Next

More

Table of content

Table of content

How It Works

How It Works