Documentation
Everything you need to secure your AI agent with passkey approvals.
Overview — How ClawGate Works
ClawGate adds human-in-the-loop approval to AI agent workflows using passkeys (Face ID / Touch ID). When your agent tries to do something sensitive — delete files, send emails, publish packages — ClawGate intercepts the action, sends a push notification to your phone, and waits for your biometric approval before proceeding.
The Three Components
iOS App
Your control panel. Register passkeys, manage API keys, approve/deny actions with Face ID. Get push notifications even when the app is closed.
ClawGate Server
Handles approval requests, WebAuthn verification, push notifications. Hosted at api.clawgate.ai or self-host your own.
OpenClaw Plugin
Intercepts tool calls at the infrastructure level. Pattern-matches commands. Agents cannot bypass it.
ClawGate follows the delegation pattern: your agent requests approval for specific actions, you approve with your passkey, and the agent receives a scoped, time-limited token. The agent never has access to your passkey — same model as OAuth 2.0.
End-to-End Flow
Here's exactly what happens when your agent hits a sensitive command:
Agent Makes a Tool Call
Your agent decides to run rm -rf ./old-data or npm publish. This goes through OpenClaw's tool execution pipeline.
ClawGate Plugin Intercepts
The plugin's before_tool_call hook fires. It checks the command against your configured patterns. Match found → approval required.
Approval Request Created
Plugin sends a POST to the ClawGate server with the action details, agent ID, and context. The server creates a pending approval request.
Push Notification Sent
The server sends an APNs push notification to your registered iOS device. You see the action description and can tap to open the app.
You Approve with Face ID
Open the notification, review the action, and approve (or deny) with Face ID. The passkey authenticates your decision via WebAuthn — phishing-resistant by design.
Agent Proceeds (or Stops)
The plugin polls for the result. Approved → tool call executes normally. Denied or timed out → tool call is blocked and the agent gets a denial message.
Quick Start
1. Download the ClawGate iOS App
Get ClawGate from the App Store. Create your account with email, then register your passkey — just one Face ID scan. Your passkey syncs via iCloud Keychain across all your Apple devices.
2. Generate an API Key
In the app: Settings → API Keys → Create New. Name it (e.g. "My Agent") and copy the key. It looks like ag_xDWZ7V_OamQEDz-uBk5t4LeM6bZxBHXi. You won't see it again, but you can always generate a new one.
3. Install the OpenClaw Plugin
# Via OpenClaw CLI (recommended)
openclaw plugins install clawgate
# Or manually
mkdir -p ~/.openclaw/extensions/clawgate
cd ~/.openclaw/extensions/clawgate
npm install clawgate4. Add to Your OpenClaw Config
Edit ~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"clawgate": {
"enabled": true,
"config": {
"apiKey": "ag_YOUR_KEY_HERE",
"agentId": "my-agent"
}
}
}
}
}The server defaults to https://api.clawgate.ai. Only change it if you're self-hosting.
5. Restart and Test
openclaw gateway restart
openclaw clawgate status # verify connection
openclaw clawgate test # send test approval to your phoneApprove the test notification with Face ID. Then try asking your agent to delete a test file — you'll see ClawGate intercept it in real time.
That's it. ClawGate is now enforcing approval on sensitive commands at the infrastructure level. Your agent can't bypass it.
Configuring Patterns
Patterns determine which tool calls require approval. They use regular expressions (case-insensitive) and can be scoped to specific tools.
Default Patterns
ClawGate ships with sensible defaults that catch dangerous operations:
| Pattern | Description | Tools |
|---|---|---|
| rm\s | Delete files (Unix) | exec |
| rm -rf | Recursive delete | exec |
| del\s | Delete files (Windows) | exec |
| Remove-Item | Delete files (PowerShell) | exec |
| Format-Volume | Format disk volume | exec |
| Clear-Disk | Clear disk | exec |
| Stop-Service | Stop Windows service | exec |
| npm publish | Publish to npm | exec |
| git push.*--force | Force push | exec |
| drop.*table | Drop database table | exec |
| truncate | Truncate table | exec |
| send.*email | Send email | exec |
Custom Patterns
Override or extend patterns in your config:
"config": {
"apiKey": "ag_YOUR_KEY",
"agentId": "my-agent",
"patterns": [
{ "match": "rm\\s", "description": "Delete files", "tools": ["exec"] },
{ "match": "stripe.*charge", "description": "Stripe charge", "tools": ["exec"] },
{ "match": "curl.*POST", "description": "HTTP POST", "tools": ["exec"] },
{ "match": "send.*email", "description": "Send email" }
]
}Pattern fields:
match— Regex pattern (case-insensitive)description— Shown in the push notificationtools— Limit to specific tool names (e.g.["exec"]). Omit to match all tools.scopes— Optional scopes attached to the approval token
Always-Approve Tools
Require approval for every call to a specific tool, regardless of pattern:
"alwaysRequireApproval": ["message", "browser"]All Configuration Options
| Option | Default | Description |
|---|---|---|
| serverUrl | https://api.clawgate.ai | ClawGate server URL |
| apiKey | required | API key from the ClawGate app |
| agentId | openclaw | Identifier for this agent (shown in approvals) |
| timeoutSeconds | 120 | How long to wait for approval |
| blockOnTimeout | true | Block action if approval times out |
| blockOnError | true | Block if server unreachable (fail-closed) |
| pollIntervalMs | 2000 | Polling interval for approval status |
| patterns | 12 defaults | Array of sensitive patterns |
| alwaysRequireApproval | [] | Tool names that always need approval |
💡 Fail-closed by default: If the ClawGate server is unreachable or a request times out, the action is blocked. Set blockOnError: false or blockOnTimeout: false to change this behavior (not recommended for production).
CLI Commands
openclaw clawgate statusShows server connection, agent ID, pattern count, fail-closed mode.
openclaw clawgate testSends a test approval request to your phone. Use to verify Face ID flow works end-to-end.
openclaw clawgate patternsLists all active patterns with their regex and tool scope.
Security Model
🔒 Infrastructure-level enforcement
ClawGate uses OpenClaw's before_tool_call hook. This runs before any tool executes. The agent cannot skip, override, or work around it — it's enforced by the platform, not the agent.
🛡️ Phishing-resistant passkeys
Passkeys (WebAuthn/FIDO2) are bound to the registered domain. They can't be phished, replayed, or extracted. Even if an attacker compromises the agent, they can't approve actions without your biometric.
⏱️ Scoped, time-limited tokens
Approved actions receive a JWT token that's scoped to the specific action and expires in minutes. Can't be reused for different actions.
🚫 Fail-closed
If the server is unreachable, push fails, or the request times out — the action is blocked. Security degrades gracefully toward "deny" rather than "allow".
📊 Full audit trail
Every approval request is logged: what action, which agent, when it was requested, and whether it was approved, denied, or timed out. Viewable in the iOS app.
Why not just use passwords or OTPs?
| Feature | Passkeys | Passwords | OTPs |
|---|---|---|---|
| Phishing-resistant | ✅ | ❌ | ❌ |
| Nothing to remember | ✅ | ❌ | ✅ |
| Fast (< 2 seconds) | ✅ | ❌ | ❌ |
| Can't be shared/stolen | ✅ | ❌ | ❌ |
API Reference
Use the API to integrate ClawGate with any agent framework — not just OpenClaw. Full reference: API.md on GitHub
Request Approval
POST https://api.clawgate.ai/api/v1/approval/request
Authorization: Bearer ag_your_api_key
Content-Type: application/json
{
"agentId": "my-agent",
"action": "send-email",
"description": "Send quarterly report to investors@company.com",
"timeoutSeconds": 120,
"scopes": ["email:send"]
}
// Response:
{
"requestId": "req_abc123",
"status": "pending",
"expiresAt": "2026-02-11T18:05:00Z"
}Poll for Status
GET https://api.clawgate.ai/api/v1/approval/status/{requestId}
Authorization: Bearer ag_your_api_key
// Response (approved):
{
"requestId": "req_abc123",
"status": "APPROVED",
"token": "eyJhbGciOiJFUzI1NiIs...",
"tokenExpiresAt": "2026-02-11T18:08:00Z"
}
// Possible statuses: PENDING, APPROVED, DENIED, EXPIREDIntegration Example (Python)
import requests, time
API_KEY = "ag_your_key"
BASE = "https://api.clawgate.ai/api/v1"
def request_approval(action, description):
r = requests.post(f"{BASE}/approval/request",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"agentId": "my-agent", "action": action, "description": description}
)
req_id = r.json()["requestId"]
for _ in range(60): # poll for 2 minutes
s = requests.get(f"{BASE}/approval/status/{req_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
).json()
if s["status"] == "APPROVED": return True
if s["status"] in ("DENIED", "EXPIRED"): return False
time.sleep(2)
return False
if request_approval("send-email", "Send report to investors@co.com"):
send_the_email()
else:
print("Denied by user")Self-Hosting
ClawGate is 100% open source. Self-host everything if you want full control.
Requirements
- Node.js 20+
- PostgreSQL 14+ (or SQLite for development)
- HTTPS domain (required for WebAuthn)
- Apple Developer account (for push notifications)
Docker
git clone https://github.com/AsteyaTech-com/clawgate-api.git
cd clawgate-api
docker-compose up -dManual
git clone https://github.com/AsteyaTech-com/clawgate-api.git
cd clawgate-api/server
npm install
cp .env.example .env # edit with your DB, keys, etc.
npx prisma db push
npm run devThen set serverUrl in your plugin config to your server's URL. Full guide: GETTING_STARTED.md
Troubleshooting
Plugin says "missing apiKey — skipping"
Check that your openclaw.json has the correct path: plugins.entries.clawgate.config.apiKey. Restart the gateway after editing.
Not getting push notifications
Make sure notifications are enabled for ClawGate in iOS Settings → Notifications. Also check that your device token was registered — open the app and it should re-register automatically.
"Server unreachable — blocked" but server is up
Check your network/firewall. The plugin needs to reach api.clawgate.ai on port 443. Run openclaw clawgate status to test connectivity.
Too many false positives (dev commands getting blocked)
Override the default patterns with more specific ones. For example, instead of matching all Remove-Item, match only Remove-Item.*-Recurse or specific paths.
Approval timed out but I never saw a notification
Push delivery isn't guaranteed — APNs can delay or drop notifications. If this happens frequently, check the ClawGate app for pending requests (they appear even without push).
Need help? Open an issue on GitHub or check the setup guide.