Human-in-the-loop for OpenClaw
Human approval for OpenClaw tool calls, on a phone.
A before_tool_call hook holds risky OpenClaw tools until your user approves them on their phone.
What OpenClaw gives you
The before_tool_call hook
An OpenClaw plugin can register a before_tool_call hook. It runs before the tool, and returning { block: true, blockReason } stops the call and tells the model why. That is the right place for an approval, because it blocks the action instead of reporting it afterwards.
Where it stops
- The hook has no way to reach a person who is away from the gateway.
- It has no wait that survives a restart while someone decides.
- It keeps no record of what was allowed or blocked, or who decided.
The fix
Pushary gets your user's answer.
before_tool_call can stop a tool. decisions.ask() inside it sends the question to your user's phone, waits for Approve or Deny, and saves the answer. The hook blocks on anything but a yes.
The plugin gates three tools: deploy_service, delete_record and send_email. For those, the hook calls decisions.ask() and returns { block: true } unless your user approves. Every other call skips the hook and runs untouched. Every answer is saved.
npm i @pushary/serverimport { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"
import { createPusharyServer } from "@pushary/server"
const pushary = createPusharyServer({ apiKey: process.env.PUSHARY_API_KEY! })
const GATED = new Set(["deploy_service", "delete_record", "send_email"])
export default definePluginEntry({
id: "pushary-approvals",
name: "Pushary approvals",
register(api) {
api.on("before_tool_call", async (event) => {
if (!GATED.has(event.toolName)) return
const d = await pushary.decisions
.ask({ question: `Allow ${event.toolName}?`, externalId: "user_123", type: "confirm" })
.catch(() => ({ approved: false }))
if (!d.approved) {
return { block: true, blockReason: "A person did not approve this action." }
}
})
},
})How it works
From install to the first answer
Connect your user once. Put the approval on the risky step. Pushary sends the question, waits for the answer and saves it.
- 01
Install and set your key
Run npm i @pushary/server in your plugin workspace and set PUSHARY_API_KEY.
- 02
Connect your user once
One SDK call returns a connect link. The person who approves opens it on their phone with the free Pushary app. No account, no payment.
- 03
Register the hook
In your plugin entry, register a before_tool_call hook that calls decisions.ask() for the tool names you gate.
- 04
Block on anything but a yes
Return { block: true } with a blockReason unless the answer is an explicit Approve, so a no or a timeout stops the call.
A question can be a yes or no, a choice from a list, or a typed answer. Every answer is saved.
Before you ship
Things that bite on OpenClaw
- Ask in the hook, not in a tool
- A tool the model chooses to call is optional, and a prompt that says “ask first” is not a gate. before_tool_call runs on every call whether the model wants it or not, so the approval belongs there.
The Partner plan
Your agent asks your users, not just you
Ship your agent to your users. Each of them approves its risky actions from their phone, under your brand.
Your users never make a Pushary account or pay us.
Your users answer on their own phones
Connect each user once with a link. They install the free Pushary app and answer from the lock screen, with no account of their own.
No answer means no
Run the action only after an explicit Approve. A request that is still waiting, expired or cancelled never counts as a yes. Pushary keeps every request, so your code can pick it up again after a restart.
Reaches them on their phone
The app comes first, because only the app puts Approve and Deny on the lock screen. Browser notifications come next. You build no delivery system.
Every answer saved
Every answer is saved with who answered and when. You can search and export it, and with a callback URL, each answer is also sent to your server as a signed webhook.
FAQ
Questions, answered
Is there a @pushary/openclaw package?
How do I block a tool call?
What happens on a timeout?
Can I gate only some tools?
Who approves the call?
Let your OpenClaw agent ask before it acts.
Connect a user once, ask with one call, and run the action only on a yes. Every answer is saved.
Start freePartner plan, $99 a month. Your users never make a Pushary account or pay us.