@aporthq/aport-agent-guardrails 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/bin/openclaw +14 -14
- package/docs/PROVIDER.md +6 -6
- package/docs/QUICKSTART_OPENCLAW_PLUGIN.md +42 -408
- package/docs/RELEASE.md +3 -2
- package/docs/frameworks/openclaw.md +123 -39
- package/extensions/openclaw-aport/CHANGELOG.md +8 -2
- package/extensions/openclaw-aport/MIGRATION.md +22 -375
- package/extensions/openclaw-aport/README.md +72 -362
- package/extensions/openclaw-aport/api-client.js +22 -0
- package/extensions/openclaw-aport/audit.js +32 -0
- package/extensions/openclaw-aport/decision.js +21 -0
- package/extensions/openclaw-aport/index.js +169 -591
- package/extensions/openclaw-aport/local-evaluator.js +303 -0
- package/extensions/openclaw-aport/openclaw.plugin.json +5 -5
- package/extensions/openclaw-aport/package-lock.json +2 -2
- package/extensions/openclaw-aport/package.json +27 -6
- package/extensions/openclaw-aport/tool-mapping.js +89 -0
- package/package.json +1 -1
- package/extensions/openclaw-aport/index.ts +0 -547
- package/extensions/openclaw-aport/test.js +0 -356
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ The security concern is that agent tools and skills can execute sensitive action
|
|
|
97
97
|
|
|
98
98
|
| Framework | Doc | Integration | Install |
|
|
99
99
|
|-----------|-----|--------------|--------|
|
|
100
|
-
| **OpenClaw** | [docs/frameworks/openclaw.md](docs/frameworks/openclaw.md) |
|
|
100
|
+
| **OpenClaw** | [docs/frameworks/openclaw.md](docs/frameworks/openclaw.md) | **Plugin:** `before_tool_call` via `openclaw-aport` | `npx @aporthq/aport-agent-guardrails openclaw` |
|
|
101
101
|
| **Cursor** | [docs/frameworks/cursor.md](docs/frameworks/cursor.md) | `beforeShellExecution` / `preToolUse` hooks → writes `~/.cursor/hooks.json`. **Runtime enforcement is the bash hook;** the Node package `@aporthq/aport-agent-guardrails-cursor` is a helper only (Evaluator, `getHookPath()`). | `npx @aporthq/aport-agent-guardrails cursor` |
|
|
102
102
|
| **Claude Code** | [docs/frameworks/claude-code.md](docs/frameworks/claude-code.md) | PreToolUse hook → writes `~/.claude/settings.json` (Claude Code format; not Cursor). | `npx @aporthq/aport-agent-guardrails claude-code` |
|
|
103
103
|
| **LangChain / LangGraph** | [docs/frameworks/langchain.md](docs/frameworks/langchain.md) | **Python:** `APortCallback` (`on_tool_start`) | `npx @aporthq/aport-agent-guardrails langchain` then `pip install aport-agent-guardrails-langchain` + `aport-langchain setup` |
|
|
@@ -126,13 +126,18 @@ npx @aporthq/aport-agent-guardrails
|
|
|
126
126
|
# or: npx @aporthq/aport-agent-guardrails openclaw | cursor | claude-code | langchain | crewai | deerflow | n8n
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
**Python (LangChain, CrewAI, or DeerFlow):**
|
|
129
|
+
**Python (LangChain, CrewAI, or DeerFlow):** Use the Python CLI directly via `uvx` or an installed package:
|
|
130
|
+
```bash
|
|
131
|
+
uvx --from aport-agent-guardrails aport setup --framework=langchain
|
|
132
|
+
# or --framework=crewai / deerflow
|
|
133
|
+
```
|
|
134
|
+
Or install the package first:
|
|
130
135
|
```bash
|
|
131
136
|
pip install aport-agent-guardrails
|
|
132
137
|
aport setup --framework=langchain
|
|
133
138
|
# or --framework=crewai / deerflow
|
|
134
139
|
```
|
|
135
|
-
Then
|
|
140
|
+
Then install the framework-specific Python package and follow the printed integration step for your framework.
|
|
136
141
|
|
|
137
142
|
This runs the **passport wizard** and writes config for your framework. Follow the **next steps** printed at the end (e.g. restart Cursor; or for CrewAI: by default install `aport-agent-guardrails-crewai` for released CrewAI, or opt into native-provider mode if your CrewAI build supports it).
|
|
138
143
|
|
package/bin/openclaw
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# OpenClaw + APort: interactive setup
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# Works from a repo checkout or from the published npm package via npx.
|
|
4
|
+
# One run secures OpenClaw: creates a passport or wires a hosted agent_id,
|
|
5
|
+
# installs the APort plugin, writes config, and installs guardrail wrappers.
|
|
5
6
|
# After setup, start OpenClaw with the generated config (e.g. --config ~/.openclaw/config.yaml).
|
|
6
7
|
#
|
|
7
8
|
# Usage: ./bin/openclaw [agent_id]
|
|
@@ -216,8 +217,12 @@ if true; then
|
|
|
216
217
|
echo " ✅ Plugin installed successfully"
|
|
217
218
|
PLUGIN_INSTALLED=true
|
|
218
219
|
else
|
|
219
|
-
echo "
|
|
220
|
+
echo " ❌ Plugin installation failed."
|
|
221
|
+
echo " OpenClaw did not accept the plugin bundle, so setup is stopping here"
|
|
222
|
+
echo " instead of writing plugin config that points at a broken install."
|
|
223
|
+
echo " Retry after fixing the bundle or install it manually:"
|
|
220
224
|
echo " openclaw plugins install -l $APORT_PLUGIN_PATH"
|
|
225
|
+
exit 1
|
|
221
226
|
fi
|
|
222
227
|
echo ""
|
|
223
228
|
|
|
@@ -322,7 +327,7 @@ YAML
|
|
|
322
327
|
# Passport file location (in aport/ subdir)
|
|
323
328
|
passportFile: $PASSPORT_FILE
|
|
324
329
|
|
|
325
|
-
#
|
|
330
|
+
# Legacy compatibility field; current plugin versions use the built-in JS local evaluator
|
|
326
331
|
guardrailScript: $CONFIG_DIR/.skills/aport-guardrail-bash.sh
|
|
327
332
|
YAML
|
|
328
333
|
fi
|
|
@@ -433,26 +438,21 @@ YAML
|
|
|
433
438
|
'{ mode: $mode, passportFile: $pf, guardrailScript: $gs, failClosed: true, allowUnmappedTools: ($allow_unmapped == "true") } + (if $mode == "api" then { apiUrl: $api_url } else {} end)')
|
|
434
439
|
fi
|
|
435
440
|
|
|
436
|
-
if jq --argjson cfg "$CONFIG_JSON"
|
|
441
|
+
if jq --argjson cfg "$CONFIG_JSON" '
|
|
437
442
|
.plugins = (.plugins // {}) |
|
|
438
443
|
.plugins.entries = (.plugins.entries // {}) |
|
|
439
444
|
.plugins.entries["openclaw-aport"] = ((.plugins.entries["openclaw-aport"] // {}) | .enabled = true | .config = $cfg) |
|
|
440
|
-
.plugins.load = (.plugins.load // {}) |
|
|
441
|
-
.plugins.load.paths = (
|
|
442
|
-
((.plugins.load.paths // []) | map(select((type == "string" and contains("/openclaw-aport")) | not))) + [$plugin_path]
|
|
443
|
-
) |
|
|
444
445
|
.plugins.installs = (.plugins.installs // {}) |
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
| .installPath = $plugin_path)
|
|
446
|
+
del(.plugins.installs["openclaw-aport"]) |
|
|
447
|
+
.plugins.load = (.plugins.load // {}) |
|
|
448
|
+
.plugins.load.paths = ((.plugins.load.paths // []) | map(select((type == "string" and contains("/openclaw-aport")) | not)))
|
|
449
449
|
' "$OPENCLAW_JSON" > "$OPENCLAW_JSON.tmp" 2>/dev/null && { backup_file "$OPENCLAW_JSON"; mv "$OPENCLAW_JSON.tmp" "$OPENCLAW_JSON"; }; then
|
|
450
450
|
if [ "$USE_HOSTED_PASSPORT" = true ]; then
|
|
451
451
|
echo " ✅ Merged plugin config into $OPENCLAW_JSON (mode=$PLUGIN_MODE, hosted passport, allowUnmappedTools=$ALLOW_UNMAPPED)"
|
|
452
452
|
else
|
|
453
453
|
echo " ✅ Merged plugin config into $OPENCLAW_JSON (mode=$PLUGIN_MODE, allowUnmappedTools=$ALLOW_UNMAPPED)"
|
|
454
454
|
fi
|
|
455
|
-
echo " ✅
|
|
455
|
+
echo " ✅ Removed stale source-linked OpenClaw plugin paths from $OPENCLAW_JSON"
|
|
456
456
|
fi
|
|
457
457
|
fi
|
|
458
458
|
|
package/docs/PROVIDER.md
CHANGED
|
@@ -8,7 +8,7 @@ APort ships a generic `OAPGuardrailProvider` for both Python and TypeScript. It
|
|
|
8
8
|
Framework defines interface APort implements it
|
|
9
9
|
──────────────────────── ───────────────────
|
|
10
10
|
DeerFlow: GuardrailProvider ←── Python OAPGuardrailProvider
|
|
11
|
-
|
|
11
|
+
TypeScript frameworks with a GuardrailProvider seam ←── TypeScript OAPGuardrailProvider
|
|
12
12
|
Your framework: same shape ←── Same class, same language
|
|
13
13
|
```
|
|
14
14
|
|
|
@@ -45,23 +45,23 @@ guardrails:
|
|
|
45
45
|
```typescript
|
|
46
46
|
import { OAPGuardrailProvider } from "@aporthq/aport-agent-guardrails-core";
|
|
47
47
|
|
|
48
|
-
const provider = new OAPGuardrailProvider({ framework: "
|
|
48
|
+
const provider = new OAPGuardrailProvider({ framework: "your-framework" });
|
|
49
49
|
const decision = await provider.evaluate(request); // async
|
|
50
50
|
const decision = provider.evaluateSync(request); // sync
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
**Supported frameworks:**
|
|
53
|
+
**Supported frameworks:** TypeScript frameworks that expose a `GuardrailProvider` interface. Current public OpenClaw uses the plugin path documented in `docs/frameworks/openclaw.md`; a native provider path would be additive when upstream support exists.
|
|
54
54
|
|
|
55
|
-
**Config:** `~/.
|
|
55
|
+
**Config:** `~/.aport/<framework>/config.yaml` or the framework-specific path your host expects
|
|
56
56
|
|
|
57
|
-
**
|
|
57
|
+
**Example TypeScript host config:**
|
|
58
58
|
```yaml
|
|
59
59
|
guardrails:
|
|
60
60
|
enabled: true
|
|
61
61
|
provider:
|
|
62
62
|
use: "@aporthq/aport-agent-guardrails-core"
|
|
63
63
|
config:
|
|
64
|
-
framework: "
|
|
64
|
+
framework: "your-framework"
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
## What the provider does
|
|
@@ -1,310 +1,48 @@
|
|
|
1
|
-
# QuickStart: OpenClaw Plugin
|
|
1
|
+
# QuickStart: OpenClaw Plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Set up deterministic, platform-level guardrails for OpenClaw with one public command.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Quick start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npx @aporthq/aport-agent-guardrails
|
|
8
|
+
npx @aporthq/aport-agent-guardrails openclaw
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
This uses the [npm package](https://www.npmjs.com/package/@aporthq/aport-agent-guardrails): it downloads the package (policies + plugin), runs the setup wizard, installs the APort OpenClaw plugin, and runs a smoke test.
|
|
14
|
-
|
|
15
|
-
Then start OpenClaw with the generated config (e.g. `openclaw gateway start --config ~/.openclaw/config.yaml`). The plugin will enforce policies on every tool call.
|
|
16
|
-
|
|
17
|
-
**Alternative: clone the repo** (e.g. to hack on the code or use without npm):
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
git clone https://github.com/aporthq/aport-agent-guardrails.git && \
|
|
21
|
-
cd aport-agent-guardrails && \
|
|
22
|
-
git submodule update --init --recursive && \
|
|
23
|
-
./bin/openclaw
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
*Already have the repo?* From the repo root run: `./bin/openclaw`
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Why Use the Plugin?
|
|
31
|
-
|
|
32
|
-
| Approach | Deterministic? | Bypass Risk | Security Level |
|
|
33
|
-
|----------|----------------|-------------|----------------|
|
|
34
|
-
| **OpenClaw Plugin** ✅ | Yes | None | 🟢 Secure |
|
|
35
|
-
| AGENTS.md prompts | No | High | 🔴 Not secure |
|
|
36
|
-
|
|
37
|
-
**Bottom line:** With the plugin, the platform enforces policy before every tool execution. The AI cannot bypass it.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Installation (Automatic)
|
|
42
|
-
|
|
43
|
-
**Recommended:** Use `npx @aporthq/aport-agent-guardrails` (see top of this doc). If you cloned the repo instead, from the repo root run:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
./bin/openclaw
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The script will:
|
|
50
|
-
1. Ask for your OpenClaw config directory (default `~/.openclaw`)
|
|
51
|
-
2. Create your passport (OAP v1.0) there
|
|
52
|
-
3. Prompt to install the APort OpenClaw plugin
|
|
53
|
-
4. Ask for mode (default: **API**; or local) and generate `config.yaml` with plugin settings (passport path, guardrail script path, apiUrl for API mode)
|
|
54
|
-
5. Install guardrail wrappers in the config dir’s `.skills/` (including `aport-guardrail-bash.sh` used by the plugin in local mode)
|
|
55
|
-
6. **Update your passport** — the installer sets `allowed_commands: ["*"]` automatically so normal exec works with no manual editing. You only need to edit the passport later if you want to restrict commands more tightly.
|
|
56
|
-
7. Run a **self-check** (guardrail invoked the same way OpenClaw will use it); if it’s denied, the script exits with a clear message so you know the setup is incomplete.
|
|
57
|
-
8. Optionally install the APort skill and AGENTS.md rule, and run a smoke test
|
|
58
|
-
9. Verify plugin installation
|
|
59
|
-
|
|
60
|
-
**That's it!** Start OpenClaw with that config (e.g. `openclaw gateway start --config ~/.openclaw/config.yaml`). The plugin will enforce policies on every tool call; no extra steps required.
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Installation (Manual)
|
|
65
|
-
|
|
66
|
-
If you prefer manual installation:
|
|
67
|
-
|
|
68
|
-
### 1. Create Passport
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
./bin/aport-create-passport.sh --output ~/.openclaw/aport/passport.json
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### 2. Install Plugin
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
openclaw plugins install -l /path/to/aport-agent-guardrails/extensions/openclaw-aport
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 3. Configure Plugin
|
|
81
|
-
|
|
82
|
-
Create or edit `~/.openclaw/config.yaml`:
|
|
83
|
-
|
|
84
|
-
```yaml
|
|
85
|
-
plugins:
|
|
86
|
-
enabled: true
|
|
87
|
-
entries:
|
|
88
|
-
openclaw-aport:
|
|
89
|
-
enabled: true
|
|
90
|
-
config:
|
|
91
|
-
# Mode: "api" (default, recommended) or "local" (guardrail script, no network)
|
|
92
|
-
mode: api
|
|
93
|
-
|
|
94
|
-
# Passport file location
|
|
95
|
-
passportFile: ~/.openclaw/aport/passport.json
|
|
96
|
-
|
|
97
|
-
# For local mode: path to guardrail script
|
|
98
|
-
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
99
|
-
|
|
100
|
-
# Fail-closed: block on error (default: true)
|
|
101
|
-
failClosed: true
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
For **API mode (default)**, set:
|
|
105
|
-
```yaml
|
|
106
|
-
mode: api
|
|
107
|
-
apiUrl: https://api.aport.io
|
|
108
|
-
```
|
|
109
|
-
Set `APORT_API_KEY` in the environment if your API requires auth. Do not put `${APORT_API_KEY}` in the config file (OpenClaw will require the var to exist at load time).
|
|
110
|
-
|
|
111
|
-
### 4. Install Guardrail Scripts (local mode only)
|
|
112
|
-
|
|
113
|
-
If you **did not** run `./bin/openclaw`, you need the guardrail script for local mode. If you **did** run the setup script, it already created `CONFIG_DIR/.skills/aport-guardrail-bash.sh`; skip this step.
|
|
114
|
-
|
|
115
|
-
Otherwise:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
mkdir -p ~/.openclaw/.skills
|
|
119
|
-
# Create wrapper that points to this repo (replace /path/to with real path)
|
|
120
|
-
cat > ~/.openclaw/.skills/aport-guardrail-bash.sh << 'EOF'
|
|
121
|
-
#!/bin/bash
|
|
122
|
-
APORT_REPO_ROOT="/path/to/aport-agent-guardrails"
|
|
123
|
-
export OPENCLAW_PASSPORT_FILE="${OPENCLAW_PASSPORT_FILE:-$HOME/.openclaw/aport/passport.json}"
|
|
124
|
-
export OPENCLAW_DECISION_FILE="${OPENCLAW_DECISION_FILE:-$HOME/.openclaw/aport/decision.json}"
|
|
125
|
-
exec "$APORT_REPO_ROOT/bin/aport-guardrail-bash.sh" "$@"
|
|
126
|
-
EOF
|
|
127
|
-
chmod +x ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### 5. Verify Installation
|
|
11
|
+
Hosted passport:
|
|
131
12
|
|
|
132
13
|
```bash
|
|
133
|
-
|
|
134
|
-
openclaw plugins list | grep openclaw-aport
|
|
135
|
-
|
|
136
|
-
# Should show: openclaw-aport (enabled)
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## How It Works
|
|
142
|
-
|
|
143
|
-
```
|
|
144
|
-
User → AI: "Delete all log files"
|
|
145
|
-
↓
|
|
146
|
-
OpenClaw: AI wants to use tool "exec.run"
|
|
147
|
-
↓
|
|
148
|
-
Platform: Fires before_tool_call hook
|
|
149
|
-
↓
|
|
150
|
-
APort Plugin: Maps "exec.run" → "system.command.execute.v1"
|
|
151
|
-
↓
|
|
152
|
-
APort Plugin: Calls guardrail script/API
|
|
153
|
-
↓
|
|
154
|
-
Guardrail: Evaluates against passport + limits
|
|
155
|
-
↓
|
|
156
|
-
┌──────────┴──────────┐
|
|
157
|
-
│ │
|
|
158
|
-
ALLOW DENY
|
|
159
|
-
│ │
|
|
160
|
-
↓ ↓
|
|
161
|
-
Tool executes Returns { block: true, blockReason }
|
|
162
|
-
↓
|
|
163
|
-
OpenClaw throws error
|
|
164
|
-
↓
|
|
165
|
-
Tool NEVER executes
|
|
14
|
+
npx @aporthq/aport-agent-guardrails openclaw ap_your_agent_id
|
|
166
15
|
```
|
|
167
16
|
|
|
168
|
-
|
|
17
|
+
No repo clone is required.
|
|
169
18
|
|
|
170
|
-
|
|
19
|
+
## What the setup command does
|
|
171
20
|
|
|
172
|
-
|
|
21
|
+
1. Prompts for your OpenClaw config directory
|
|
22
|
+
2. Creates a local passport or wires a hosted `agent_id`
|
|
23
|
+
3. Installs the `openclaw-aport` plugin with `openclaw plugins install -l ...`
|
|
24
|
+
4. Writes plugin config into `config.yaml` and `openclaw.json`
|
|
25
|
+
5. Installs `aport-*` wrappers under `CONFIG_DIR/.skills/`
|
|
26
|
+
6. Runs a smoke test so you know the setup is complete
|
|
173
27
|
|
|
174
|
-
|
|
28
|
+
After setup, start OpenClaw with the generated config:
|
|
175
29
|
|
|
176
30
|
```bash
|
|
177
31
|
openclaw gateway start --config ~/.openclaw/config.yaml
|
|
178
32
|
```
|
|
179
33
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
Try a simple command that should be allowed:
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
# Via OpenClaw agent
|
|
186
|
-
"Run: node --version"
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
Expected: Command executes (allowed by passport limits)
|
|
190
|
-
|
|
191
|
-
### 3. Test Denied Action
|
|
192
|
-
|
|
193
|
-
Try a command that exceeds your passport limits:
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
# Via OpenClaw agent
|
|
197
|
-
"Delete all files in /tmp"
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Expected: Tool blocked with message:
|
|
201
|
-
```
|
|
202
|
-
🛡️ APort Policy Denied
|
|
34
|
+
## What gets installed
|
|
203
35
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
---
|
|
36
|
+
- `~/.openclaw/aport/passport.json` for local passport mode
|
|
37
|
+
- `~/.openclaw/config.yaml` with `plugins.entries.openclaw-aport`
|
|
38
|
+
- `~/.openclaw/openclaw.json` with matching plugin entry
|
|
39
|
+
- `~/.openclaw/.skills/aport-*` wrappers for manual checks and shell tooling
|
|
211
40
|
|
|
212
41
|
## Modes
|
|
213
42
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
### API Mode (default, recommended)
|
|
217
|
-
|
|
218
|
-
**Best for:** Production, full OAP policy (JSON Schema, assurance, evaluation rules), signed decisions, cloud kill switch, audit logs.
|
|
219
|
-
|
|
220
|
-
```yaml
|
|
221
|
-
config:
|
|
222
|
-
mode: api
|
|
223
|
-
passportFile: ~/.openclaw/aport/passport.json
|
|
224
|
-
apiUrl: https://api.aport.io
|
|
225
|
-
```
|
|
226
|
-
Set `APORT_API_KEY` in the environment only if your API requires auth.
|
|
227
|
-
|
|
228
|
-
**How it works:**
|
|
229
|
-
- Plugin loads local passport
|
|
230
|
-
- Sends passport + context to APort API
|
|
231
|
-
- API evaluates (passport NOT stored, stateless)
|
|
232
|
-
- Returns signed decision
|
|
233
|
-
- **Network required**
|
|
234
|
-
|
|
235
|
-
### Local Mode
|
|
236
|
-
|
|
237
|
-
**Best for:** Privacy, offline use, no network dependency
|
|
238
|
-
|
|
239
|
-
```yaml
|
|
240
|
-
config:
|
|
241
|
-
mode: local
|
|
242
|
-
passportFile: ~/.openclaw/aport/passport.json
|
|
243
|
-
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
**How it works:**
|
|
247
|
-
- Plugin calls local bash script
|
|
248
|
-
- Script evaluates policy using local passport (subset of OAP; see [Verification methods](VERIFICATION_METHODS.md))
|
|
249
|
-
- Returns decision (exit 0 = allow, exit 1 = deny)
|
|
250
|
-
- **No network required**
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Troubleshooting
|
|
255
|
-
|
|
256
|
-
### Plugin not loading
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# Check plugin list
|
|
260
|
-
openclaw plugins list
|
|
261
|
-
|
|
262
|
-
# Should show: openclaw-aport (enabled)
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
If not listed:
|
|
266
|
-
1. Verify installation: `openclaw plugins install -l /path/to/extensions/openclaw-aport`
|
|
267
|
-
2. Check config.yaml has `plugins.entries.openclaw-aport.enabled: true`
|
|
268
|
-
3. Restart OpenClaw gateway
|
|
269
|
-
|
|
270
|
-
### Tools not being blocked
|
|
271
|
-
|
|
272
|
-
Check:
|
|
273
|
-
1. **Plugin enabled?** `openclaw plugins list` should show `openclaw-aport (enabled)`
|
|
274
|
-
2. **Tool mapped?** See tool-to-policy mapping in plugin README
|
|
275
|
-
3. **Passport allows it?** The installer sets `allowed_commands: ["*"]` by default. If you intentionally tightened the allowlist, re-add the commands you need to `limits.system.command.execute.allowed_commands` in your passport.
|
|
276
|
-
4. **Script working?** Test directly:
|
|
277
|
-
```bash
|
|
278
|
-
~/.openclaw/.skills/aport-guardrail-bash.sh system.command.execute '{"command":"ls"}'
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Error: "Failed to run guardrail script"
|
|
282
|
-
|
|
283
|
-
Check:
|
|
284
|
-
1. Script exists: `ls -l ~/.openclaw/.skills/aport-guardrail-bash.sh`
|
|
285
|
-
2. Script executable: `chmod +x ~/.openclaw/.skills/aport-guardrail-bash.sh`
|
|
286
|
-
3. Script works: Run test command above
|
|
287
|
-
|
|
288
|
-
### Guardrail DENY / `oap.passport_version_mismatch`
|
|
289
|
-
|
|
290
|
-
If the guardrail denies every call and `~/.openclaw/aport/decision.json` (or `~/.openclaw/decision.json`) shows reason `oap.passport_version_mismatch` ("Passport spec version is 'unknown', expected 'oap/1.0'"):
|
|
291
|
-
|
|
292
|
-
1. **Passport must have `spec_version: "oap/1.0"`** (OAP spec). If your passport has only `"version": "1.0.0"` in metadata and no top-level `spec_version`, it was created by an older or non–spec-compliant tool.
|
|
293
|
-
2. **Limits must be nested per capability.** The verifier expects e.g. `limits["system.command.execute"]` with `allowed_commands`, `blocked_patterns`, not a flat `limits.allowed_commands` at the top level.
|
|
294
|
-
|
|
295
|
-
**Fix:** Re-run the installer so it can normalize the passport:
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
npx @aporthq/aport-agent-guardrails
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
Choose to overwrite the existing passport when prompted, or run the wizard with `--output` to a new file. The installer now ensures `spec_version: "oap/1.0"` and nested limits. If you prefer to fix the file manually, add `"spec_version": "oap/1.0"` at the top level and move any top-level `allowed_commands` / `blocked_patterns` under `limits["system.command.execute"]`. See [agent-passport/spec/oap](https://github.com/aporthq/agent-passport/tree/main/spec/oap) for the canonical schema.
|
|
302
|
-
|
|
303
|
-
---
|
|
304
|
-
|
|
305
|
-
## Configuration Reference
|
|
43
|
+
### API mode
|
|
306
44
|
|
|
307
|
-
|
|
45
|
+
Recommended for production.
|
|
308
46
|
|
|
309
47
|
```yaml
|
|
310
48
|
plugins:
|
|
@@ -319,33 +57,11 @@ plugins:
|
|
|
319
57
|
failClosed: true
|
|
320
58
|
```
|
|
321
59
|
|
|
322
|
-
|
|
60
|
+
Hosted passports use `agentId` instead of `passportFile`.
|
|
323
61
|
|
|
324
|
-
|
|
325
|
-
plugins:
|
|
326
|
-
enabled: true
|
|
327
|
-
entries:
|
|
328
|
-
openclaw-aport:
|
|
329
|
-
enabled: true
|
|
330
|
-
config:
|
|
331
|
-
# Mode: "api" (default) or "local"
|
|
332
|
-
mode: api
|
|
333
|
-
|
|
334
|
-
# Passport file location
|
|
335
|
-
passportFile: ~/.openclaw/aport/passport.json
|
|
336
|
-
|
|
337
|
-
# For local mode: path to guardrail script
|
|
338
|
-
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
339
|
-
|
|
340
|
-
# For API mode: APort API endpoint
|
|
341
|
-
apiUrl: https://api.aport.io # or your self-hosted API URL
|
|
342
|
-
# Optional: set APORT_API_KEY in the environment if your API requires auth
|
|
343
|
-
|
|
344
|
-
# Fail-closed: block on error (default: true)
|
|
345
|
-
failClosed: true
|
|
346
|
-
```
|
|
62
|
+
### Local mode
|
|
347
63
|
|
|
348
|
-
|
|
64
|
+
Best for offline or privacy-sensitive workflows.
|
|
349
65
|
|
|
350
66
|
```yaml
|
|
351
67
|
plugins:
|
|
@@ -356,115 +72,33 @@ plugins:
|
|
|
356
72
|
config:
|
|
357
73
|
mode: local
|
|
358
74
|
passportFile: ~/.openclaw/aport/passport.json
|
|
359
|
-
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
360
75
|
failClosed: true
|
|
361
76
|
```
|
|
362
77
|
|
|
363
|
-
|
|
78
|
+
Current plugin versions use a built-in JavaScript evaluator in local mode. The setup command still installs `aport-guardrail-bash.sh` for manual smoke tests and shell tooling, but the plugin does not depend on `child_process` or the bash script for local-mode enforcement.
|
|
364
79
|
|
|
365
|
-
##
|
|
80
|
+
## Development install
|
|
366
81
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
| OpenClaw Tool | APort Policy |
|
|
370
|
-
|---------------|--------------|
|
|
371
|
-
| `git.create_pr`, `git.merge`, `git.push` | `code.repository.merge.v1` |
|
|
372
|
-
| `exec.run`, `system.command.*`, `bash` | `system.command.execute.v1` |
|
|
373
|
-
| `message.send`, `messaging.*` | `messaging.message.send.v1` |
|
|
374
|
-
| `mcp.*` | `mcp.tool.execute.v1` |
|
|
375
|
-
| `session.create` | `agent.session.create.v1` |
|
|
376
|
-
| `tool.register` | `agent.tool.register.v1` |
|
|
377
|
-
| `payment.refund` | `finance.payment.refund.v1` |
|
|
378
|
-
| `payment.charge` | `finance.payment.charge.v1` |
|
|
379
|
-
| `data.export` | `data.export.create.v1` |
|
|
380
|
-
|
|
381
|
-
Unmapped tools are allowed (fail-open for flexibility).
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## Security Considerations
|
|
386
|
-
|
|
387
|
-
### Fail-Closed by Default
|
|
388
|
-
|
|
389
|
-
By default, `failClosed: true` means **any error blocks the tool**:
|
|
390
|
-
- Script not found → BLOCK
|
|
391
|
-
- API unreachable → BLOCK
|
|
392
|
-
- Invalid passport → BLOCK
|
|
393
|
-
|
|
394
|
-
This is secure-by-default. To fail-open (not recommended):
|
|
395
|
-
|
|
396
|
-
```yaml
|
|
397
|
-
config:
|
|
398
|
-
failClosed: false # Allow on error (NOT RECOMMENDED)
|
|
399
|
-
```
|
|
82
|
+
If you are developing from a local checkout:
|
|
400
83
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
Plugins run **in-process** with full access to OpenClaw. Only install from trusted sources:
|
|
404
|
-
- Official APort plugin (this)
|
|
405
|
-
- Your own forks/modifications
|
|
406
|
-
|
|
407
|
-
Use `plugins.allow` allowlist in config.yaml:
|
|
408
|
-
|
|
409
|
-
```yaml
|
|
410
|
-
plugins:
|
|
411
|
-
allow:
|
|
412
|
-
- openclaw-aport
|
|
413
|
-
- your-other-trusted-plugin
|
|
84
|
+
```bash
|
|
85
|
+
openclaw plugins install -l /path/to/aport-agent-guardrails/extensions/openclaw-aport
|
|
414
86
|
```
|
|
415
87
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
**With plugin:** AI **cannot** bypass policy enforcement. The platform calls `before_tool_call` before every tool.
|
|
419
|
-
|
|
420
|
-
**Without plugin (AGENTS.md only):** AI **can** bypass via:
|
|
421
|
-
- Prompt injection
|
|
422
|
-
- Forgetting to call guardrail
|
|
423
|
-
- Deciding action is "safe"
|
|
424
|
-
|
|
425
|
-
**Bottom line:** Plugin = deterministic. AGENTS.md = best-effort (not secure).
|
|
426
|
-
|
|
427
|
-
---
|
|
428
|
-
|
|
429
|
-
## Next Steps
|
|
430
|
-
|
|
431
|
-
1. **Run the setup (once):** From repo root: `./bin/openclaw`. Use the default config dir or choose a path.
|
|
432
|
-
2. **Choose "yes"** when prompted to install the plugin.
|
|
433
|
-
3. **Start OpenClaw** with the generated config: `openclaw gateway start --config <your-config-dir>/config.yaml` (e.g. `~/.openclaw/config.yaml`).
|
|
434
|
-
4. **Test enforcement:** Run the agent; try an allowed action (e.g. `node --version`) and one that should be blocked by your passport (e.g. `rm -rf /`). The plugin blocks before the tool runs.
|
|
435
|
-
5. **Customize passport:** Edit `<config-dir>/aport/passport.json` (or `<config-dir>/passport.json` for legacy) to adjust limits and allowed commands.
|
|
436
|
-
|
|
437
|
-
---
|
|
438
|
-
|
|
439
|
-
## Support
|
|
440
|
-
|
|
441
|
-
- **Full documentation:** [`extensions/openclaw-aport/README.md`](../extensions/openclaw-aport/README.md)
|
|
442
|
-
- **Issues:** [GitHub Issues](https://github.com/aporthq/aport-agent-guardrails/issues)
|
|
443
|
-
- **Discord:** [discord.gg/aport](https://discord.gg/aport)
|
|
444
|
-
|
|
445
|
-
---
|
|
446
|
-
|
|
447
|
-
## Summary
|
|
448
|
-
|
|
449
|
-
✅ **One command:** Run `./bin/openclaw` from the repo root to create passport, install plugin, write config and wrappers, and verify. You only need this once per config dir.
|
|
450
|
-
✅ **Deterministic enforcement:** The plugin runs before every tool; the platform enforces, the AI cannot bypass.
|
|
451
|
-
✅ **Fail-closed:** Blocks on error by default.
|
|
452
|
-
✅ **API (default) or local:** Full OAP via API, or local script for offline/privacy.
|
|
453
|
-
✅ **Zero OpenClaw core changes:** Uses the existing OpenClaw plugin API.
|
|
88
|
+
Public users should prefer the `npx @aporthq/aport-agent-guardrails openclaw` path.
|
|
454
89
|
|
|
455
|
-
|
|
90
|
+
## Runtime behavior
|
|
456
91
|
|
|
457
|
-
|
|
92
|
+
On every tool call:
|
|
458
93
|
|
|
459
|
-
|
|
94
|
+
1. OpenClaw fires `before_tool_call`
|
|
95
|
+
2. APort maps the OpenClaw tool to an OAP policy pack
|
|
96
|
+
3. APort evaluates the passport and limits
|
|
97
|
+
4. `allow` lets the tool run
|
|
98
|
+
5. `deny` returns `block: true` and the tool never executes
|
|
460
99
|
|
|
461
|
-
|
|
462
|
-
|------|----------------|
|
|
463
|
-
| You run `./bin/openclaw` | Script asks for config dir, creates passport, installs plugin, writes `config.yaml`, installs wrappers in `<config-dir>/.skills/`, and **updates the passport** with default `allowed_commands` (bash, sh, ls, mkdir, npm, etc.) so normal exec works. |
|
|
464
|
-
| `config.yaml` | Contains `passportFile` and `guardrailScript` pointing to `<config-dir>/aport/passport.json` and `<config-dir>/.skills/aport-guardrail-bash.sh`. |
|
|
465
|
-
| Passport allowlist | The installer sets `allowed_commands: ["*"]` automatically. No manual editing needed unless you want to restrict commands. |
|
|
466
|
-
| Wrapper script | `<config-dir>/.skills/aport-guardrail-bash.sh` is a small script that calls this repo’s `bin/aport-guardrail-bash.sh` with the same args and env (passport path, etc.). |
|
|
467
|
-
| You start OpenClaw | `openclaw gateway start --config <config-dir>/config.yaml` (or use that config when running the agent). |
|
|
468
|
-
| On every tool call | OpenClaw runs the plugin’s `before_tool_call` hook → plugin calls the guardrail script with tool name and params → script evaluates against passport and policy → allow = tool runs, deny = plugin returns `block: true` and the tool never runs. |
|
|
100
|
+
## Notes
|
|
469
101
|
|
|
470
|
-
|
|
102
|
+
- Current public OpenClaw integration is plugin-based
|
|
103
|
+
- No upstream native guardrail-provider merge is required for this path
|
|
104
|
+
- If setup cannot install the plugin, it now stops immediately instead of writing broken config
|
package/docs/RELEASE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Release process and version policy
|
|
2
2
|
|
|
3
|
-
**Current release:** 1.0.
|
|
3
|
+
**Current release:** 1.0.22 (see [CHANGELOG.md](../CHANGELOG.md)).
|
|
4
4
|
|
|
5
5
|
We keep **one version number** across all published packages (Node core, Python core, and every framework adapter). That avoids “core is 1.2 but CLI is 0.9” and keeps the story simple for users and support.
|
|
6
6
|
|
|
@@ -52,7 +52,8 @@ So: **root = CLI/setup**; **core = library**. We publish core so that (1) the ad
|
|
|
52
52
|
```
|
|
53
53
|
5. **CI (`.github/workflows/release.yml`)**: on tag push `v*`:
|
|
54
54
|
- **publish-npm**: publishes the **root** package `@aporthq/aport-agent-guardrails` (CLI) and workspace packages `@aporthq/aport-agent-guardrails-core`, `-langchain`, `-crewai`, `-cursor`, `-claude-code`, and `@aporthq/openclaw-aport` to npm. The **n8n** package is not published yet (coming soon). Uses `NPM_TOKEN` secret.
|
|
55
|
-
- **publish-python**: builds and publishes `aport-agent-guardrails`, `aport-agent-guardrails-langchain`, and `aport-agent-guardrails-crewai` to PyPI (uses `PYPI_TOKEN` secret).
|
|
55
|
+
- **publish-python**: builds and publishes `aport-agent-guardrails`, `aport-agent-guardrails-langchain`, and `aport-agent-guardrails-crewai` to PyPI (uses `PYPI_TOKEN` secret). Uploads use `--skip-existing`, so reruns or recovery releases can still publish any missing Python artifacts for the same version.
|
|
56
|
+
- **workflow_dispatch**: supports release recovery for an existing version after workflow fixes land on `main`.
|
|
56
57
|
- **create-release**: creates the GitHub Release with install notes for both ecosystems.
|
|
57
58
|
|
|
58
59
|
**PyPI**: In [PyPI project settings](https://pypi.org/help/#project-urls), set Repository and (if using trusted publishing) add this repo and workflow name **Release**. Otherwise configure the `PYPI_TOKEN` secret in the GitHub repo.
|