Agent Inbox
by Zijian-Ni
README.md
# 📥 Agent Inbox
> **Approve before, not audit after.** A local human-in-the-loop gate for AI agents. It blocks the action until you decide — and **a timeout means denied**.
[](https://github.com/Zijian-Ni/agent-inbox/actions/workflows/test.yml)
[](LICENSE)
[](#privacy)
**Part of the [Aurora Evidence Suite](https://github.com/Zijian-Ni/aurora-evidence-suite)** — local-first evidence tools for AI agents.
---
## Why this exists
Every other tool in the suite is retrospective. Traceboard replays what an agent did; ClaimTape checks what it claimed; Evolution Ledger audits how it changed. All of that is *after the fact*.
Agents are increasingly given real capability — deploying, deleting, spending, messaging people on your behalf. For those actions, "we can reconstruct what went wrong" is not good enough. **Agent Inbox is the one piece that sits in front of the action.**
```
┌──────────────┐ request_approval ┌─────────────┐
Agent ──│ Agent Inbox │◀──── BLOCKS ─────────│ your call │
└──────┬───────┘ └─────────────┘
│ approved → agent proceeds
│ denied → agent stops
│ timeout → DENIED (never assumed safe)
```
---
## 30-second Quickstart
```bash
git clone https://github.com/Zijian-Ni/agent-inbox.git
cd agent-inbox && npm install
npx agent-inbox serve # web UI on http://127.0.0.1:7777
npx agent-inbox pending # or stay in the terminal
```
Wire it into an agent (MCP):
```bash
claude mcp add agent-inbox -- npx agent-inbox-mcp
```
Then tell your agent, in its instructions:
> Before any irreversible action — deleting data, deploying, spending money, or sending messages on the user's behalf — call `request_approval` and wait. A denial or a timeout means stop and report back; it never means find another way.
---
## The one rule that matters
**Deny is the default.**
A request that times out, or hits a crashed UI, a full disk, an unparsable log line or any ambiguous state, resolves to **denied**. Never approved.
This is not defensive coding for its own sake. *An approval gateway that fails open is worse than no gateway*, because it manufactures the belief that somebody is watching. If this tool is running, silence must mean "no".
Verified by tests, and by driving the real MCP server over stdio:
```
after a 1500ms deadline with NO human present:
status : expired
approved: false
guidance: NOT approved. Do not proceed. Report this to the user
instead of retrying or working around it.
```
---
## What you get
| Surface | Use it when |
|---|---|
| **MCP server** (`agent-inbox-mcp`) | The agent asks; `request_approval` blocks until you answer |
| **Web UI** (`agent-inbox serve`) | You want to see the payload and click; loopback only |
| **CLI** (`agent-inbox pending/approve/deny/watch`) | You are already in a terminal, or on a phone over SSH |
All three read and write **the same append-only JSONL file**, so they agree without any server in between:
```
~/.agent-inbox/approvals.jsonl (or $AGENT_INBOX_PATH)
```
### Commands
```bash
agent-inbox pending # what needs you
agent-inbox show <id> # full detail, including the exact payload
agent-inbox approve <id> --reason "checked the diff"
agent-inbox deny <id> --reason "not tonight"
agent-inbox watch # follow new requests live
agent-inbox serve --port 7777 # web UI
agent-inbox stats # counts + median decision time
agent-inbox verify # has the log been tampered with?
agent-inbox compact # collapse the log (backs up first)
```
---
## Design decisions worth knowing
**You always see the payload, not just the label.** Approving "deploy to production" when the actual command is something else is the obvious attack on a tool like this. Both the CLI and the web UI show the exact `detail` before you can decide.
**The log is append-only and hash-checked.** A decision appends a record; it never rewrites one. Each record carries a SHA-256 of its immutable request fields, so `verify` catches a detail edited after approval, and catches a decision quietly changed from denied to approved. "Who approved the thing that broke production" stays answerable.
**A settled request cannot be re-decided.** Replaying an old pending record cannot reopen something you already denied — there is a test for exactly that, because message replay is a realistic failure mode with agents.
**Loopback only, by design.** The web server binds `127.0.0.1` and the host is not configurable. An approval console reachable from your network is a remote-code-execution panel with a friendly face. The security boundary is "you are already on this machine".
**Stopping is always the frictionless direction.** High-risk *approvals* get a confirmation speed bump; denials never do.
---
## Honest limitations
- **It gates what the agent chooses to ask about.** This is cooperative, not a sandbox. An agent that never calls `request_approval` is not gated — pair this with real OS/container permissions for anything genuinely hostile.
- **Risk levels are the agent's own claim.** `risk: "low"` means the agent said so. Read the payload.
- **No authentication.** Anyone with access to your machine and that port can approve. That is the intended threat model; do not expose it.
- **Not a queue for teams.** One human, one machine. Multi-user approval with identity is a different product.
---
## Privacy
No telemetry, no accounts, no cloud. The MCP server and CLI make **zero network requests**. The only listener is the loopback web UI you start yourself.
---
## 中文说明
**Agent Inbox = 事前批准,而不是事后审计。**
这套工具里其他几个都是回溯性的:Traceboard 回放 agent 做过什么、ClaimTape 核查它声称了什么、Evolution Ledger 审计它怎么改的自己。**只有这一个站在动作之前。**
agent 现在被交付越来越多的真实权限——部署、删除、花钱、以你的名义发消息。对这些动作来说,「出事后能还原过程」是不够的。
**最重要的一条规则:超时 = 拒绝。**
请求超时、界面崩了、磁盘满了、日志有坏行、任何状态不明的情况,一律判为**拒绝**,绝不放行。这不是过度防御——**一个「失败时放行」的批准网关比没有网关更糟**,因为它制造了「有人在看着」的错觉。
**几个刻意的设计:**
- **永远展示真实载荷,而不只是标签。** 界面上写「部署到生产」、实际命令却是别的东西,这是这类工具最典型的攻击方式。CLI 和网页在你做决定之前都会把完整 `detail` 摊开给你看。
- **日志只追加,且带哈希校验。** 决定是追加一条新记录,不是改写旧记录;每条都带请求字段的 SHA-256,所以「批准之后偷偷改内容」和「把拒绝悄悄改成批准」都能被 `verify` 抓出来。
- **已决定的请求不能被重新决定。** 重放一条旧的 pending 记录,无法把你已经拒绝的事情重新打开——这条有专门的测试,因为在 agent 场景里消息重放是真实存在的故障模式。
- **只监听本机回环,且不可配置。** 一个能从局域网访问的批准面板,本质上就是一个长着友好外表的远程代码执行控制台。
- **「停下」永远是阻力最小的方向。** 高风险的**批准**要多一次确认,拒绝从来不需要。
**诚实的边界**:它只能拦住 agent 主动来问的事情——这是协作机制,不是沙箱;`risk` 等级是 agent 自己的说法,请自己读载荷;没有身份认证,所以千万不要暴露到网络上。
---
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md). The most valuable contribution is **a way to make this fail open** — if you find one, that is a security bug and I want to know.
## License
MIT © Zijian Ni
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues