Skip to main content

AHP unified safety supervision framework for AI agent runtimes.

Project description

ClawSentry — AHP Supervision Gateway

Python 3.11+ | 3135 regression tests | Protocol ahp.1.0

ClawSentry is the Python reference implementation of AHP (Agent Harness Protocol) — a unified security supervision gateway for multi-agent frameworks. Deployed as a sidecar, it normalizes runtime events from different frameworks (a3s-code, Claude Code, Codex, Gemini CLI, OpenClaw) into a unified protocol, passes them through a three-layer progressive risk evaluation pipeline, and produces real-time decisions (allow / block / modify / defer) with complete audit trails.

Core goal: Eliminate cross-framework policy duplication and observability fragmentation through a "protocol-first, decision-centralized" approach to agent security governance.


Table of Contents


Three-Layer Decision Model

                    Event Flow 100%
                        |
                 +------v------+
                 |  L1 Rules   |  < 0.3ms, D1-D6 composite scoring
                 +------+------+
                        |
            +-----------+-----------+
            v           v           v
     LOW (allow)   MEDIUM (?)   CRITICAL (block)
      ~60%          ~30%          ~10%
         |              |           |
         |       +------v------+   |
         |       |  L2 Semantic |   |  Pluggable LLM, < 3s
         |       +------+------+   |
         |              |          |
         |       +------v------+   |
         |       |  L3 Agent   |   |  Multi-turn tool use, < 30s
         |       +------+------+   |
         |              |          |
         v              v          v
       allow      allow/block    block
Layer Implementation Latency Activation
L1 Rules D1-D6 six-dimensional scoring + short-circuit rules < 0.3ms Always on
L2 Semantic RuleBased / LLM / Composite + 25 attack patterns < 3s CS_LLM_PROVIDER
L3 Agent AgentAnalyzer + ReadOnlyToolkit + SkillRegistry < 30s CS_L3_ENABLED=true

When L3 is enabled, the env-driven factory now assembles a nested chain: CompositeAnalyzer([CompositeAnalyzer([RuleBasedAnalyzer, LLMAnalyzer]), AgentAnalyzer]). That keeps the three-layer contract honest: L3 is only considered after the combined L2 result is known.

Current deterministic L3 trigger reasons are: manual_l3_escalate, suspicious_pattern, cumulative_risk, and high_risk_complex_payload. The new suspicious_pattern path currently covers five bounded sequence families:

  • secret-access-plus-network sequences
  • progressive read -> write -> exec -> sudo escalation chains
  • temporary-file staging followed by outbound exfiltration
  • reconnaissance commands followed by sudo-backed privileged execution
  • repeated secret harvest followed by archive/packaging preparation

For runtime observability, the top-level trigger_reason remains stable, while suspicious-pattern traces now also expose a finer trigger_detail family such as secret_plus_network or secret_harvest_archive. That detail is now visible in clawsentry watch, the dashboard runtime feed, and the session replay timeline without changing the alert taxonomy.

The archive/packaging branch is intentionally narrow: ordinary local tar/zip packaging of build artifacts does not trigger by itself, even if the session previously read secrets. The packaging step must visibly involve sensitive material before it upgrades into suspicious_pattern. Decode-style restore flows such as base64 -d are also excluded from the archive signal; the heuristic is intentionally biased toward export/packaging behavior. Extract-style local restore flows such as tar -x* / tar x*, unzip, gunzip, and gzip -dc are also excluded, so unpacking a local archive does not get conflated with secret export. Archive inspection flows such as tar tf and tar --list are excluded as well, so listing local archive contents does not get conflated with export. Local gzip/zip inspection and validation flows such as gzip -l, zip -T, and zip -sf are also excluded, so checking an archive does not get conflated with packaging or export. Their long-option equivalents such as gzip --list, zip --test, and zip --show-files are excluded as well. The inspection matcher is now command-token-aware rather than raw-substring based, so zip -t no longer accidentally aliases gzip -tv. gzip -t* validation flows such as gzip -tv and gzip --test are excluded explicitly. Archive-family detection now also keys off actual shell command heads, so printed examples such as echo "zip ..." or heredoc bodies that merely contain archive commands do not get conflated with real export behavior. Wrapped shell execution such as bash -lc "zip ..." and sh -c 'tar ...' is now unwrapped before matching, so real nested archive/export commands are still detected while quoted echo text remains excluded. Bounded python -c launchers such as os.system("zip ...") and subprocess.run(['tar', ...]) are also unwrapped now, while pure debug printing such as python -c "print('zip ...')" remains excluded. That bounded launcher path now treats subprocess.Popen(...) consistently as well, even after command normalization lowercases the outer python -c payload. That same bounded launcher path now also recognizes subprocess.check_call(...) and subprocess.check_output(...) when their first argument is a constant command string or argv list, while quoted debug text remains excluded. It now also recognizes subprocess.getoutput(...) and subprocess.getstatusoutput(...) for bounded constant-string command flows, while quoted debug text remains excluded. The same bounded launcher path now also recognizes os.popen(...) for constant-string command flows, while quoted debug text remains excluded. It now also recognizes bounded os.execlp(...) argv flows, while quoted debug text remains excluded. It now also recognizes bounded os.spawnlp(...) argv flows after skipping the leading mode argument, while quoted debug text remains excluded. It now also recognizes bounded os.execvp(...) argv-list flows, while quoted debug text remains excluded. It now also recognizes bounded os.spawnvp(...) argv-list flows after skipping the leading mode argument, while quoted debug text remains excluded. It now also recognizes bounded os.execv(...) argv-list flows while ignoring the leading executable path argument, and quoted debug text remains excluded. It now also recognizes bounded os.spawnv(...) argv-list flows while skipping the leading mode and executable path arguments, and quoted debug text remains excluded. It now also recognizes bounded os.execve(...) argv-list flows while ignoring the leading executable path argument and trailing env mapping, and quoted debug text remains excluded. It now also recognizes bounded os.spawnve(...) argv-list flows while skipping the leading mode and executable path arguments plus the trailing env mapping, and quoted debug text remains excluded. It now also recognizes bounded os.execvpe(...) argv-list flows while ignoring the leading executable name argument and trailing env mapping, and quoted debug text remains excluded. It now also recognizes bounded os.spawnvpe(...) argv-list flows while skipping the leading mode and executable name arguments plus the trailing env mapping, and quoted debug text remains excluded. It now also recognizes bounded vararg os.execl(...) and os.spawnl(...) flows, plus bounded os.execle(...) and os.spawnle(...) flows that carry a trailing env mapping, while quoted debug text remains excluded. The same bounded launcher path now also reconstructs literal argv-list concatenation such as ['tar'] + ['-czf', ...], so constant split-sequence helpers still map back to archive/export behavior without evaluating dynamic expressions. It also reconstructs literal command-string concatenation such as 'zip /tmp/secrets.zip ' + '/app/.env ...', so bounded os.system(...) and subprocess.*(..., shell=True) constant helpers still map back to archive/export behavior without evaluating dynamic expressions. It also reconstructs literal separator joins such as ' '.join(['zip', ...]), plus direct shlex.join(['zip', ...]), so bounded command-string helpers still map back to archive/export behavior when the entire sequence is statically literal. It also reconstructs bounded f-strings and positional str.format(...) helpers when every fragment still reduces to a supported constant command string, so helper-composed archive/export commands remain visible without falling through to variable evaluation. It also reconstructs bounded % formatting and direct subprocess.list2cmdline(...) helpers when their inputs remain fully literal, so more shell-oriented command builders still map back to archive/export behavior without widening into dynamic expression evaluation. It also reconstructs bounded string.Template(...).substitute(...) and literal_template.format_map(literal_dict) helpers when every template input remains fully literal, so named-template command builders remain visible without falling through into general expression evaluation. It now also reconstructs bounded named str.format(...) helpers when every keyword value remains fully literal, so named-placeholder command builders remain visible without widening into dynamic expression evaluation. It now also reconstructs bounded expanded-keyword str.format(**{...}) helpers when every mapping entry remains fully literal, so literal expanded placeholder mappings remain visible without widening into variable evaluation. It now also reconstructs bounded string.Template(...).substitute(literal_dict) helpers when every mapping entry remains fully literal, so positional template mapping helpers remain visible without widening into variable evaluation. It now also reconstructs bounded string.Template(...).safe_substitute(...) helpers, including literal positional mappings, when every mapping entry remains fully literal, so safe-substitution command builders remain visible without widening into variable evaluation. It now also reconstructs bounded literal dict(...) mapping constructors when every keyword value remains fully literal, so constructor-based mapping helpers remain visible without widening into dynamic mapping evaluation.

D1-D6 Risk Dimensions

Dim Target Score Notes
D1 Tool type risk (bash=3, read_file=0) 0-3
D2 Target path sensitivity (/etc/passwd=3, /tmp=0) 0-3
D3 Command pattern (rm -rf=3, ls=0) 0-3
D4 Session accumulation (high-risk event count) 0-2
D5 Agent trust level 0-2
D6 Injection detection (prompt injection heuristics) 0-3 E-4, multiplier formula

Composite scoring: base = max(D1,D2,D3)*w1 + D4*w2 + D5*w3, then score = base * (1.0 + 0.5 * D6/3.0)

Short-circuit rules: D1=3 & D2>=2 -> CRITICAL | D3=3 -> CRITICAL | D1=D2=D3=0 -> LOW

Post-Action Security Fence

For POST_ACTION events, an async post-action analyzer inspects command outputs for:

  • Indirect prompt injection patterns
  • Data exfiltration (10 types: curl, wget, base64, DNS, etc.)
  • Obfuscation (Shannon entropy, encoding)

Tiered response: LOG_ONLY / MONITOR / ESCALATE / EMERGENCY

Trajectory Analyzer

Multi-step attack sequence detection across session events:

  • exfil-credential: credential file read -> outbound transfer
  • backdoor-install: download -> permission change -> persistence
  • recon-then-exploit: enumeration -> targeted attack
  • secret-harvest: multiple secret file accesses
  • staged-exfil: staging to temp -> bulk exfiltration

Self-Evolving Pattern Repository (E-5)

High-risk events automatically extract candidate attack patterns. Patterns progress through CANDIDATE -> EXPERIMENTAL -> STABLE -> DEPRECATED lifecycle with confidence scoring. Controlled by CS_EVOLVING_ENABLED.


Architecture

 +------------------------------------------------------------------+
 |              Framework Runtime Layer                               |
 |  +------------------+          +-------------------------+        |
 |  | a3s-code (Rust)   |          |  OpenClaw (TypeScript)   |        |
 |  |   stdio Hook      |          |  WS exec.approval        |        |
 |  +--------+---------+          +----------+--------------+        |
 +-----------|-------------------------------|---------------------+
             |                               |
 +-----------v-------------------------------v---------------------+
 |                    Adapter Layer                                  |
 |  +------------------+     +------------------------------+      |
 |  |  A3SCodeAdapter   |     |  OpenClawAdapter + WS Client |      |
 |  |  + Harness bridge |     |  + Webhook Receiver          |      |
 |  +--------+---------+     +----------+-------------------+      |
 +-----------|--------------------------|------------------------+
             |   UDS / HTTP (JSON-RPC)  |
 +-----------v--------------------------v------------------------+
 |              ClawSentry  -  AHP Supervision Gateway             |
 |                                                                  |
 |  +----------+  +----------+  +----------+  +---------------+   |
 |  | L1 Rules |->| L2 LLM   |->| L3 Agent |->| Decision      |   |
 |  | D1-D6    |  | Semantic |  | Toolkit  |  | Router        |   |
 |  | <0.3ms   |  | <3s      |  | <30s     |  | allow/block/  |   |
 |  +----------+  +----------+  +----------+  | modify/defer  |   |
 |                                              +-------+-------+   |
 |  +---------------+  +--------------+  +----------v--------+    |
 |  | D6 Injection  |  | Post-Action  |  | TrajectoryStore   |    |
 |  | Detector      |  | Analyzer     |  | SQLite audit      |    |
 |  +---------------+  +--------------+  +-------------------+    |
 |                                                                  |
 |  +---------------+  +--------------+  +-------------------+    |
 |  | SessionRegistry|  | AlertRegistry|  | PatternEvolution  |    |
 |  | + EventBus/SSE|  | + AttackPats |  | Self-evolving     |    |
 |  +---------------+  +--------------+  +-------------------+    |
 |                                                                  |
 |  +-------------------+                +-------------------+     |
 |  | DetectionConfig   |                | Web Dashboard     |     |
 |  | 17 CS_* env vars  |                | React SPA at /ui  |     |
 |  +-------------------+                +-------------------+     |
 +------------------------------------------------------------------+

Design principles:

Principle Description
Protocol-first Solve cross-framework interop before stacking policies
Centralized decisions All final decisions from Gateway; adapters don't decide
Dual-channel pre-action sync blocking, post-action async audit
Escalate only L2/L3 can only raise risk level, never lower it
Fail-closed High-risk ops blocked when Gateway unreachable

Quick Start

Install

pip install clawsentry            # Base
pip install "clawsentry[llm]"     # + LLM semantic analysis
pip install "clawsentry[all]"     # Everything

# Development
git clone <repo-url> && cd ClawSentry
pip install -e ".[dev]"

OpenClaw Users

clawsentry init openclaw --auto-detect   # Auto-detect ~/.openclaw config
clawsentry init openclaw --setup         # Configure OpenClaw settings
clawsentry start --framework openclaw    # Project env only (no ~/.openclaw edits)
clawsentry start --framework openclaw --setup-openclaw
clawsentry gateway                        # Start (auto-detects OpenClaw)
clawsentry watch                          # Real-time monitoring
# Browser: http://127.0.0.1:8080/ui      # Web dashboard

a3s-code Users

clawsentry init a3s-code
clawsentry gateway
clawsentry watch

Framework Compatibility

Framework Integration mode Pre-action interception Post-action observation Main dependency Maturity
a3s-code Explicit SDK transport + clawsentry-harness Yes Yes Agent code must wire SessionOptions.ahp_transport High
openclaw WebSocket approvals + webhook receiver Yes Yes ~/.openclaw/ must be configured for gateway exec + callbacks Medium-high
codex Session JSONL watcher + optional native hooks No by default; optional tested PreToolUse(Bash) preflight Yes Session logs / optional .codex/hooks.json must be reachable Medium
gemini-cli Gemini CLI native command hooks Yes; real BeforeTool deny smoke proven for run_shell_command Yes, with post-tool caveat Project .gemini/settings.json managed hooks; global home only with explicit --gemini-home Medium-high (real_beforetool_block_supported)
claude-code Host hooks + clawsentry-harness Yes Yes ~/.claude/settings.json hooks must remain installed Medium

Operational boundary notes:

  • codex remains an observation-first path by default; clawsentry init codex --setup can add managed native hooks without replacing user/OMX hooks. The tested host-blocking surface is intentionally narrow: PreToolUse(Bash) can deny when Gateway returns block/defer; other Codex native events stay async advisory/observational.
  • gemini-cli uses Gemini native command hooks via clawsentry init gemini-cli --setup, defaulting to project-local .gemini/settings.json. Real Gemini CLI hook execution is proven through the provider tool path, including a real BeforeTool deny smoke for run_shell_command after Gemini shell-tool canonicalization. Do not treat Kimi/OpenAI-compatible endpoints as directly supported by Gemini CLI; Kimi remains a future Google-GenAI-compatible proxy/adapter spike.
  • Gemini managed hook commands redirect diagnostics away from stderr and fail open if the harness process itself cannot start, because Gemini can interpret plain stderr text as hook output.
  • a3s-code should be documented as explicit SDK transport wiring, not .a3s-code/settings.json auto-loading.
  • openclaw and claude-code provide strong coverage only when host-side setup remains intact.

For a machine-readable local view of the same boundaries, run clawsentry integrations status --json. The command now also emits per-framework readiness diagnostics with concrete next steps, and clawsentry start reuses the same summary in its startup banner.


CLI Commands

Command Description
clawsentry gateway Start Gateway (auto-detects framework, starts WS/Webhook as needed)
clawsentry start Auto-init + Gateway + watch; supports --frameworks, explicit --setup-openclaw, and startup readiness summaries
clawsentry integrations status Inspect enabled frameworks, host-side diagnostics, framework capability summaries, and per-framework readiness
clawsentry watch SSE real-time display (--filter/--json/--no-color/--interactive)
clawsentry init <framework> Initialize config (a3s-code/claude-code/codex/gemini-cli/openclaw)
clawsentry harness a3s-code stdio bridge subprocess
clawsentry rules lint Authoring-time validation for attack patterns + review skills (--json)
clawsentry rules dry-run Replay sample canonical events against current rule surfaces (--events, --json; accepts JSON object / array / JSONL)
clawsentry rules report Write combined lint/dry-run JSON and optional markdown dashboard artifacts for CI or release evidence (--output, optional --events, optional --summary-markdown)

Rule Governance

clawsentry rules is the rule-governance entrypoint. It is intentionally narrow: it validates and dry-runs the existing YAML rule assets instead of introducing a runtime DSL for L1/L2/L3 control flow.

clawsentry rules lint --json
clawsentry rules dry-run --events examples/sample-events.jsonl --json
clawsentry rules report \
  --output artifacts/rules-report.json \
  --events examples/sample-events.jsonl \
  --summary-markdown artifacts/rules-dashboard.md

rules lint reports schema / duplicate / conflict findings for attack patterns and review skills. rules dry-run replays sample canonical events from a JSON object, JSON array, or JSONL file through the current attack-pattern matcher and review-skill selector so authors can preview policy effects before rollout. rules report combines those checks into a stable JSON artifact with status, exit_code, per-check summaries, the deterministic fingerprint, and optional dry-run results for CI/release records. When --summary-markdown is provided, it also writes a human-readable rollout dashboard summarizing status, findings, and dry-run event coverage.


API Endpoints

All endpoints require Authorization: Bearer <token> (except /health and /ui).

Method Path Description
POST /ahp JSON-RPC sync decision
POST /ahp/resolve DEFER resolution proxy
GET /ahp/patterns List attack patterns (core + evolved)
POST /ahp/patterns/confirm Confirm/reject evolved pattern
GET /health Health check (no auth)
GET /report/summary Cross-framework aggregate stats
GET /report/sessions Active sessions + risk ranking
GET /report/session/{id} Session trajectory replay
GET /report/session/{id}/risk Session risk detail + D1-D6 timeline
GET /report/stream SSE real-time events
GET /report/alerts Alert list (filter: severity/acknowledged)
POST /report/alerts/{id}/acknowledge Acknowledge alert
GET /ui Web dashboard SPA (no auth)

Web Dashboard

Built-in React SPA operator console at /ui. Light-first premium dashboard with real-time SSE data and a summary-first landing view.

clawsentry start prints a Web UI URL such as http://127.0.0.1:8080/ui?token=.... The page saves that token to sessionStorage, strips ?token= from the address bar, and then calls the Gateway. Manual login uses the same CS_AUTH_TOKEN. An invalid token / 401 message means the value does not match CS_AUTH_TOKEN; Gateway unavailable means the local Gateway cannot be reached and is not a credential failure. In proxy-heavy shells, set NO_PROXY=localhost,127.0.0.1,::1 for loopback Gateway calls.

Page Features
Dashboard Operator brief + live decision feed + metric cards + risk overview
Sessions Active sessions + D1-D6 radar + risk curve + decision timeline
Alerts Alert table + severity filter + acknowledge + SSE auto-push
DEFER Panel Pending decisions + countdown + Allow/Deny buttons

Tech stack: React 18 + TypeScript + Vite + recharts + lucide-react


Project Structure

src/clawsentry/
|-- gateway/                           # Core supervision engine
|   |-- models.py                      # Unified data models (CanonicalEvent/Decision/RiskSnapshot)
|   |-- server.py                      # FastAPI HTTP + UDS + Auth + SSE + static files
|   |-- stack.py                       # One-click start: Gateway + OpenClaw runtime + DEFER
|   |-- policy_engine.py               # L1 rules + L2 Analyzer integration
|   |-- risk_snapshot.py               # D1-D6 six-dimensional risk assessment
|   |-- injection_detector.py          # D6 injection detection (weak/strong patterns + canary)
|   |-- post_action_analyzer.py        # Post-action security fence (exfil/injection/obfuscation)
|   |-- trajectory_analyzer.py         # Multi-step attack sequence detection (5 sequences)
|   |-- pattern_matcher.py             # Attack pattern matching engine (25 OWASP ASI patterns)
|   |-- pattern_evolution.py           # Self-evolving pattern repository (E-5)
|   |-- detection_config.py            # DetectionConfig (17 tunable CS_* env vars)
|   |-- semantic_analyzer.py           # L2 pluggable semantic (Protocol + 3 implementations)
|   |-- llm_provider.py                # LLM Provider base (Anthropic/OpenAI)
|   |-- llm_factory.py                 # Environment-driven analyzer builder
|   |-- agent_analyzer.py              # L3 review Agent (single-turn MVP + multi-turn runtime)
|   |-- review_toolkit.py              # L3 ReadOnlyToolkit (7 read-only tools incl. transcript/session risk)
|   |-- review_skills.py               # L3 SkillRegistry (YAML load/select)
|   |-- l3_trigger.py                  # L3 trigger policy (explicit trigger reasons)
|   |-- idempotency.py                 # Request idempotency cache
|   +-- skills/                        # 6 built-in review domain skills (YAML)
|-- adapters/                          # Framework adapters
|   |-- a3s_adapter.py                 # a3s-code Hook -> CanonicalEvent normalization
|   |-- a3s_gateway_harness.py         # a3s-code stdio bridge (JSON-RPC 2.0)
|   |-- openclaw_adapter.py            # OpenClaw main adapter (approval state machine)
|   |-- openclaw_normalizer.py         # OpenClaw event normalization
|   |-- openclaw_ws_client.py          # OpenClaw WS client (listen + resolve)
|   |-- openclaw_webhook_receiver.py   # OpenClaw Webhook secure receiver
|   |-- openclaw_gateway_client.py     # OpenClaw -> Gateway RPC client
|   |-- openclaw_approval.py           # Approval lifecycle state machine
|   |-- openclaw_bootstrap.py          # OpenClaw unified config factory
|   +-- webhook_security.py            # Token + HMAC verification
|-- cli/                               # Unified CLI
|   |-- main.py                        # clawsentry entry (init/gateway/watch/harness)
|   |-- init_command.py                # init + --setup + --auto-detect
|   |-- start_command.py               # Framework detection + start routing
|   |-- watch_command.py               # watch SSE terminal + --interactive DEFER
|   |-- dotenv_loader.py               # .env.clawsentry auto-load
|   +-- initializers/                  # Framework initializers (openclaw/a3s_code)
|-- ui/                                # Web security dashboard (React SPA)
|   |-- src/                           # TypeScript source
|   +-- dist/                          # Pre-built artifacts (shipped with pip)
+-- tests/                             # Test suite (3135 regression tests)

Configuration

Core

Variable Default Description
CS_AUTH_TOKEN (disabled) HTTP Bearer token (>= 32 chars recommended)
CS_HTTP_HOST 127.0.0.1 HTTP bind address
CS_HTTP_PORT 8080 HTTP port
CS_UDS_PATH /tmp/clawsentry.sock UDS listen path
CS_TRAJECTORY_DB_PATH /tmp/clawsentry-trajectory.db SQLite trajectory file

Detection Tuning (CS_*)

Variable Default Description
CS_COMPOSITE_WEIGHT_MAX_D123 0.6 Weight for max(D1,D2,D3)
CS_COMPOSITE_WEIGHT_D4 0.25 Weight for D4 session risk
CS_COMPOSITE_WEIGHT_D5 0.15 Weight for D5 trust
CS_D6_INJECTION_MULTIPLIER 0.5 D6 multiplier coefficient
CS_THRESHOLD_CRITICAL 2.2 Score threshold for CRITICAL
CS_THRESHOLD_HIGH 1.5 Score threshold for HIGH
CS_THRESHOLD_MEDIUM 0.8 Score threshold for MEDIUM
CS_L2_BUDGET_MS 3000 L2 analysis time budget (ms)
CS_ATTACK_PATTERNS_PATH (built-in) Custom attack patterns YAML
CS_EVOLVING_ENABLED false Enable self-evolving pattern repository
CS_EVOLVED_PATTERNS_PATH (none) Path for evolved patterns YAML
CS_POST_ACTION_EMERGENCY 0.9 Post-action EMERGENCY tier threshold
CS_POST_ACTION_ESCALATE 0.7 Post-action ESCALATE tier threshold
CS_POST_ACTION_MONITOR 0.4 Post-action MONITOR tier threshold

LLM

Variable Description
CS_LLM_PROVIDER anthropic / openai
CS_LLM_BASE_URL Custom API endpoint
CS_LLM_MODEL Model name
CS_L3_ENABLED Enable L3 review Agent
CS_L3_MULTI_TURN Force L3 multi_turn/single-turn runtime mode (false keeps MVP single-turn)
CS_L3_ADVISORY_ASYNC_ENABLED Auto-create frozen advisory snapshots after high/critical decisions or high+ trajectory alerts (default off; automatic snapshots do not run a real review scheduler)
CS_L3_HEARTBEAT_REVIEW_ENABLED Reserved heartbeat/idle advisory snapshot review trigger (default off; no timer-only review is started by the current implementation)
CS_L3_ADVISORY_PROVIDER_ENABLED Explicitly enable the advisory provider worker (default off; dry-run/degraded unless provider/model/key are explicit and dry-run is disabled)
CS_L3_ADVISORY_PROVIDER Advisory provider shell to select (openai / anthropic); intentionally does not inherit CS_LLM_PROVIDER
CS_L3_ADVISORY_MODEL Advisory worker model label; intentionally does not inherit CS_LLM_MODEL
CS_L3_ADVISORY_BASE_URL Advisory worker OpenAI-compatible endpoint used only when provider execution is explicitly enabled
CS_L3_ADVISORY_PROVIDER_DRY_RUN Advisory provider worker dry-run gate; defaults to true, and must be explicitly false before bridging to a real LLM provider
CS_L3_ADVISORY_TEMPERATURE Advisory provider temperature; defaults to 1.0 for OpenAI-compatible smoke compatibility
CS_L3_ADVISORY_DEADLINE_MS Advisory provider completion deadline in milliseconds (default 30000)
CS_L3_ADVISORY_RUN_REAL_SMOKE Pytest real-provider smoke gate; defaults to skip
CS_L3_ADVISORY_SMOKE_STRIP_PROXY_ENV Manual smoke proxy hygiene; defaults to true

When CS_L3_ENABLED=true, the env-driven factory now defaults L3 to multi_turn. Set CS_L3_MULTI_TURN=false to force the older single-turn MVP behavior. The clawsentry test-llm probe surfaces the active L3 mode and trigger reason in its detail output so operators can verify the runtime path.

L3 Advisory Review and Full Review

L3 advisory review adds a separate bounded evidence workflow without changing canonical decisions. Operators can create a frozen l3_evidence_snapshot over a bounded trajectory record range, then attach an l3_advisory_review result marked advisory_only=true. When CS_L3_ADVISORY_ASYNC_ENABLED=true, high/critical decisions and high+ trajectory alerts automatically create frozen advisory snapshots. These records are surfaced through report/session/replay payloads and SSE events (l3_advisory_snapshot, l3_advisory_review) but never retroactively mutate the original allow / block decision or run a real background L3 review by default.

The explicit llm_provider worker runner adds provider execution safety gates. It reads only CS_L3_ADVISORY_PROVIDER_* settings, does not inherit the synchronous L2/L3 CS_LLM_* provider, and returns degraded advisory reviews for disabled, missing-key, missing-model, unsupported provider, or dry-run paths without making network calls unless the dry-run gate is explicitly disabled.

For operator-controlled readiness checks, use the packaged manual smoke helper:

CS_L3_ADVISORY_PROVIDER_ENABLED=true \
CS_L3_ADVISORY_PROVIDER=openai \
CS_L3_ADVISORY_MODEL=gpt-advisory-smoke \
OPENAI_API_KEY=sk-... \
python -m clawsentry.devtools.l3_advisory_provider_smoke \
  --output-report l3-advisory-provider-smoke-readiness.md

The provider smoke defaults to dry-run and proves that no network call is made until explicitly enabled. Set CS_L3_ADVISORY_PROVIDER_DRY_RUN=false only for an operator-controlled manual real-provider smoke, and use --require-completed to fail unless the provider returns a completed advisory review. Pytest real-network smoke additionally requires CS_L3_ADVISORY_RUN_REAL_SMOKE=true; otherwise it is skipped by default.

Operators can also trigger a bounded full advisory review explicitly:

POST /report/session/{session_id}/l3-advisory/full-review

This endpoint creates an operator_full_review frozen snapshot, queues one advisory job, and can either leave it queued (run=false) or execute exactly one runner (deterministic_local, fake_llm, or gated llm_provider). The response is always advisory-only and includes canonical_decision_mutated=false.

CLI equivalent:

clawsentry l3 full-review \
  --session <session-id> \
  --runner deterministic_local \
  --queue-only

OpenClaw

Variable Description
OPENCLAW_WS_URL OpenClaw Gateway WS URL
OPENCLAW_OPERATOR_TOKEN Operator token
OPENCLAW_ENFORCEMENT_ENABLED Enable enforcement mode
OPENCLAW_WEBHOOK_TOKEN Webhook auth token
OPENCLAW_WEBHOOK_SECRET Webhook HMAC secret

Session Enforcement

Variable Default Description
AHP_SESSION_ENFORCEMENT_ENABLED false Enable session-level cumulative enforcement
AHP_SESSION_ENFORCEMENT_THRESHOLD 3 High-risk event accumulation threshold
AHP_SESSION_ENFORCEMENT_ACTION defer Action on trigger (defer/block/l3_require)

Running Tests

pip install -e ".[dev]"

# Full suite
python -m pytest src/clawsentry/tests/ -v --tb=short
# Expected: 3135 passed, 4 skipped

# E2E (requires LLM API key)
A3S_SDK_E2E=1 python -m pytest src/clawsentry/tests/ -v --tb=short
# Runs additional a3s-code SDK E2E coverage when a3s_code, agent.hcl, and credentials are available

# By module
python -m pytest src/clawsentry/tests/test_risk_and_policy.py -v
python -m pytest src/clawsentry/tests/test_injection_detector.py -v
python -m pytest src/clawsentry/tests/test_post_action_analyzer.py -v
python -m pytest src/clawsentry/tests/test_trajectory_analyzer.py -v
python -m pytest src/clawsentry/tests/test_pattern_evolution.py -v
python -m pytest src/clawsentry/tests/test_ws_gateway_integration.py -v
python -m pytest src/clawsentry/tests/test_openclaw_e2e.py -v
python -m pytest src/clawsentry/tests/test_detection_config.py -v

Decision Effects, Session Quarantine, and Rewrite

ClawSentry can attach request-only decision_effects metadata to canonical decisions without changing the stable allow/block/modify/defer verdict set.

  • block + action_scope=session marks a session as quarantined; v1 blocks subsequent same-session pre_action events but does not claim host process termination.
  • modify + modified_payload + rewrite_effect supports audited command/tool-input rewrite. The host response may include the replacement payload; persisted replay/reporting surfaces keep hashes and redacted previews by default.
  • Adapter outcomes are recorded separately via adapter_effect_result records and /ahp/adapter-effect-result, so unsupported hosts are reported as degraded/unsupported instead of falsely enforced.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clawsentry-0.5.7.tar.gz (901.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clawsentry-0.5.7-py3-none-any.whl (933.0 kB view details)

Uploaded Python 3

File details

Details for the file clawsentry-0.5.7.tar.gz.

File metadata

  • Download URL: clawsentry-0.5.7.tar.gz
  • Upload date:
  • Size: 901.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clawsentry-0.5.7.tar.gz
Algorithm Hash digest
SHA256 9a6f13630ce1a729258b5c306e7855ce16dbed83f5962cc01febd234e69fc24a
MD5 c81da19f2c09a9d603c883bcbc4c2673
BLAKE2b-256 74d27d2b931a9ab3df79d77b9bb88493e6ecba1f0ed6764dfa9de610e2b043f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for clawsentry-0.5.7.tar.gz:

Publisher: publish.yml on Elroyper/ClawSentry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file clawsentry-0.5.7-py3-none-any.whl.

File metadata

  • Download URL: clawsentry-0.5.7-py3-none-any.whl
  • Upload date:
  • Size: 933.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clawsentry-0.5.7-py3-none-any.whl
Algorithm Hash digest
SHA256 4b7da77f22ef9418ca43b35fbfaf0320f436357952085a7ecb70e69aeb3b2011
MD5 e3c9997171836cc7e89b8eb121d8cc29
BLAKE2b-256 e4954710425b8d91b8f16767ddb314a44cd023ab47e9131471c5f2447418f698

See more details on using hashes here.

Provenance

The following attestation bundles were made for clawsentry-0.5.7-py3-none-any.whl:

Publisher: publish.yml on Elroyper/ClawSentry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page