Tools
Witness
Tamper-evident audit trails for OpenClaw agents. Lightweight HITL plugin with hash-chained logging.
Install
npm install
npm
Configuration Example
# In your OpenClaw config (clawdbot.json or plugin config):
plugins:
witness:
mode: audit # audit | gate-writes | gate-all
db_path: witness.db # SQLite database path
ttl_minutes: 30 # auto-expire pending approvals
auto_approve_threshold: 10 # approvals before auto-approve
risk_overrides: # override default risk levels
exec: critical
Read: low
README
# Witness ๐๏ธ
**Tamper-evident audit trails for OpenClaw agents.**
Witness is an OpenClaw plugin that records every tool call your AI agent makes into a hash-chained, queryable SQLite log. No friction by default โ it just watches. When you're ready, opt into approval gates for high-risk actions.
## Why
You gave your AI agent access to your email, files, calendar, maybe your bank. It's doing things on your behalf 24/7. But:
- **What did it actually do at 3 AM?** You have no idea.
- **Can you prove it didn't send that email?** Not without structured logs.
- **Can you gradually trust it with more?** Not without a trust ramp.
Witness solves this. Every tool call โ structured event โ hash-chained log โ queryable audit trail.
## How It Works
```
Agent calls tool โ OpenClaw hook fires โ Witness logs/gates โ Tool executes (or blocks)
```
### Three Modes
| Mode | Behavior | Default risk blocked |
|------|----------|---------------------|
| `audit` (default) | Log everything, block nothing | None |
| `gate-writes` | Block high-risk + critical | `exec`, `process`, `rm -rf`, `.env` writes |
| `gate-all` | Block medium and above | Above + `Write`, `Edit`, `message.send`, `browser.navigate` |
### Risk Assessment Engine
Static risk levels per tool name + param-aware escalation:
| Risk Level | Tools | Param Escalation |
|-----------|-------|-----------------|
| ๐ข Low | `Read`, `web_search`, `memory_search`, `session_status` | โ |
| ๐ก Medium | `Write`, `Edit`, `message`, `browser` | `message.send` โ medium |
| ๐ High | `exec`, `process` | `sudo`, `elevated: true` โ high |
| ๐ด Critical | โ | `rm -rf`, `.env`/`.pem`/`.ssh` writes โ critical |
## Install
```bash
# From ClawHub (when published):
openclaw skill install witness
# For development:
git clone https://github.com/cheenu1092-oss/witness.git
cd witness
npm install
npm run build
```
### OpenClaw Plugin Config
```yaml
# In your OpenClaw config (clawdbot.json or plugin config):
plugins:
witness:
mode: audit # audit | gate-writes | gate-all
db_path: witness.db # SQLite database path
ttl_minutes: 30 # auto-expire pending approvals
auto_approve_threshold: 10 # approvals before auto-approve
risk_overrides: # override default risk levels
exec: critical
Read: low
```
## Usage
Once installed, Witness runs automatically. Every tool call is logged.
### Query Commands
```
/witness โ Show recent events (last 20)
/witness recent 50 โ Show last 50 events
/witness search exec โ Search by tool name, params, or result
/witness stats โ Tool counts, costs, errors, risk breakdown
/witness verify โ Verify hash chain integrity (tamper detection)
/witness mode โ Show current operating mode
/witness export โ Export info (file export coming soon)
/witness help โ Full command list
```
### Approval Commands (gate modes only)
```
/witness pending โ Show pending work orders
/witness approve wo_01HXYZ... โ Approve a blocked action
/witness approve wo_01HXYZ... Looks safe โ Approve with note
/witness reject wo_01HXYZ... โ Reject a blocked action
/witness trust exec โ Show trust history for a tool
```
### Approval Flow
```
1. Agent calls exec({command: "rm -rf /tmp/old"})
2. Witness: ๐ BLOCKED โ critical risk (destructive command)
3. Agent tells user: "Blocked by Witness. Approve with /witness approve wo_xxx"
4. User: /witness approve wo_xxx
5. Witness: โ
Approved โ system event โ agent re-executes
```
## Architecture
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OpenClaw Gateway โ
โ โ
โ Agent โโโ before_tool_call โโโ Witness Gate โ
โ โ โ
โ โโโโโโโดโโโโโโ โ
โ ALLOW BLOCK โ
โ โ โ โ
โ Tool runs Work order โ
โ โ created โ
โ โผ โ โ
โ Agent โโโ after_tool_call โโโ /witness approve โ
โ โ โ โ
โ Witness Log System event โ
โ โ โ re-execute โ
โ โผ โ
โ SQLite (WAL) โ
โ โโโโโโโโโโโโโโโโโโโโโโ โ
โ โ events (hash-chain)โ โ append-only, immutable โ
โ โ work_orders โ โ mutable state machine โ
โ โ trust_ledger โ โ auto-approval tracking โ
โ โ config โ โ runtime settings โ
โ โโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
### Key Design Decisions
1. **Events are immutable + hash-chained.** Work orders are mutable. They're in separate tables to preserve the append-only invariant.
2. **Hash chain = tamper detection, not prevention.** If someone owns your machine, they can rewrite the DB. But the chain will break, and `/witness verify` will catch it.
3. **`after_tool_call` is async.** It fires after tool execution completes โ zero latency overhead on the tool call itself.
4. **`before_tool_call` blocks synchronously.** In gate modes, the tool call is blocked before execution. The agent receives an error with the block reason.
5. **Re-execution uses system events.** After approval, a system event is enqueued. The agent sees it at the start of the next turn and can re-execute the tool.
6. **SQLite WAL mode.** ~66ฮผs per insert. Handles 500 rapid sequential appends without corruption. Chain survives process restart.
## Database Schema
Four tables:
| Table | Rows Grow? | Mutable? | Hash-chained? | Purpose |
|-------|-----------|----------|---------------|---------|
| `events` | Yes (append-only) | No | Yes | Audit log of every tool call |
| `work_orders` | Yes (per block) | Yes | No | Approval queue state machine |
| `trust_ledger` | Yes (per tool) | Yes | No | Auto-approval ramp tracking |
| `config` | Rarely | Yes | No | Runtime key-value settings |
### Event Schema
```sql
events (
id TEXT PRIMARY KEY, -- evt_<ulid>
seq INTEGER UNIQUE, -- monotonic sequence
timestamp TEXT, -- ISO 8601 UTC
session_key TEXT, -- OpenClaw session
agent_id TEXT, -- agent that made the call
tool_name TEXT, -- e.g. 'exec', 'Read'
params_json TEXT, -- JSON tool params
result_ok INTEGER, -- 1=success, 0=error
result_summary TEXT, -- truncated result (max 1KB)
duration_ms INTEGER, -- execution time
risk_level TEXT, -- unknown|low|medium|high|critical
risk_reasons TEXT, -- JSON array of reasons
action TEXT, -- logged|blocked|auto_approved
cost_usd REAL, -- estimated cost
prev_hash TEXT, -- SHA-256 of previous event
hash TEXT -- SHA-256(prev_hash+id+timestamp+tool_name+params_json)
)
```
## Project Status
| Component | Status | Tests |
|-----------|--------|-------|
| Audit store (events, hash chain) | โ
Complete | 8 tests |
| Work orders (create, resolve, sweep) | โ
Complete | 9 tests |
| Trust ledger (approve/reject tracking) | โ
Complete | 6 tests |
| Concurrency (WAL, rapid inserts) | โ
Validated | 5 tests |
| Risk assessment engine | โ
Complete | 20 tests |
| Plugin integration (register, hooks, commands) | โ
Complete | 30+ tests |
| Edge cases (unicode, nulls, empty DB) | โ
Complete | 4 tests |
| **Total** | | **80+ tests** |
### Phase Roadmap
| Phase | Scope | Lines | Status |
|-------|-------|-------|--------|
| Phase 1 | Audit-only (log every tool call, hash chain, /witness commands) | ~800 | โ
Built |
| Phase 2 | Approval gates (before_tool_call, work orders, approve/reject flow) | +600 | โ
Built |
| Phase 3 | Trust ramp (auto-approve, trust ledger UI, export) | +400 | โ
Built |
| **Total** | | **~1,800** | |
### MVP (Phase 1 ship criteria)
- [x] `register(api)` plugin entry point
- [x] `after_tool_call` hook logs every tool call
- [x] SHA-256 hash chain on all events
- [x] `/witness` command with 11 subcommands
- [x] SQLite WAL mode, <100ฮผs per insert
- [x] 80+ tests passing
- [x] Plugin manifest (`openclaw.plugin.json`)
- [x] SKILL.md for ClawHub
- [ ] npm publish (`openclaw-witness`)
- [ ] GitHub repo creation
- [ ] Real-world testing on live OpenClaw instance
## Development
```bash
npm install # install deps
npm test # run vitest
npm run build # compile TypeScript
npm run dev # watch mode
```
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
## License
MIT
## Credits
Built by [cheenu1092-oss](https://github.com/cheenu1092-oss) as an OpenClaw community plugin.
Research informed by analysis of [Ruflo](https://github.com/ruvnet/ruflo) (MIT), [Temporal](https://temporal.io), and the [OpenClaw plugin system](https://github.com/openclaw/openclaw).
tools
Comments
Sign in to leave a comment