Umbrella for declarative Raxol.Agent.PolicyApplier policies.
Each policy is a struct that wraps an operation with one side-condition: retry on failure, abort on timeout, short-circuit on cache hit. Policies are composable; the applier walks a list and wraps the operation outermost-first.
Built-in policies
Policy.Cache.ets(ttl_ms: 300_000, key_fn: &(&1.user_id))
Policy.Timeout.new(30_000)
Policy.Retry.exponential(max_attempts: 3, base_ms: 200)Composition order
When passed to Raxol.Agent.PolicyApplier.apply/3:
apply([Cache, RateLimit, Timeout, Retry, ...], fun, params)the runtime evaluates from outermost (head) to innermost (just
before fun):
- Cache -- check; on hit, return the cached value and stop.
- RateLimit (deferred) -- check; on reject, return
{:error, :rate_limited}. - Timeout -- wrap; spawn
funin aTaskand abort onwall_mselapsed. - Retry -- wrap; loop until success or attempts exhausted.
- fun -- the wrapped operation runs.
The reverse of declaration order is intentional: the author lists "what I want true at the top" (cache first, then rate limits, then bounded wall time, then retry on failure); the runtime peels them off in order.
Telemetry
Every policy decision emits an event under
[:raxol, :agent, :policy, :*]:
:cache_hit,:cache_miss:retry_attempt,:retry_exhausted:timeout:applied(final outcome of the composed pipeline)
Metadata: policy_kind, params, attempt (where applicable),
plus any trace context attached upstream.
Summary
Types
@type t() :: Raxol.Agent.Policy.Retry.t() | Raxol.Agent.Policy.Timeout.t() | Raxol.Agent.Policy.Cache.t()