Policy Engine
The policy engine is the core of OnlyFence. It runs a pipeline of independent check functions in sequence. Each check evaluates a trade intent and returns pass or reject.
How It Works
Every action your agent requests goes through the policy pipeline before execution:
Check Interface
Every policy check implements the PolicyCheck interface:
interface PolicyCheck {
name: string;
description: string;
evaluate(intent: TradeIntent, ctx: PolicyContext): CheckResult;
}
interface CheckResult {
status: 'pass' | 'reject';
reason?: string;
detail?: string;
metadata?: Record<string, unknown>;
}
Current Checks
Token Allowlist
Verifies both the source and destination tokens are in the configured allowlist.
[chain.sui.allowlist]
tokens = ["SUI", "USDC", "USDT", "DEEP", "BLUE", "WAL"]
Spending Limit
Two-part check:
- Per-trade limit — trade USD value must be under
max_single_trade - Daily volume — rolling 24h total must stay under
max_24h_volume
[chain.sui.limits]
max_single_trade = 200.0
max_24h_volume = 500.0
Config-Driven Loading
Checks are registered based on which config sections exist. No config section = check not loaded.
Adding a New Check
Adding a new guardrail requires three steps:
- Implement
PolicyCheck— one file - Define config schema — one TOML section
- Register in loader — one line
Zero changes to existing checks or pipeline logic.
Planned Checks
Oracle Failure Handling
If the price oracle is unreachable after 3 retries:
- OnlyFence uses a fail-closed approach
- Falls back to cached price for up to 5 minutes
- If cache is stale or absent, the trade is rejected
- Token allowlist checks always apply regardless of oracle status