Your agent has your keys.
OpenClaw sends email, posts, and runs commands as you. The guard checks every action before it runs: allow it, ask you first, or block it.
task main · “triage mentions and email, queue the launch post”
| time | where | decision | reason |
|---|
wants to post: “we're live 🎉”
agent:main · macmini · hash-chained · seq 87
Routine actions pass, and get recorded anyway.
Sensitive actions wait for a tap on your phone. Silence means no.
Destructive actions never start. The reason lands in the feed.
problem/
“READ-ONLY” is a prompt, not a policy.
This line ships in a real Twitter skill. The model follows it, until a poisoned page talks it around (the attack is called prompt injection) or one creative interpretation posts as you. The guard reads the action itself, classifies its intent (post vs read, send vs list, delete vs status), and rules on that, not on wording.
## Rules
⛔ STRICT READ-ONLY — NEVER post/reply/DM/follow
Rules the model can't talk its way around.
proof/
The tweet that never happened.
Recorded live on an ordinary, unmodified OpenClaw. The guard classifies the action, checks policy, and refuses before the command runs.
the record it left behind
- action
bird tweet "we're live 🎉"- classified
twitter.post- policy
social-guard · write → deny- caller
agent:main- verdict
- deny
- receipt
seq 84 · sha256:ab3f…9c2e · chained to 83
packs/
Seven guardrails, ready on install.
Twitter stays read-only, Drive deletes get stopped, and secrets never leave in an outbound message. Each pack knows its tools and gates them by intent. Flip a mode below; it applies live, no restart.
Local packs can only make policy stricter. Loosening happens in your cloud dashboard, where every change is signed, so nothing on the machine can quietly relax its own rules.
Learn mode
| agent | where | action | count | would-block |
|---|---|---|---|---|
| llm-twitter | read | 44 | 0 | |
| llm-twitter | post | 2 | 2 | |
| main | send | 7 | 3 | |
| main | github | push | 12 | 0 |
| reddit-digest | comms | read | 31 | 0 |
proposed packs
learn/
It watches before it blocks.
Packs start in observe mode: watching, never blocking. The guard records what each agent actually does, then one click turns that profile into policy: read-only agents locked read-only, sensitive actions set to ask, secret leaks blocked outright. Nothing breaks on day one.
approvals/
Yes or no, from your pocket.
When policy says ask, the guard messages you on Telegram. Approve or deny with one tap; the same request sits in the local console. No answer in 90 seconds counts as no. Approvals never route through the agent being governed.
Agent llm-twitter wants to twitter.post:
“gm 🌅 (scheduled)”
gmail send to a first-time recipient · pii:email
audit/
Every decision, on the record.
What ran, what was blocked, who asked, who approved. Export it any time; the data is yours. Every verdict below is from a live run.
| action | verdict | classified as |
|---|---|---|
bird tweet … |
deny “Command blocked by PreToolUse hook” | twitter.post |
gog drive delete … --force |
deny | file.delete |
Telegram message carrying a GitHub token (ghp_…) |
deny | comms.send + secret:ghp |
gog gmail send to a stranger |
ask | email.send + pii:email |
git push --force |
deny “blocked: git force-push” | github.force_push |
bird search, benign echo |
allow | twitter.read · exec.run |
answers/
Straight answers.
Can a hijacked agent get around it?
Partly. The guard and the agent run on the same machine under the same user account, so an agent that fully took over could kill the guard itself. What it can't do is quietly loosen the rules: local changes only ever make policy stricter. Separate user accounts or OS-level interception close the remaining gap.
Does it slow the agent down?
No. Checks run on the machine itself and come back in milliseconds. The only time an agent waits is when policy says ask, and that wait is the point.
Does it read what the model says back?
No. The guard governs actions. What the model writes back to you is the model's business.
Put a guard on it.
npx @aarvionai/guard onboard <pairing-code>One command: links this machine to your dashboard, installs the plugin into your existing OpenClaw, restarts it. Everything starts in observe mode, so it blocks nothing until you say so.