An AI agent with hands can do real things. It can press Pay. It can send an email as you. It can type a password, or empty the Trash. Waldo gives any AI agent hands on your Mac, and he stops at four kinds of act every time. He asks you first, and he waits for your own click.
What are the four hard stops?
The hard stops live in Waldo’s code, not in a prompt. No model, however clever, can talk its way past them. Each gate catches a kind of act:
| Gate | It catches |
|---|---|
| Money | Buttons such as Pay, Buy, Place order, and Transfer. Any click on a bank, broker, or checkout page. |
| Sending as you | Buttons such as Send, Post, Reply, and Submit. Return in a chat app. Cmd+Return anywhere. |
| Passwords and keys | Typing into a password field. Any click in Keychain Access, Passwords, 1Password, or a system password dialog. |
| Destructive changes | Buttons such as Delete, Erase, Reset, and Sign out. A drop on the Trash. Cmd+Delete in Finder. Disk Utility. |
A rule about what an act is, such as a Transfer button, asks every time. A rule about where you are, such as a bank’s site, offers a yes for ten minutes.
Why put the gates in code instead of a prompt?
A rule in a prompt is advice to the model. A model can be talked out of advice. A web page or an email can carry hidden instructions that try. The OWASP project for AI security calls this indirect prompt injection. Its list of defences includes “Require human approval for high-risk actions” and “Enforce privilege control and least privilege access” (OWASP LLM01:2025 Prompt Injection).
Waldo does both, in code. The model does not decide whether a gate applies. The code does, from facts it reads off the screen: the app, the web address, the label about to be clicked, and the key about to be pressed. Every input needs a ticket that only the gate can issue, so code that skips the gate does not compile.
Who can say yes?
Only you. No agent can approve itself. The ask panel shows what the agent wants to do, and how the panel behaves is fixed:
- It never takes the keyboard. It is safe to show while you type elsewhere.
- Allow needs a real click from your mouse or trackpad.
- No answer in two minutes is a no.
- While it shows, the tools refuse all input.
A click posted by software is refused. So is a press sent through the accessibility API. Both are tested.
Can I see or change the rules?
Yes. The rules are plain lists in crates/waldo-core/src/gate.rs in the Waldo repo. Run waldo policy to print them. Save an edited copy as policy.json in ~/Library/Application Support/Waldo to change them. A file that does not parse stops every tool, so a typo cannot switch the gates off.
Every tool call and every gate answer is one line in ~/Library/Application Support/Waldo/audit.jsonl. Text typed into a password field is logged as a count only. waldo log prints the last lines.
What do the hard stops not stop?
Read this part before you turn Waldo on.
- The gates are guard rails, not a jail. A session also has a shell, and your terminal holds the Accessibility grant. A session that set out to cheat could post its own events from the shell, or edit
policy.json. The gates stop mistakes. They stop instructions hidden in a web page or an email. They do not stop a model that is trying to get round them. - The shell has no gates of its own beyond your agent’s own permission settings.
- The label rules read English. An app that draws its own controls has no tree. There the tools fall back to positions, and only the place rules and the model’s own
confirmapply. See accessibility tree vs screenshots. - When you are away, nobody can click Allow. Gated acts are refused.
Found a way past a gate? That is a security bug. Report it privately, as SECURITY.md explains.
How do I turn the hard stops on?
Install Waldo. The gates come with him, for every agent that borrows his hands: Claude Code, Codex, Gemini CLI, Cursor, or any agent that speaks MCP. The steps are on the install section, and below.
When you need everything to stop at once, push your pointer into the top-left corner of the screen. That is the panic corner.