Give your agents boundaries, not blindfolds.
Scan MCP servers, OpenClaw skills, and Python SDK tools. Enforce policies at runtime — in code, outside the LLM context window.
SEE IT IN ACTION
An AI agent attempts to delete files. AgentWard blocks it — in code, not prompts.
THE PROBLEM
26% of 31,000 AI agent skills contain vulnerabilities. 230+ malicious skills found on ClawHub. OpenClaw has 140K+ GitHub stars and gives agents full computer control — but zero permission governance. Every existing tool only scans before installation, then walks away.
AgentWard does all four — across MCP servers, OpenClaw skills, and Python SDK tools.
Scans your environment, generates a policy, wires enforcement, and starts the proxy — all in one step.
Five stages. Each command does one thing well.
Real examples from production agent setups — individually and in combination
OVERPRIVILEGED(UNSAFE) SKILLS
shell_executor — run arbitrary commands
Agents use this to run scripts, install packages, move files. The skill itself is the problem — a single misdirected instruction can wipe a directory, exfiltrate environment variables, or open a reverse shell.
filesystem — write + delete access
Read-only filesystem access is usually fine. But write and delete permissions mean a confused model can overwrite config files or delete things it was only asked to "clean up."
email-manager — send + delete access
A skill that can both read and delete emails can silently erase inbound messages — including password resets or fraud alerts — without the user ever seeing them.
UNSAFE IN COMBINATION
web-browser + email-manager
individually: LOW · LOW → combined: HIGH
Neither skill is alarming alone. But together an agent can be tricked into exfiltrating data — read a private doc, summarize it, send the summary to an external address.
calendar-reader + slack-poster
individually: LOW · LOW → combined: MEDIUM
Reading someone's calendar is low-risk. Posting to Slack is low-risk. Together, an agent can leak when executives are traveling or who is on PTO — to any Slack channel it can reach.
code-executor + github-writer
individually: MEDIUM · MEDIUM → combined: CRITICAL
A coding agent that can run code locally and push to GitHub can introduce malicious changes, exfiltrate secrets found during execution, or overwrite CI config to persist access.
YAML you can read, diff, and version control. Auto-generated from scan results.
# agentward.yaml — auto-generated by agentward configure
version: "1.0"
skills:
email-manager:
gmail:
read: true
send: false # 🚫 blocked — requires approval
delete: false
google_calendar:
denied: true # email skill has zero calendar access
finance-tracker:
gmail:
read: true
filters:
only_from: ["chase.com", "amex.com"]
network:
outbound: false # financial data NEVER leaves machine
web-researcher:
browser: { allowed: true }
gmail: { denied: true }
filesystem: { denied: true }
skill_chaining:
- email-manager cannot trigger web-researcher
- finance-tracker cannot trigger any other skill
- web-researcher cannot trigger shell-executor
require_approval:
- send_email
- delete_file
- outbound_network_with_pii
- shell_command_with_sudo
Hardened profile for 6 popular MCP servers — filesystem, GitHub, Slack, memory, Brave Search, and Puppeteer.
30 seconds from clone to fully enforced. Customize the YAML to fit your workflow.
†Snyk mcp-scan proxy: guardrails via Invariant Labs API; PII detection in proxy mode.
‡SecureClaw: code-level plugin (51 audit checks) + behavioral skill (15 rules in LLM context, bypassable via prompt injection).
WORKS WITH
Common issues and fixes
OPENCLAW GATEWAY SETUP
OpenClaw does not support openclaw stop, openclaw start, or openclaw restart as standalone commands. The correct command is:
openclaw gateway restart
Also avoid openclaw reset — that cancels the current operation, it does not restart the gateway.
Symptom: AgentWard proxy fails to start with OSError: [Errno 48] address already in use on port 18789.
Root cause: OpenClaw is still listening on the original port (18789) because it wasn't restarted after agentward setup --gateway openclaw swapped the port.
Fix:
1. Run: agentward setup --gateway openclaw
2. Run: openclaw gateway restart
3. Verify: lsof -i :18790 # should show node
lsof -i :18789 # should be empty
4. Run: agentward inspect --gateway openclaw --policy agentward.yaml
Symptom: After editing clawdbot.json to change the port, OpenClaw still binds to the old port after restart.
Root cause: OpenClaw uses a macOS LaunchAgent plist at ~/Library/LaunchAgents/com.clawdbot.gateway.plist that hardcodes the port in two places — ProgramArguments and EnvironmentVariables. OpenClaw reads from the plist at launch, not from clawdbot.json. Both must be updated.
Fix: Run agentward setup --gateway openclaw — it patches both files automatically. If debugging manually, check both clawdbot.json and the plist.
Symptom: Proxy starts but creates an infinite loop, or agentward setup reports the gateway is already wrapped but ports look wrong.
Root cause: A stale .agentward-gateway.json sidecar file in ~/.clawdbot/ from a previous run.
Fix:
rm ~/.clawdbot/.agentward-gateway.json agentward setup --gateway openclaw openclaw gateway restart agentward inspect --gateway openclaw --policy agentward.yaml
Symptom: OpenClaw UI at http://127.0.0.1:18789/ shows blank page or connection error when accessed through the AgentWard proxy.
Root cause (historical): The HTTP proxy was not forwarding WebSocket upgrade requests. OpenClaw's React SPA communicates with the gateway over WebSocket.
Current state: This is fixed. The proxy now detects WebSocket upgrade headers and proxies traffic bidirectionally. No action needed unless this reappears after code changes.
OpenClaw's tool invocation endpoint is POST /tools-invoke (with a hyphen), not /tools/invoke (with a slash). If policy enforcement isn't working, verify the proxy is intercepting the correct path.
POLICY & RUNTIME
Symptom: You blocked a tool (e.g., browser: denied: true), then removed the block from agentward.yaml and restarted the proxy. The agent still avoids using the tool, or says something like "that tool is blocked."
Root cause: This is not AgentWard blocking the tool. When a tool is blocked, AgentWard injects a message like [AgentWard: blocked tool 'browser'] into the LLM response. The LLM sees this in its conversation history and "remembers" the restriction — so even after you re-enable the tool, the LLM avoids using it because it thinks it's still blocked.
Fix: Start a new chat session after changing your policy. A fresh conversation has no memory of the previous block. You can confirm AgentWard is no longer blocking by checking the proxy output — if you see ALLOW (or no BLOCK message), the tool is allowed through.
HTTP PROXY ISSUES
Root cause (historical): Two bugs in the HTTP proxy:
request.json() consumed the body, then request.read() returned empty bytes when forwarding.web.StreamResponse and copying the backend's Content-Length header while streaming caused mismatches.Current state: Fixed. The proxy now reads raw body once with request.read(), parses with json.loads(), and passes cached raw_body to _forward_request(). Uses web.Response (not StreamResponse) to avoid header issues.
MCP STDIO PROXY ISSUES
Check that the server command works standalone first:
npx -y @modelcontextprotocol/server-filesystem /tmp
If the server requires specific env vars or paths, pass them through the agentward command.
Start verifying.
5 seconds to see what your AI agent's tools can actually do.
Apache 2.0 · Python 3.11+ · No API key · Everything runs locally
[email protected]