This episode extends OpenClaw beyond its built-in features: writing custom policy modules, integrating external data sources like databases and webhooks, and using advanced rule evaluation hooks for unique business needs.

In episode 15 you tuned OpenClaw's performance — sizing, evaluation optimization, and high availability. Now imagine needs that built-in features can't satisfy: blocking a transaction because the customer is on a company database blacklist, or applying a special policy that only applies to a specific region. Do you have to wait for an OpenClaw release? No — in episode 16 you write it yourself.
Episode 16 opens the extension box: custom policy modules, external data source integration, and advanced rule evaluation hooks. This is the point where OpenClaw transforms from a platform into a foundation for your organization's logic.
OpenClaw offers two ways to extend capabilities: policy modules and plugins. A policy module is a unit of evaluation logic that can be called from within a rule — like a function deciding true-false or returning a value. Plugins are broader: they can capture events, interact with the data plane, or provide new data sinks.
All extensions are registered with the control plane through a centralized resource. Because they're registered rather than hardcoded, extensions remain reviewable, versionable, and rollback-able through the GitOps process you built in episode 9. Every extension must declare its version — new releases won't spread silently:
apiVersion: openclaw.io/v1
kind: ExtensionRegistry
metadata:
name: registry
namespace: openclaw-system
spec:
modules:
- name: fraud-check
version: 2.1.0
source: ghcr.io/acme/openclaw-modules/fraud-check
- name: geo-risk
version: 1.4.0
source: ghcr.io/acme/openclaw-modules/geo-riskA policy module receives the request context and returns an evaluation result — for example allow, deny, or a risk score. Here's a simple module that decides whether a transaction exceeds a customer's daily limit:
def evaluate(ctx):
customer = ctx.lookup("customer_id")
amount = ctx.lookup("amount")
spent = ctx.data_store.get_daily_spend(customer)
if spent + amount > ctx.get_config("daily_limit"):
return {
"decision": "deny",
"reason": "daily_limit_exceeded",
}
return {"decision": "allow"}This module uses two important facilities: ctx.lookup to fetch request attributes, and ctx.data_store to pull external data — the bridge to the next section. After writing the module, test it independently before registering it:
openclaw module test daily-limit.py \
--input '{"customer_id": "u-42", "amount": 500}'
openclaw module lint daily-limit.pyOnly after passing tests is the module registered, then referenced from an ordinary policy:
apiVersion: openclaw.io/v1
kind: Policy
metadata:
name: daily-limit
namespace: openclaw-system
spec:
scope: mesh
rules:
- module: daily-limit
config:
daily_limit: 1000000
defaultAction: allowGood policy decisions often need data from outside the cluster: blacklists, prices, customer quotas. OpenClaw supports several data sources — databases, HTTP webhooks, even periodically synced tables. Each source is declared, and its loading is cached so it doesn't burden the original source:
apiVersion: openclaw.io/v1
kind: DataSource
metadata:
name: blacklist-db
namespace: openclaw-system
spec:
type: postgres
connection:
host: postgres.data.svc
database: risk
credentialsSecret: risk-db-credentials
refresh:
intervalSeconds: 60
cacheTtlSeconds: 55
query: |
SELECT id, region FROM blocked_entities
WHERE status = 'active'Two things must be noted: credentials come from a secret (not hardcoded), and there's a refresh with an interval and cache TTL. Stale data causes wrong decisions; data refreshed too often burdens the database. For data that changes rarely, periodic sync makes more sense than per-request queries.
An alternative for data that must be real-time is webhook lookup — the data plane asks an external service during evaluation:
apiVersion: openclaw.io/v1
kind: DataSource
metadata:
name: fraud-api
namespace: openclaw-system
spec:
type: webhook
endpoint: http://fraud-service:8080/check
timeoutMs: 150
cacheTtlSeconds: 2Note timeoutMs: 150 and cacheTtlSeconds: 2: a slow webhook will slow down every policy decision. Always set a short timeout and prepare fallback values when the source doesn't respond — a slightly delayed decision is better than one that hangs the request.
Warning
External data sources are new points of failure. Before enabling one, decide the behavior when the source dies: fail-closed (deny requests) for security-related sources, or fail-open (allow requests) for sources that only enrich decisions. Don't let a surprising default catch you mid-incident.
For the finest-grained control, OpenClaw provides hooks on the evaluation lifecycle. Hooks run at specific points — before the main evaluation, after a decision, or when side effects like blocking occur. This enables logic that's awkward to express as a rule:
apiVersion: openclaw.io/v1
kind: EvaluationHooks
metadata:
name: observability-hooks
namespace: openclaw-system
spec:
preDecision:
- module: enrich-context
postDecision:
- module: publish-decision
config:
topic: policy-decisions
onDeny:
- module: escalate-notify
config:
webhook: http://incident-bot:8080/hookpreDecision enriches the context before rules are evaluated — for example adding a risk score from a webhook. postDecision publishes every decision to a downstream system. onDeny runs special actions when a request is denied, like notifying the security team. The combination of hooks and modules gives you the freedom to build behavior truly specific to your organization — without waiting for an OpenClaw feature release.
Episode 16 showed that OpenClaw doesn't stop at built-in features: custom policy modules house unique business logic, external data sources bring policies to life with real data from databases and webhooks, and evaluation hooks give control at every point of the decision lifecycle. The platform can now be shaped to fit your needs, not just used as-is.
Key takeaways:
openclaw module test before registering them.One cluster is now flexible, but what if your organization has many clusters across several clouds at once? In episode 17 we step out of a single cluster: Multi-cluster & Hybrid Environments — cross-cluster policy management, gateway routing for multi-cluster traffic, and hybrid cloud networking considerations. See you there!