Summary
PolicyContext exposes params, and policies-config.json has a policyParams map, so a custom policy appears configurable from config. It is not — custom policies always receive params: {}, silently.
Cause
POLICY_PARAMS_MAP is built only from BUILTIN_POLICIES entries that declare a params schema:
https://github.com/FailproofAI/failproofai/blob/main/src/hooks/policy-evaluator.ts#L31-L35
A CustomHook has no params schema (CustomHook in policy-types.ts:68-75 declares only name/description/match/fn), so lookup misses and it falls to the else-branch:
// policy-evaluator.ts:104-105
// Custom hooks and policies without schema get empty params
ctx = { ...baseCtx, params: {} };
Impact
Adding this to policies-config.json does nothing, with no warning:
{ "policyParams": { "my-custom-policy": { "threshold": 10 } } }
The failure is silent in both directions — the config key is accepted, and ctx.params is a valid empty object rather than undefined, so a policy reading ctx.params.threshold gets undefined and typically falls through to its default. Users have no signal that the value never arrived.
The comment at :104 reads as deliberate, so this may be intended. If so the gap is documentation plus a warning; if not, custom policies need a params channel.
Workaround
Hardcode values as module constants in the policy file, or read config/env directly inside fn.
Possible fixes
- Let
CustomHook declare an optional params schema, and resolve it the same way builtins are.
- Pass
config.policyParams[<custom name>] through unresolved (no schema, no defaults) — smaller change, no type addition.
- Keep current behavior, but warn at load time when
policyParams names a policy that is not a builtin, and document the limitation.
Found while building a policy-authoring skill; it was a genuine surprise that survived reading the public types.
Summary
PolicyContextexposesparams, andpolicies-config.jsonhas apolicyParamsmap, so a custom policy appears configurable from config. It is not — custom policies always receiveparams: {}, silently.Cause
POLICY_PARAMS_MAPis built only fromBUILTIN_POLICIESentries that declare aparamsschema:https://github.com/FailproofAI/failproofai/blob/main/src/hooks/policy-evaluator.ts#L31-L35
A
CustomHookhas noparamsschema (CustomHookinpolicy-types.ts:68-75declares onlyname/description/match/fn), so lookup misses and it falls to the else-branch:Impact
Adding this to
policies-config.jsondoes nothing, with no warning:{ "policyParams": { "my-custom-policy": { "threshold": 10 } } }The failure is silent in both directions — the config key is accepted, and
ctx.paramsis a valid empty object rather thanundefined, so a policy readingctx.params.thresholdgetsundefinedand typically falls through to its default. Users have no signal that the value never arrived.The comment at :104 reads as deliberate, so this may be intended. If so the gap is documentation plus a warning; if not, custom policies need a params channel.
Workaround
Hardcode values as module constants in the policy file, or read config/env directly inside
fn.Possible fixes
CustomHookdeclare an optionalparamsschema, and resolve it the same way builtins are.config.policyParams[<custom name>]through unresolved (no schema, no defaults) — smaller change, no type addition.policyParamsnames a policy that is not a builtin, and document the limitation.Found while building a policy-authoring skill; it was a genuine surprise that survived reading the public types.