Voice
Blackwall Openclaw
BLACK_WALL pre-action guardrail for OpenClaw agents. Hooks before_tool_call to call forecast() before any tool runs; blocks STOP verdicts; surfaces CAUTION as approval prompts. Receipts are Ed25519-signed and verifiable offline.
Configuration Example
import { createBlackwallPlugin } from 'blackwall-openclaw-plugin';
export default createBlackwallPlugin({
mode: 'enforce',
cautionAction: 'approve', // 'approve' (default) | 'block' | 'allow'
});
README
# blackwall-openclaw-plugin
Pre-action risk check for [OpenClaw](https://github.com/openclaw/openclaw) agents. Hooks `before_tool_call` so STOP-rated actions can be **blocked before they run** β without modifying your character, tools, or other plugins.
Powered by [BLACK_WALL](https://blackwalltier.com). Get a free key at [blackwalltier.com/dashboard/keys](https://blackwalltier.com/dashboard/keys).
## Install
```bash
npm i blackwall-openclaw-plugin
```
Add to `~/.openclaw/openclaw.json`:
```json5
{
plugins: {
entries: {
"blackwall-openclaw-plugin": { enabled: true }
}
}
}
```
Set the env var (in your shell, `~/.openclaw/.env`, or the launcher):
```bash
BLACKWALL_API_KEY=bw_live_xxx
BLACKWALL_MODE=observe # or 'enforce' once you trust the verdicts
```
That's it. Every tool the agent tries to call goes through `before_tool_call` β BLACK_WALL forecast β verdict.
## What you get back per tool call
- `GO` / `CAUTION` / `STOP`
- risk score 0β100
- reversibility class (REVERSIBLE / RECOVERABLE / IRREVERSIBLE)
- named red flags β e.g. `SQL_NO_WHERE`, `PROMPT_INJECTION_LIKELY`, `IRREVERSIBLE_NO_BACKUP`
- an Ed25519-signed Decision Receipt β verifiable offline against the published public key
Round trip ~4β8s.
## Modes
| Mode | Behavior |
|---|---|
| `observe` (default) | Score every tool call and log to BLACK_WALL; never block. Zero behavior change β safe to drop in. |
| `enforce` | **STOP** β hard block (returns `{ block: true }`). **CAUTION** β surfaces an approval prompt natively via OpenClaw's `requireApproval`. **GO** β proceeds. |
Start in `observe` for a few days to see what the verdicts look like on your real traffic. Switch to `enforce` once you trust the scoring.
## Configurable CAUTION behavior
```js
import { createBlackwallPlugin } from 'blackwall-openclaw-plugin';
export default createBlackwallPlugin({
mode: 'enforce',
cautionAction: 'approve', // 'approve' (default) | 'block' | 'allow'
});
```
- `approve` β fires OpenClaw's built-in approval prompt with the named red flags. User decides per call.
- `block` β treats CAUTION as STOP. Hard block.
- `allow` β treats CAUTION as GO. Lets it run, just observed.
## Why hook into `before_tool_call`?
OpenClaw's plugin SDK exposes [`before_tool_call`](https://docs.openclaw.ai/plugins/hooks) as an official typed hook with `block` + `requireApproval` return semantics β exactly the shape a pre-action guardrail needs. The plugin does **not** monkey-patch the dispatcher; it uses the documented extension surface.
That means:
- Priority-ordered with other policy hooks (defaults to `priority: 80`)
- Per-hook timeout (`timeoutMs: 15_000` by default β a hung forecast can't stall the agent)
- Native `requireApproval` flow for CAUTION verdicts
- Hot-reloadable via the gateway
## Companion skills
This package also ships two OpenClaw skills under `./skills/` that you can install into `~/.openclaw/skills/`:
- **`/blackwall-policy`** β Explains what BLACK_WALL is gating in this session, the failure-mode codes, and why a tool was blocked. Read by the agent when a `failureResult` references BLACK_WALL.
- **`/blackwall-verify`** β Verifies a Decision Receipt cryptographically (offline against the published public key, or via the hosted stateless verify endpoint).
Copy them in:
```bash
cp -r node_modules/blackwall-openclaw-plugin/skills/* ~/.openclaw/skills/
```
(or symlink for development).
## Full config reference
```js
createBlackwallPlugin({
apiKey: process.env.BLACKWALL_API_KEY, // or set BLACKWALL_API_KEY
baseUrl: 'https://blackwalltier.com', // override for self-hosted/staging
mode: 'enforce', // 'observe' (default) | 'enforce'
cautionAction: 'approve', // 'approve' (default) | 'block' | 'allow'
shouldGate: (toolName) => toolName !== 'no_op', // per-tool opt-out
maxInputBytes: 8 * 1024, // truncate forecast payload over this size
forecastTimeoutMs: 15_000, // per-hook timeout
onEvent: (event) => myTelemetry(event), // optional telemetry hook
});
```
### Telemetry events emitted via `onEvent`
`register`, `skipped`, `observed`, `stop`, `require_approval`, `forecast_error`, `observe_error`, `observed_outcome`.
## How it works
```
ββββββββββββββββββββββββββββββββ
β OpenClaw agent decides to β
β call tool X with params Y β
βββββββββββββββ¬βββββββββββββββββ
β
before_tool_call
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββ
β blackwall plugin: forecast(X, Y) β
β β β
β STOP β return { block: true, β
β blockReason: "..." } β
β CAUTION β return { requireApproval: {...}} β
β GO β return undefined β
ββββββββββββββββββββ¬ββββββββββββββββββββββββ
β (if not blocked)
βΌ
tool actually runs
β
after_tool_call
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββ
β blackwall plugin: observe(forecast_id, β
β outcome_class) β
β matched / diverged / aborted β
ββββββββββββββββββββββββββββββββββββββββββββ
```
Fail-open: if BLACK_WALL is unreachable, the hook logs a warning and lets the tool proceed. A BLACK_WALL outage will never take down your agent.
## Architecture
```
ββββββββββββββββββββββββββββββββββββββββββββββββ
β BLACK_WALL HTTP API (stable, versioned) β
ββββββββββββββββββββββββββββββββββββββββββββββββ
β²
ββββββββββββββββββββββββββββββββββββββββββββββββ
β blackwall-mcp/lib (shared client logic) β
β - forecast() β
β - observe() β
ββββββββββββββββββββββββββββββββββββββββββββββββ
β²
ββββββββββββββββββββββββββββββββββββββββββββββββ
β blackwall-openclaw-plugin (this package) β
β - before_tool_call hook β
β - after_tool_call hook β
ββββββββββββββββββββββββββββββββββββββββββββββββ
β²
OpenClaw
```
When OpenClaw ships breaking changes to its plugin contract, only this package needs to update. The HTTP API, the `blackwall-mcp` library, the MCP server, and every other BLACK_WALL integration remain insulated.
## Links
- Site & docs: https://blackwalltier.com
- Free API key: https://blackwalltier.com/dashboard/keys
- Failure-mode taxonomy (28 named red-flag codes): https://blackwalltier.com/failure-modes
- npm: [`blackwall-openclaw-plugin`](https://www.npmjs.com/package/blackwall-openclaw-plugin) Β· [`blackwall-mcp`](https://www.npmjs.com/package/blackwall-mcp)
- Source: https://github.com/bluetieroperations-create/blackwall-openclaw-plugin
- Sibling plugin (ElizaOS): [`blackwall-eliza-guardrail`](https://www.npmjs.com/package/blackwall-eliza-guardrail)
## License
MIT
voice
Comments
Sign in to leave a comment