← Back to Plugins
Voice

Safeguard Audit

lykeion-dev By lykeion-dev 👁 22 views ▲ 0 votes

OpenClaw native plugin: tool-call auditing and safeguard with external LLM judgment

GitHub

Configuration Example

{
  "plugins": {
    "allow": ["mimo-search", "safeguard-audit"],
    "entries": {
      "safeguard-audit": {
        "enabled": true,
        "hooks": {
          "allowConversationAccess": true,
          "timeoutMs": 20000
        },
        "config": {
          "safeguard": {
            "enabled": true,
            "provider": "nvidia-nim",
            "model": "nvidia/nemotron-content-safety-reasoning-4b",
            "apiKeyEnv": "NVIDIA_API_KEY",
            "timeoutMs": 10000,
            "failBehavior": "open"
          },
          "sessionFilter": {
            "mode": "whitelist",
            "agents": ["main"]
          },
          "rejection": {
            "threshold": 2,
            "window": 5,
            "fallbackMode": "switch",
            "fallbackModel": "z-ai/glm-5.1"
          }
        }
      }
    }
  }
}

README

# Safeguard Audit Plugin

OpenClaw ネイティブプラグイン。外部 watchdog スクリプト (`watchdog.sh` + `safeguard_daemon.py`) のツール呼び出し監査機能を、OpenClaw の Plugin Hook に移植。

**対象: OpenClaw >= 2026.5.17**

## ⚠️ safeguard モデル選定の注意点

### 推奨: ルールベースの軽量モデル

safeguard は**ツール呼び出しのたびに**発火するため、安価で高速なモデルを選択してください。

**推奨モデル:**
- `nvidia/nemotron-content-safety-reasoning-4b` — 専用の安全判定モデル。ルールベースの評価に最適
- `openai/gpt-oss-safeguard-20b` — OpenRouter 経由。安全判定に特化したオープンモデル
- その他の軽量な safety/content-safety モデル

**非推奨:**
- GPT-4o, Claude Sonnet 等の高額汎用モデル — 1回の呼び出しが $0.01〜$0.10 程度。100回/日の利用で $1〜$10/日
- reasoning モデル — 推論時間が長く、ツール呼び出し全体のレイテンシに影響

### 設計前提

- safeguard モデルは**自由テキスト形式のルール**(システムプロンプト)を受け取り、JSON で判定を返す
- `safeguard.systemPrompt` でルールを自由に記述可能
- 汎用 LLM でも動作するが、**安全判定に特化したモデル**のほうが速く安価
- `safeguard.timeoutMs` でタイムアウトを設定し、遅延を制御

### コスト目安

| モデル | 1回あたり | 100回/日 | 備考 |
|--------|----------|---------|------|
| nemotron-4b | ~$0.001 | ~$0.10/日 | 推奨。最速 |
| gpt-oss-safeguard-20b | ~$0.005 | ~$0.50/日 | OpenRouter 経由 |
| GPT-4o-mini | ~$0.01 | ~$1.00/日 | 汎用。高額 |
| Claude Sonnet | ~$0.05 | ~$5.00/日 | 非推奨 |

## watchdog との対応関係

| watchdog の動作 | plugin の実現方法 |
|----------------|-----------------|
| `call_safeguard()` → 外部LLM審査 | `before_tool_call` 内 `fetch()` |
| `check_line()` → 危険パターン検出 | `detectDanger()` (config で上書き可能) |
| `should_monitor_session()` → フィルタ | `sessionFilter` config |
| 注意メッセージ + 再開 | `fallbackMode: "warn"` → `requireApproval` |
| モデル切替 + 再開 | `fallbackMode: "switch"` → `mutateConfigFile` + `block` |
| abort (chat.abort) | `fallbackMode: "block"` → `block: true` |
| `safeguard-prompt.txt` → システムプロンプト | `safeguard.systemPrompt` (config で上書き) |
| `EXEC_PATTERNS` → 危険コマンドパターン | `safeguard.execPatterns` (config で上書き) |
| `DANGEROUS_PATHS` → 危険ファイルパス | `safeguard.dangerousPaths` (config で上書き) |

## セットアップ

### 1. ファイルをデプロイ

```bash
cp -r safeguard-audit-plugin/ ~/.openclaw/extensions/safeguard-audit/
```

### 2. openclaw.json に設定追加

```json
{
  "plugins": {
    "allow": ["mimo-search", "safeguard-audit"],
    "entries": {
      "safeguard-audit": {
        "enabled": true,
        "hooks": {
          "allowConversationAccess": true,
          "timeoutMs": 20000
        },
        "config": {
          "safeguard": {
            "enabled": true,
            "provider": "nvidia-nim",
            "model": "nvidia/nemotron-content-safety-reasoning-4b",
            "apiKeyEnv": "NVIDIA_API_KEY",
            "timeoutMs": 10000,
            "failBehavior": "open"
          },
          "sessionFilter": {
            "mode": "whitelist",
            "agents": ["main"]
          },
          "rejection": {
            "threshold": 2,
            "window": 5,
            "fallbackMode": "switch",
            "fallbackModel": "z-ai/glm-5.1"
          }
        }
      }
    }
  }
}
```

### 3. 環境変数

```bash
export NVIDIA_API_KEY="your-nvidia-api-key"
```

### 4. Gateway 再起動

```bash
openclaw gateway restart
```

## 設定項目(全量)

### safeguard

| 項目 | デフォルト | 説明 |
|------|----------|------|
| `enabled` | `true` | 外部LLM審査の有効/無効 |
| `provider` | `"openrouter"` | API プロバイダ (openrouter/openai-compatible/cohere/groq/mistral/dashscope/nvidia-nim/local) |
| `apiUrl` | (プロバイダ依存) | API URL の直接指定。設定時はプロバイダのデフォルトURLを上書き |
| `apiKeyEnv` | `"SAFEGUARD_API_KEY"` | API キーの環境変数名 |
| `model` | `"openai/gpt-oss-safeguard-20b"` | 審査用モデル |
| `systemPrompt` | (組み込み) | システムプロンプトの全文上書き |
| `timeoutMs` | `15000` | API タイムアウト (ms) |
| `failBehavior` | `"open"` | API失敗時: `open`=許可, `closed`=ブロック |
| `execPatterns` | (組み込み26件) | exec コマンドの危険パターン `{pattern, desc}` の配列で全文上書き |
| `dangerousPaths` | (組み込み8件) | 危険ファイルパスの配列で全文上書き |

### sessionFilter

| 項目 | デフォルト | 説明 |
|------|----------|------|
| `mode` | `"blacklist"` | `whitelist`=指定のみ監視, `blacklist`=指定以外を監視 |
| `agents` | `[]` | agent ID リスト |
| `providers` | `[]` | プロバイダ リスト |

### audit

| 項目 | デフォルト | 説明 |
|------|----------|------|
| `logFile` | `"safeguard-audit.jsonl"` | ログファイルパス |
| `logAllCalls` | `false` | 全ツール呼び出しを記録 (危険な呼び出しのみでない) |
| `maxLogSizeMb` | `10` | ログサイズ上限 (MB) |

### rejection

| 項目 | デフォルト | 説明 |
|------|----------|------|
| `threshold` | `2` | 連続拒否回数で強制 abort |
| `window` | `5` | 拒否カウントのターン窓 |
| `fallbackMode` | `"block"` | 後述 |
| `fallbackModel` | (なし) | `switch` モード時の切替先モデル |

### fallbackMode の3つの動作

| モード | watchdog での相当 | 動作 |
|--------|-----------------|------|
| `"block"` | chat.abort | ツール呼び出しをブロック。LLM にブロック理由を返す |
| `"warn"` | 注意メッセージ + 再開 | `requireApproval` でユーザーに承認を求める。60秒で自動deny |
| `"switch"` | モデル切替 + 再開 | `mutateConfigFile()` でモデルを切替えてからブロック |

## 技術詳細

### 使用する Plugin Hook (2026.5.17)

| Hook | 用途 | priority |
|------|------|----------|
| `before_tool_call` | 危険検出 + LLM審査 + ブロック/承認 | 100 |
| `after_tool_call` | 実行後ログ | 0 |
| `llm_input` | 会話コンテキストキャプチャ | 0 |
| `message_received` | コンテキストfallback | 0 |

### 処理フロー

```
全ツール呼び出し → before_tool_call 発火
  → sessionFilter でフィルタ
  → detectDanger() でパターンマッチ
  → 危険でない → pass through (LLM呼ばない)
  → 危険 → callSafeguardAPI() で外部LLM起動
  → APPROVE → pass through
  → REJECT → fallbackMode に応じた動作:
      "block"  → block: true
      "warn"   → requireApproval (ユーザー承認ダイアログ)
      "switch" → mutateConfigFile() でモデル切替 + block
```
voice

Comments

Sign in to leave a comment

Loading comments...