Skip to main content

Claude Code + AxonFlow Integration

How to use this doc:

  • Understanding the problem? Read sections 1–3
  • Ready to implement? Jump to Integration Pattern

What Claude Code Does Well

Claude Code is Anthropic's official CLI for Claude—an agentic coding assistant that operates directly in your terminal. Its strengths are substantial:

Agentic Coding: Claude understands your codebase, makes edits, runs commands, and iterates on feedback. Natural language to working code.

Tool Execution: Built-in tools for file operations, bash commands, web fetching, and more. Extended via MCP servers for databases, APIs, and enterprise systems.

Lifecycle Hooks: Pre and post hooks for tool calls, notifications, and custom integrations. Control what happens before and after tool execution.

Context Awareness: Understands project structure through CLAUDE.md files and codebase exploration. Maintains context across sessions.

MCP Integration: Connect to external data sources via Model Context Protocol servers. Query databases, call APIs, access enterprise systems.

Local Execution: Runs entirely in your terminal. No cloud dependency for core functionality.


What Claude Code Doesn't Provide

Claude Code focuses on developer productivity. These concerns are explicitly out of scope:

Production RequirementClaude Code's Position
Policy enforcement before tool executionHooks available—governance logic not provided
PII detection in queries/responsesNot addressed—developer responsibility
Audit trails for complianceSession logs exist—not compliance-formatted
SQL injection preventionNot provided—MCP servers handle their own security
Per-user/team cost controlsNot provided—usage is per-account
Data residency enforcementNot addressed—follows Anthropic API routing
Multi-tenant isolationNot applicable—single-user tool

This isn't a criticism—it's a design choice. Claude Code is a developer productivity tool. Enterprise governance is a separate concern.


Where Teams Hit Production Friction

Based on real enterprise deployments, here are the blockers that appear when Claude Code moves beyond individual developer use:

1. The MCP Data Exposure

A developer configures an MCP server connected to production databases. Claude Code queries customer records as part of debugging. The query results—including PII—flow through the conversation. No filtering, no audit.

2. The "What Did It Access?" Question

Security asks:

  • What database queries did Claude Code execute?
  • What data was returned?
  • Was any PII included in prompts?
  • What commands were run?

Session logs exist but aren't formatted for compliance audits.

3. The Accidental Production Change

Claude Code has bash access. A developer asks it to "fix the database issue." It runs a command that modifies production data. The command was allowed—there was no policy preventing it.

4. The Security Review Block

Security review: BLOCKED
- No policy enforcement on MCP queries
- PII can flow through conversations unchecked
- Bash commands not governed
- Audit trail not compliance-ready
- No approval gates for sensitive operations

Claude Code works perfectly for development. Governance gaps block production use.


How AxonFlow Plugs In

AxonFlow integrates with Claude Code through lifecycle hooks—the same mechanism Claude Code uses for custom integrations. AxonFlow provides the governance layer:

Claude Code → Pre-Hook → AxonFlow Policy Check → Tool Execution

Claude Code ← Post-Hook ← AxonFlow Audit ← Tool Result

What AxonFlow adds:

  • Policy enforcement before tool execution
  • PII detection and redaction in queries and responses
  • SQL injection prevention for MCP database queries
  • Compliance-ready audit trails
  • Approval gates for sensitive operations

Integration Pattern

Configure Claude Code to call AxonFlow before sensitive tool operations:

# ~/.claude/hooks/pre-tool.sh
#!/bin/bash

TOOL_NAME="$1"
TOOL_INPUT="$2"

# Tools that require governance
GOVERNED_TOOLS=("Bash" "mcp__postgres" "mcp__mysql" "mcp__mongodb" "Write" "Edit")

if [[ " ${GOVERNED_TOOLS[*]} " =~ " ${TOOL_NAME} " ]]; then
# Call AxonFlow policy check
RESULT=$(curl -s -X POST http://localhost:8080/api/policy/pre-check \
-H "Content-Type: application/json" \
-d "{
\"user_token\": \"$(whoami)\",
\"client_id\": \"claude-code\",
\"query\": \"$TOOL_INPUT\",
\"context\": {\"tool\": \"$TOOL_NAME\"}
}")

APPROVED=$(echo "$RESULT" | jq -r '.approved')

if [ "$APPROVED" != "true" ]; then
REASON=$(echo "$RESULT" | jq -r '.block_reason // "Policy violation"')
echo "❌ BLOCKED: $REASON" >&2
exit 1
fi

# Check for PII that requires redaction
REQUIRES_REDACTION=$(echo "$RESULT" | jq -r '.requires_redaction // false')
if [ "$REQUIRES_REDACTION" == "true" ]; then
POLICIES=$(echo "$RESULT" | jq -r '.policies | join(", ")')
echo "⚠️ Redaction required (policies: $POLICIES)" >&2
fi
fi

exit 0

Option 2: MCP Gateway Mode

Instead of configuring MCP servers directly in Claude Code, route database queries through AxonFlow's MCP connectors. This provides automatic governance for all database operations.

Setup:

  1. Configure the database connector in AxonFlow (see MCP Connectors)
  2. Use the AxonFlow MCP query endpoint from your hook:
# In your pre-tool hook, route MCP queries through AxonFlow
curl -X POST http://localhost:8080/api/v1/mcp/query \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-d '{
"connector": "postgres",
"operation": "query",
"statement": "SELECT * FROM orders WHERE customer_id = 123",
"user_token": "developer"
}'

With this approach:

  • All database queries flow through AxonFlow's policy engine
  • SQL injection patterns are blocked automatically
  • PII in responses is detected and optionally redacted
  • Every query is logged to mcp_query_audits

Option 3: SDK Integration (Custom Hooks)

For more control, use the AxonFlow SDK in custom hook scripts:

#!/usr/bin/env python3
# ~/.claude/hooks/pre-tool.py

import sys
from axonflow import AxonFlow

def main():
tool_name = sys.argv[1]
tool_input = sys.argv[2] if len(sys.argv) > 2 else ""

with AxonFlow.sync(
endpoint="http://localhost:8080",
client_id="claude-code",
client_secret="your-secret"
) as client:
ctx = client.get_policy_approved_context(
user_token="developer",
query=tool_input,
context={"tool": tool_name, "source": "claude-code"}
)

if not ctx.approved:
print(f"❌ BLOCKED: {ctx.block_reason}", file=sys.stderr)
sys.exit(1)

if ctx.requires_redaction:
print(f"⚠️ Redaction required (policies: {', '.join(ctx.policies)})", file=sys.stderr)

if __name__ == "__main__":
main()

Configuration

Enable Hooks in Claude Code

Claude Code supports lifecycle hooks via the settings file. Configure hooks in ~/.claude/settings.json:

{
"hooks": {
"preToolCall": "~/.claude/hooks/pre-tool.sh"
}
}

Or set via environment:

export CLAUDE_PRE_TOOL_HOOK="$HOME/.claude/hooks/pre-tool.sh"

See Claude Code documentation for the latest hook configuration options.

AxonFlow Policies for Claude Code

AxonFlow's built-in policies automatically apply to Claude Code requests:

  • SQL Injection Detection — 37 patterns blocked automatically
  • PII Detection — SSN, credit cards, Aadhaar, PAN, email, phone detected
  • Dangerous Query Blocking — DROP TABLE, TRUNCATE, DELETE FROM patterns

For custom policies, use the Orchestrator API or Customer Portal (Enterprise):

# Create a custom policy via API
curl -X POST http://localhost:8081/api/v1/policies \
-H "Content-Type: application/json" \
-d '{
"name": "claude-code-production-block",
"description": "Block production database access from Claude Code",
"policy_type": "content",
"conditions": [
{"field": "query", "operator": "contains", "value": "production"}
],
"actions": [
{"type": "block", "message": "Production access blocked"}
]
}'

See Policy Documentation for the full policy API reference.


What Gets Logged

Every governed operation creates an audit entry in the gateway_contexts table:

{
"context_id": "ctx_abc123",
"client_id": "claude-code",
"user_id": "developer",
"query": "SELECT * FROM customers WHERE id = 123",
"approved": true,
"triggered_policies": [],
"requires_redaction": false,
"created_at": "2026-01-24T10:15:30Z",
"expires_at": "2026-01-24T10:20:30Z"
}

For blocked requests:

{
"context_id": "ctx_def456",
"client_id": "claude-code",
"user_id": "developer",
"query": "DROP TABLE users; --",
"approved": false,
"triggered_policies": ["sql_injection_detection"],
"block_reason": "SQL injection pattern detected",
"created_at": "2026-01-24T10:16:45Z"
}

When using MCP connectors, additional entries go to mcp_query_audits with:

  • Connector name and operation type
  • Request/response policy evaluation results
  • PII redaction details
  • Row counts and duration

Example: Governed Database Query

# Developer asks Claude Code to query customer data
> "Show me the recent orders for customer 12345"

# Claude Code invokes MCP postgres tool
# Pre-hook calls AxonFlow:

curl -X POST http://localhost:8080/api/policy/pre-check \
-H "Content-Type: application/json" \
-d '{
"user_token": "developer",
"client_id": "claude-code",
"query": "SELECT * FROM orders WHERE customer_id = 12345",
"context": {"tool": "mcp__postgres"}
}'

# Response (approved):
{
"context_id": "ctx_abc123",
"approved": true,
"policies": [],
"expires_at": "2026-01-24T11:15:30Z"
}

# Query executes, results returned to Claude Code
# Post-hook logs the audit entry

# Response (if PII requires redaction):
{
"context_id": "ctx_def456",
"approved": true,
"requires_redaction": true,
"policies": ["pii_email_detection", "pii_phone_detection"],
"expires_at": "2026-01-24T11:15:30Z"
}

Latency Considerations

OperationTypical Latency
Policy pre-check2-5ms
PII detection1-3ms
SQL injection scan1-2ms
Audit write (async)0ms (non-blocking)
Total overhead3-10ms

For interactive Claude Code usage, this overhead is imperceptible.


Best Practices

1. Start in Observe Mode

AxonFlow supports observe-only mode where policies log but don't block:

# Set PII detection to log-only mode
export PII_ACTION=log

# Or per-policy via API
curl -X PUT http://localhost:8081/api/v1/policies/{id} \
-d '{"actions": [{"type": "log"}]}'

Review logs before enabling enforcement.

2. Govern Sensitive Tools Only

Don't add overhead to read-only operations:

GOVERNED_TOOLS=("Bash" "mcp__postgres" "mcp__mysql" "Write" "Edit")
# Skip: Read, Glob, Grep, WebFetch

3. Use Context for Better Policies

Pass Claude Code context to AxonFlow for smarter decisions:

{
"context": {
"tool": "Bash",
"working_directory": "/home/user/project",
"session_id": "claude-session-123",
"project": "customer-portal"
}
}

4. Configure Approval Workflows (Enterprise)

For high-risk operations, require human approval via HITL (Human-in-the-Loop):

# Create a policy requiring approval
curl -X POST http://localhost:8081/api/v1/policies \
-H "Content-Type: application/json" \
-d '{
"name": "production-approval-required",
"conditions": [
{"field": "query", "operator": "matches", "value": ".*production.*"}
],
"actions": [
{"type": "require_approval", "approvers": ["security-team"]}
]
}'

See HITL Documentation for approval workflow configuration.


Troubleshooting

Hook Not Executing

# Check hook permissions
chmod +x ~/.claude/hooks/pre-tool.sh

# Verify hook is registered
claude config get hooks.pre_tool

# Test manually
~/.claude/hooks/pre-tool.sh "Bash" "ls -la"

AxonFlow Connection Failed

# Check AxonFlow is running
curl http://localhost:8080/health

# Verify network connectivity from hook
curl -v http://localhost:8080/api/policy/pre-check

Policy Not Applied

# Check policy is loaded (Orchestrator API on port 8081)
curl http://localhost:8081/api/v1/policies | jq '.[] | select(.name == "claude-code-governance")'

# Test a policy evaluation manually
curl -X POST http://localhost:8080/api/policy/pre-check \
-H "Content-Type: application/json" \
-d '{"user_token": "test", "client_id": "claude-code", "query": "DROP TABLE users"}'

Next Steps


Need Help?