IActuationPolicy is the effect-boundary gate for command dispatch.
Before ActuatorHost invokes a command handler, it evaluates each registered policy in order. A deny result blocks dispatch immediately and returns a failed completion.
Actuation policy answers:
Is this command allowed to be dispatched right now, by this agent/context, before it reaches a handler?
The layer is intentionally:
- Core-owned
- synchronous
- deterministic
- small
- handler-independent
- LLM-agnostic
- provider-agnostic
ActuatorHost.Dispatch(...) flow:
- Create actuation id.
- Evaluate policies in registration order.
- First deny wins:
- command does not reach a handler
- immediate failed
ActuationCompletedis published
- If all allow:
- handler lookup and invocation proceed as normal
Dominatus.Core.Runtime.ActuationPolicies provides reusable policy constructors:
AllowAllDenyAll(reason)When(Consideration, threshold, reason)ForCommand<TCommand>(Consideration, threshold, reason)Score((ctx, command) => floatScore, threshold, reason)Predicate((ctx, command) => bool, reason)BlockCommandTypes(params Type[])AllOf(params IActuationPolicy[])
When evaluates:
score = consideration.Eval(ctx.World, ctx.Agent)
allow when score >= threshold
deny when score < threshold
Denial diagnostics include command type, score, and threshold when no custom reason is supplied.
Score accepts a command-aware scorer:
ActuationPolicies.Score((ctx, command) => command is SomeCommand ? 0.25f : 1f);Score values are clamped to 0..1 before threshold comparison.
ForCommand<TCommand> only evaluates score for matching command types; non-matching commands are allowed through unchanged.
AllOf composes gates with deterministic short-circuit behavior:
- evaluate in order
- first deny wins
- stop evaluating subsequent policies after first deny
host.AddPolicy(
ActuationPolicies.When(
Consideration.FromBool((world, agent) => agent.Bb.GetOrDefault(CanActKey, false)),
threshold: 1f,
reason: "Agent cannot act."));host.AddPolicy(
ActuationPolicies.ForCommand<SomeCommand>(
Consideration.Constant(0f),
threshold: 0.5f,
reason: "SomeCommand is blocked."));Dominatus.OptFlow.ActuationPolicies remains available for existing call sites. Its reusable helpers forward to Core implementations where compatible.
When importing both Core and OptFlow helper namespaces, prefer fully-qualified names or alias directives to avoid type name ambiguity.
This layer is not:
- a scheduler
- retry/backoff orchestration
- a security framework
- a provider router
- a tool registry
- an async policy subsystem
Use existing Core policy primitives; do not create a SemanticKernel-specific policy engine.
- Build a capability profile and classify risk.
- Convert the reviewed subset into
SemanticKernelActuatorOptions.AllowedFunctions. - Register
SemanticKernelFunctionCommandhandler. - Add runtime policy gates with
ForCommand<SemanticKernelFunctionCommand>,When,Score, andAllOf.
This keeps concerns separate:
-
profile = classification
-
allowlist = hard permission surface
-
actuation policy = runtime allow/deny gate
-
workflow = approval/accountability boundary
-
Standard HTTP safety policy (
HttpWebSafetyActuationPolicy) is an example concreteIActuationPolicyover HTTP commands; seeACTUATORS_STANDARD_M5_HTTP_WEB_SAFETY.md.
For approval-gating examples on Graph send/update/cancel operations, see ACTUATORS_SEMANTICKERNEL_M4_GRAPH_PROFILE.md.