withEffectiveQos

Returns this Action with its QoS resolved against the platform-level AgentPlatformProperties.ActionQosProperties.

Resolution rule

ConditionResult
action.qos == ActionQos()Platform defaults are applied — action was never explicitly configured
action.qos != ActionQos()Original QoS is kept — action has an explicit configuration

This correctly handles all construction paths:

  • Annotation-based (@Agent / @Action): already wired via com.embabel.agent.api.annotation.support.DefaultActionQosProvider; their qos will differ from ActionQos() when properties are set, so this function leaves them unchanged.

  • DSL actions (AgentBuilder.transformation, AgentBuilder.promptedTransformer): default to ActionQos() unless the caller passes an explicit qos argument; platform defaults are applied here.

  • Workflow builder actions (RepeatUntil, ScatterGather, etc.): never pass a qos argument, so always receive ActionQos(); platform defaults are applied.

  • Child processes: go through the same AbstractAgentProcess.executeAction() choke point, so coverage is automatic.

Why structural equality works

ActionQos is a Kotlin data class, so ActionQos() == ActionQos() is always true. Any action that received a default-constructed QoS is therefore correctly identified as "not explicitly configured." A developer who intentionally writes ActionQos(maxAttempts = 5) — which happens to equal ActionQos() — would also have platform defaults applied, but since the values are identical the runtime behaviour is unchanged.

No-op guarantee

If the platform properties resolve back to ActionQos() (all fields null, no override configured), the original action is returned as-is — no allocation, no wrapping.