Skip to main content

OpenClaw + AxonFlow

AxonFlow adds policy enforcement, approval gates, and audit trails to OpenClaw.

OpenClaw is strong at agent runtime, tool execution, MCP connectivity, and channel integrations. AxonFlow complements it with production governance controls: inspect tool inputs before execution, scan outbound messages before delivery, and record tool + LLM activity for review, security, and compliance.

Prerequisites: OpenClaw 1.0+, AxonFlow running (Getting Started)

What This Integration Covers Today

  • Tool input governance before execution
  • Human approval for selected high-risk tools
  • Outbound message scanning for PII and secrets
  • Audit logging for tool calls and LLM activity

Current Limitation

Tool-result transcript scanning is not yet available. OpenClaw's current tool_result_persist hook is sync-only, so the plugin cannot call AxonFlow asynchronously at that point in the lifecycle. If OpenClaw adds async support there, AxonFlow can add transcript/result scanning immediately.


Quick Start

Install the plugin and add governance to your OpenClaw agent in five lines:

openclaw plugins install @axonflow/openclaw
# openclaw.config.yaml
plugins:
@axonflow/openclaw:
endpoint: http://localhost:8080
clientId: your-client-id
clientSecret: your-secret

That's it. Every tool call now flows through AxonFlow policy enforcement.


What OpenClaw Does Well

OpenClaw is an AI agent gateway for messaging platforms and enterprise chat systems. It provides the runtime layer between users and AI agents, handling tool execution, message routing, and channel connectivity:

AI Agent Gateway: Central control plane for deploying AI agents across messaging platforms. Agents register tools, and OpenClaw handles routing user requests to the right tool.

2800+ Community Skills via ClawHub: A marketplace of pre-built skills covering web search, code execution, file management, database queries, and more. Install a skill and your agent can use it immediately.

MCP Runtime: Native Model Context Protocol support for connecting agents to external data sources and APIs. OpenClaw manages MCP server lifecycle, connection pooling, and request multiplexing.

Built-in Safety Controls: Tool allow/deny lists, execution approval prompts, and SecretRef for credential management. These controls handle the "should this tool run at all" question at the agent level.

Multi-Channel Deployment: Single agent definition, deployed across Telegram, Discord, WhatsApp, Slack, and custom webhooks. Channel-specific formatting handled automatically.

Extensible Plugin Architecture: Lifecycle hooks for every stage of tool execution. Plugins can intercept, modify, or block tool calls at before_tool_call, tool_result_persist, and after_tool_call.


What OpenClaw Doesn't Try to Solve

OpenClaw focuses on agent deployment and tool execution. These concerns are explicitly out of scope:

Production RequirementOpenClaw's Position
Centralized policy enforcement across toolsNot provided. Tool allow/deny is per-agent, not org-wide
PII detection in tool arguments and resultsNot addressed. Tool inputs and outputs pass through unchanged
Audit trails with decision contextProvides execution logs. Not structured for compliance queries
Cross-tool rate limiting and budgetsNot tracked. Each tool executes independently with no cost awareness
Enterprise compliance evidenceBasic logging. Not designed for regulatory evidence packs
Content filtering on LLM responsesNot provided. Agents return LLM output directly to users

This isn't a criticism. OpenClaw handles agent deployment and tool orchestration. Governance is a separate concern.


Where Teams Hit Production Friction

Based on real enterprise deployments, here are the blockers that appear after the prototype works:

1. The Tool That Phones Home

A web_fetch skill is installed from ClawHub. An agent uses it to look up product documentation. Then a user asks: "Summarize my customer list." The agent calls web_fetch with a URL containing customer names and email addresses in query parameters. The data leaves your infrastructure.

OpenClaw executed the tool correctly. The allow/deny list approved web_fetch as a permitted tool. Nobody checked what the tool was sending.

2. The MCP Response Full of PII

An MCP connector queries your CRM database. The agent asked for "recent support tickets." The MCP server returns 50 tickets, each with customer name, email, phone number, and account details. All of it flows into the LLM context window.

OpenClaw managed the MCP connection. SecretRef handled the database credentials securely. The data itself was never inspected.

3. The Compliance Question Nobody Can Answer

Six months after deployment, a regulator asks: "For this customer interaction on March 14, which tools were called, what data did they access, what policies were in effect, and why was the agent's response allowed?"

OpenClaw has execution logs. They show the tool was called and it succeeded. The decision context (why it was allowed, what policies applied, whether PII was present) does not exist.


How AxonFlow Plugs In

AxonFlow integrates with OpenClaw through its plugin architecture. The @axonflow/openclaw registers five lifecycle hooks covering tool inputs, outbound messages, and LLM audit:

┌──────────────────────────────────────────────────────────────┐
│ OpenClaw Agent │
│ │
│ User Message → LLM Call → Tool Execution → Response → User │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ @axonflow/openclaw │ │
│ │ │ │
│ │ GOVERNANCE (can block/modify): │ │
│ │ before_tool_call (priority 10) → mcp_check_input │ │
│ │ message_sending (priority 10) → mcp_check_output │ │
│ │ │ │
│ │ AUDIT (observe-only): │ │
│ │ after_tool_call (priority 90) → audit_tool_call │ │
│ │ llm_input (priority 90) → record prompt │ │
│ │ llm_output (priority 90) → audit/tool-call │ │
│ └─────────────────────────┬─────────────────────────────┘ │
│ │ │
└─────────────────────────────┼────────────────────────────────┘


┌───────────────────┐
│ AxonFlow │
│ ┌─────┐ ┌─────┐ │
│ │Policy│ │Audit│ │
│ │Engine│ │Trail│ │
│ └─────┘ └─────┘ │
│ ┌─────┐ │
│ │ PII │ │
│ │Scan │ │
│ └─────┘ │
└───────────────────┘

What this gives you:

  • Every tool call policy-checked before execution, with arguments inspected for PII and injection
  • Every outbound message scanned for PII/secrets before delivery to Telegram/Discord/Slack
  • Every execution audited with tool name, arguments, result summary, and applied policies
  • Approval workflows triggered for high-risk tools, with the agent pausing until a human approves

What stays the same:

  • Your OpenClaw agent configuration is unchanged
  • ClawHub skills work without modification
  • MCP connectors run as before
  • Channel integrations are unaffected

Plugin Installation and Configuration

Install the plugin using OpenClaw's plugin manager:

openclaw plugins install @axonflow/openclaw

Add it to your OpenClaw configuration:

# openclaw.config.yaml
plugins:
@axonflow/openclaw:
# Required: AxonFlow agent gateway URL
endpoint: http://localhost:8080

# Required: AxonFlow credentials
clientId: openclaw-agent-01
clientSecret: your-client-secret

# Optional: tools that require human approval even when policy allows
highRiskTools:
- web_fetch
- message
- execute_sql

# Optional: only govern these tools (empty = all tools governed)
governedTools: []

# Optional: exclude these from governance (takes precedence over governedTools)
excludedTools:
- get_current_time
- list_models

# Optional: operation type for mcp_check_input ("execute" or "query")
defaultOperation: execute

Configuration Reference

FieldTypeDefaultDescription
endpointstringrequiredAxonFlow agent gateway URL
clientIdstringrequiredClient ID for Basic auth
clientSecretstringrequiredClient secret for Basic auth
highRiskToolsstring[][]Tools requiring human approval even when policy allows
governedToolsstring[][]Only govern these tools (empty = all)
excludedToolsstring[][]Exclude from governance (takes precedence over governedTools)
defaultOperationstring"execute"Operation type sent to mcp_check_input ("execute" or "query")
onErrorstring"block"Behavior when AxonFlow is unreachable: "block" (fail-closed) or "allow" (fail-open)
defaultOperationstring"execute"Operation type sent to mcp_check_input ("execute" or "query")

Tool Filtering Logic

The plugin uses a three-level filter to decide whether to govern a tool:

  1. If the tool is in excludedTools, skip governance (always takes precedence)
  2. If governedTools is non-empty and the tool is not in it, skip governance
  3. Otherwise, govern the tool

This means you can either allowlist specific tools (governedTools) or blocklist specific tools (excludedTools), but excludedTools always wins if both are set.


Integration Pattern

The plugin hooks into OpenClaw's lifecycle at five points. Here is how each hook works, matching the actual implementation.

Hook 1: before_tool_call (Priority 10)

When OpenClaw selects a tool to execute, the plugin intercepts the call before it runs. The hook receives the tool name and parameters, calls AxonFlow's mcp_check_input endpoint, and returns a decision.

// Receives from OpenClaw:
interface BeforeToolCallEvent {
toolName: string;
params: Record<string, unknown>;
runId?: string;
toolCallId?: string;
}

// The plugin:
// 1. Checks shouldGovernTool(toolName, config)
// 2. Derives connectorType = "openclaw.{toolName}"
// 3. Calls POST /api/v1/mcp/check-input with:
// { connector_type, statement: JSON.stringify(params), operation }
// 4. Returns one of three outcomes:

// BLOCKED by policy:
{ block: true, blockReason: "Blocked by AxonFlow policy" }

// REQUIRES APPROVAL (tool is in highRiskTools AND policy allowed):
{
requireApproval: {
title: "AxonFlow: web_fetch requires approval",
description: "Tool call governed by AxonFlow. 3 policies evaluated.",
severity: "warning",
timeoutMs: 60000,
timeoutBehavior: "deny",
}
}

// ALLOWED:
undefined

When a tool is blocked, OpenClaw skips execution and returns the block reason to the LLM as a tool error. When approval is required, OpenClaw pauses and posts an approval request to the configured channel.

Note that highRiskTools is evaluated after the policy check. If AxonFlow blocks the tool, it stays blocked regardless of the highRiskTools list. The approval gate only fires when AxonFlow allows the tool but the tool is in highRiskTools.

Tool Result Scanning — Pending Upstream Support

OpenClaw's tool_result_persist hook is synchronous, which means it cannot make async HTTP calls to AxonFlow for output policy evaluation. Tool results written to the session transcript are not currently scanned by this plugin.

What IS protected: Tool inputs are governed before execution, and outbound messages are scanned before delivery to users. What is NOT protected: Tool results entering the LLM context window. PII in tool results will be caught by message_sending before reaching the end user, but it will be visible to the LLM.

We have requested async support upstream. When available, this plugin will add output scanning.

Hook 2: after_tool_call (Priority 90)

After tool execution completes (whether it succeeded, failed, was blocked, or had output redacted), the plugin logs the execution to AxonFlow's audit trail. This is fire-and-forget: audit failures never block tool execution.

// Receives from OpenClaw:
interface AfterToolCallEvent {
toolName: string;
params: Record<string, unknown>;
runId?: string;
toolCallId?: string;
result?: unknown;
error?: string;
durationMs?: number;
}

// The plugin calls POST /api/v1/audit/tool-call with:
{
tool_name: "web_fetch",
tool_type: "openclaw",
input: { url: "https://example.com/api" },
output: { result: "<truncated to 500 chars>" },
success: true,
error_message: undefined,
duration_ms: 342,
}

The output field truncates result data to 500 characters to keep audit payloads reasonable. The tool_type is always "openclaw" for connector attribution. If the audit call fails (network error, AxonFlow down), the error is silently caught. Governance was already enforced in the before_tool_call hook.


Connector Type Naming

AxonFlow uses connector types to identify the source of tool calls in audit logs and policy rules. The OpenClaw plugin uses the format openclaw.{toolName}:

OpenClaw ToolAxonFlow Connector TypeExample Policy Target
web_fetchopenclaw.web_fetchBlock external URLs containing PII
execute_sqlopenclaw.execute_sqlRequire approval for all SQL execution
read_fileopenclaw.read_fileRestrict to allowed directories
send_emailopenclaw.send_emailBlock when recipient count > 100
slack_postopenclaw.slack_postScan message content for sensitive data
search_crmopenclaw.search_crmScan CRM query arguments for sensitive data

All tools (built-in, plugin-provided, and MCP-backed) use the same openclaw.{toolName} convention. The connector type is derived directly from the tool name as registered in OpenClaw.

Policy Examples Using Connector Types

# Block web_fetch from sending data to non-approved domains
- name: "restrict-web-fetch-domains"
connector_type: "openclaw.web_fetch"
condition: "url NOT MATCHES '^https://(docs\\.internal\\.com|api\\.approved\\.com)'"
action: "block"

# Require approval for any SQL execution
- name: "approve-sql-execution"
connector_type: "openclaw.execute_sql"
action: "require_approval"

# Redact PII in outbound messages (message_sending hook)
- name: "outbound-pii-redact"
connector_type: "openclaw.message_sending"
check_output: true
pii_action: "redact"

Starter Policies

The plugin repository includes research-backed starter policies addressing the top 10 OpenClaw security risks, based on real-world incidents including CVE-2026-25253, CVE-2026-33573, the ClawHavoc supply chain attack, and security research from Microsoft, Kaspersky, Cisco, and Giskard:

  • Reverse shell blocking: Detect and block nc -e, bash -i, /dev/tcp/, curl | sh, and other remote code execution patterns in exec tool arguments (Risk 1, CVE-2026-25253 vector)
  • Data exfiltration prevention: Block requests to cloud metadata endpoints (169.254.169.254) and internal networks for SSRF protection (Risk 2)
  • PII/secrets redaction in outbound messages: Automatically detect and redact SSNs, credit cards, API keys, and connection strings before delivery to users via AxonFlow's 76+ system policies (Risk 3)
  • Prompt injection detection: Scan ingested content for injection patterns before it enters the LLM context (Risk 4)
  • Outbound message scanning: Detect PII and secrets in messages before delivery to Telegram, Discord, or Slack channels (Risk 5)
  • Agent config file protection: Block writes to SOUL.md, MEMORY.md, and other OpenClaw identity files to prevent memory poisoning attacks (Risk 7)
  • Path traversal blocking: Detect ../, /etc/passwd, and other escape patterns that exploit workspace boundary bypass (Risk 10, CVE-2026-33573 vector)
  • Credential access blocking: Block cat ~/.ssh/, cat ~/.aws/, printenv SECRET, and similar credential exfiltration attempts (Risk 8)

See the policies directory in the plugin repository for ready-to-use SQL INSERT statements and configuration instructions.


Approval Workflow Integration

When a tool is in the highRiskTools list and AxonFlow allows the call, the plugin returns a requireApproval response to OpenClaw. OpenClaw's native approval mechanism takes over from there, pausing tool execution and notifying the configured approval channel:

User: "Delete all inactive customer records from the database"


Agent selects: execute_sql


Plugin: before_tool_call → POST /api/v1/mcp/check-input

├─ AxonFlow blocks → { block: true } → Agent receives block reason

└─ AxonFlow allows + tool in highRiskTools →


Plugin returns: { requireApproval: { title, description, severity } }


OpenClaw: Pauses execution, posts approval request to channel

├─ Approve → Tool executes → Audit logged
└─ Reject → Agent receives rejection → Audit logged
└─ Timeout (60s) → Denied (timeoutBehavior: "deny")

The approval request includes the tool name and a description noting how many AxonFlow policies were evaluated. The timeout defaults to 60 seconds with a "deny" behavior, meaning unanswered approval requests are rejected.


AxonFlow API Endpoints Used

The plugin calls three AxonFlow endpoints. All requests use Basic auth (base64(clientId:clientSecret)):

EndpointHookPurpose
POST /api/v1/mcp/check-inputbefore_tool_callEvaluate tool arguments against policies
POST /api/v1/mcp/check-outputmessage_sendingScan outbound messages for PII and policy violations
POST /api/v1/audit/tool-callafter_tool_call, llm_outputRecord tool/LLM execution in audit trail

HTTP 403 from check-input and check-output is treated as a policy block (not an auth error). The response body is deserialized normally to extract the block reason and policy count.


Error Handling

The plugin supports configurable fail-open/fail-closed behavior via the onError option:

plugins:
@axonflow/openclaw:
onError: block # "block" (fail-closed) or "allow" (fail-open)
  • onError: block (recommended for production): If AxonFlow is unreachable, tool calls are blocked. This is the safer default for security-sensitive deployments.
  • onError: allow: If AxonFlow is unreachable, tool calls are allowed through ungoverned. Use this for development where AxonFlow availability is less critical.

How each hook behaves when AxonFlow is unreachable:

  • before_tool_call: Blocks tool execution (if onError: block) or allows through (if onError: allow).
  • message_sending: Cancels the outbound message (if onError: block) or allows through ungoverned (if onError: allow).
  • after_tool_call: Audit failures are silently caught regardless of onError. Governance was already enforced in the before_tool_call hook.

This means governance enforcement respects your fail-open/fail-closed preference, but audit logging is always best-effort.


OpenClaw Security References

SDKs: Python v5.3.0, Go/TypeScript/Java v4.3.0 | Platform: v5.4.1 | Plugin: v0.1.0