Action Gate
Runtime owner-scoped enforcement for shared agent channels.
Action Gate sits in front of outbound sends and protects a scope (channel, thread, or shared surface) by giving it a single owner_agent. Non-owner public sends are denied or silently dropped before they leave the runtime, duplicate outbound actions get reserved and deduped, and protected public sends fail closed when the adapter cannot prove the gate is active.
scripts/sync-superada-to-clawhub.mjs on every push to main.h-mascot/agent-action-gate (canonical Action Gate repo)
Canonical source: https://github.com/h-mascot/agent-action-gate/tree/main
One-shot install into a host plugins/ directory, then the auto installer registers the plugin with the running runtime.
git clone --depth=1 https://github.com/h-mascot/agent-action-gate.git /tmp/agent-action-gate && mkdir -p plugins && cp -R /tmp/agent-action-gate/plugins/openclaw-action-gate plugins/openclaw-action-gate && (cd plugins/openclaw-action-gate && pnpm install --prod && pnpm run build) && openclaw plugins enable openclaw-action-gate git clone --depth=1 https://github.com/h-mascot/agent-action-gate.git /tmp/agent-action-gate && mkdir -p plugins && cp -R /tmp/agent-action-gate/plugins/openclaw-action-gate plugins/openclaw-action-gate cd plugins/openclaw-action-gate && pnpm install --prod && pnpm run build && openclaw plugins enable openclaw-action-gate cat > action-gate.json <<'JSON'
{
"scopes": {
"shared-room": { "owner_agent": "book", "mode": "enforce", "non_owner": "deny" }
}
}
JSON openclaw gateway restart && openclaw plugins list | grep action-gate Configuration is what you wanted. Enforcement is what happened. The verify script is the receipt.
bash plugins/openclaw-action-gate/scripts/verify.sh --scope shared-room --non-owner ada openclaw plugins list | grep action-gate action-gate enforce plugins/action-gate openclaw plugins inspect action-gate --hooks before_incoming_action, before_outbound_message, after_outbound_message bash plugins/action-gate/verify.sh --scope shared-room --non-owner ada decision=deny reason=non_owner audit=recorded bash plugins/action-gate/verify.sh --scope shared-room --owner book --send "ack" decision=allow reason=owner audit=recorded ssh enterprise@100.104.229.62 "action-gate verify --scope shared-room --non-owner ada" decision=deny reason=non_owner audit=recorded bash plugins/action-gate/verify.sh --probe-direct-paths direct_paths=covered bypasses=none Disable the plugin with the running runtime first, then remove the staged plugin directory. The audit store stays so you can prove the rollout happened.
openclaw plugins disable openclaw-action-gate && rm -rf plugins/openclaw-action-gate /home/henrymascot/.openclaw/plugins/openclaw-action-gate What problem it solves
Shared agent channels are attractive because they make collaboration visible, but they also become a concurrency surface. Two agents can see the same request, both have live outbound paths, and the wrong one can reply, or both can reply, before any prompt reminder can hold the line. Action Gate moves the answer to the runtime: who owns this scope, what should happen when a non-owner tries to publish, and what counts as proof that the live system is enforcing it.
- One owner per protected scope (channel, thread, or class of shared surface).
- Non-owner public sends denied, silently dropped, or held before they leave.
- Duplicate outbound actions reserved, deduped, and audited.
- Fail-closed for protected public sends when the adapter cannot prove the gate is active.
- Verification readback from every runtime that can still send, not just one.
Overview
Action Gate is a runtime plugin. It does not change agent prompts, prompts are guidance, not a control boundary. It hooks the outbound send path on OpenClaw and Hermes, applies a per-scope policy, and writes compact evidence of every decision to the audit store. The point is to make outbound authority measurable instead of aspirational.
Configure
The plugin reads action-gate.json from the working directory of the protected agent. A scope declares an owner_agent, a mode (observe, enforce, disabled, or frozen_public_lane), and a non_owner policy (deny, silent_drop, or hold). Use observe first if you want a read-only window into the live decisions before flipping to enforce.
{
"default_mode": "observe",
"scopes": {
"shared-room": { "owner_agent": "book", "mode": "enforce", "non_owner": "deny" },
"ops-private": { "owner_agent": "scotty", "mode": "enforce", "non_owner": "hold" }
}
} Usage
Once installed and configured, Action Gate runs automatically. It reserves an outbound action before send, decides allow or deny based on the scope policy, and writes an audit record after the send completes. Operators do not call the plugin directly. Agents publish as usual, and the gate decides for them. To intentionally move ownership, change the owner_agent for the scope and reload the gateway. To intentionally publish from a non-owner, do it on a non-protected scope or temporarily set the scope to observe mode and accept the audit trail.
Troubleshooting
When something looks off, check the live decision, not the config file. The useful question is "what did the runtime actually do?", and the audit store answers it.
- A protected send silently dropped: read the audit record for the scope. Most silent drops are non_owner policy hits from an agent that should not have been speaking.
- Plugin loaded but mode says disabled: action-gate.json probably has default_mode=disabled or the scope override says mode=disabled. Edit the policy and reload the gateway.
- Verification fails on a single runtime: that is the point. A green receipt from OpenClaw and noise from Hermes means the gate is partial. Block the second writer or extend the plugin install.
- Direct CLI sends bypass the gate: the verify.sh --probe-direct-paths step is the place to see which paths are not covered. Either route them through the plugin or block them at the adapter.
- Owner cannot send: check that owner_agent matches the actual sender identity, not just the role. The audit record will show the identity mismatch.
Verification
Configuration is what you wanted. Enforcement is what happened. The verify.sh script runs the same six checks as the verification list above and prints a per-runtime receipt. A receipt is "good" only when every runtime that can send into the protected scope returns the same decision.
Supported platforms
Action Gate ships for both runtimes that have a live public-send path for the crew: OpenClaw and Hermes. The hook surface is intentionally narrow so both runtimes can implement it without forking the policy model.
- OpenClaw: plugin hooks around before_incoming_action, before_outbound_message, after_outbound_message.
- Hermes: plugin hooks plus hard-egress wrapper artifacts around the send paths.
- A runtime that does not register the required hooks cannot claim enforcement for a protected scope, and protected public sends from that runtime will fail closed until the hook load is proven.
Source availability
Action Gate ships from the canonical h-mascot/agent-action-gate repository. The repo holds the live OpenClaw plugin (plugins/openclaw-action-gate) and the Hermes plugin in dev (plugins/hermes-action-gate). The design and runtime contract stay public on superada.ai, the installable code is now the real source linked above.
- Canonical source root: h-mascot/agent-action-gate (verified reachable on main, ships openclaw-action-gate today).
- Hermes Action Gate (plugins/hermes-action-gate) lives in the same repo and is exposed on this site as a Draft/dev entry until its hard-egress wrapper artifacts land.
- ClawHub download: the canonical openclaw-action-gate package is mirrored to ClawHub as superada-plugin-openclaw-action-gate for install-from-the-page convenience.
- Follow h-mascot/agent-action-gate/commits/main for ongoing release notes.