airflow.providers.common.ai.mixins.approval¶
Attributes¶
Classes¶
Protocol for defer for approval mixin. |
|
Mixin that pauses an operator for human review before returning output. |
Functions¶
|
Return value as a list of |
Module Contents¶
- airflow.providers.common.ai.mixins.approval.normalize_assigned_users(value, *, param)[source]¶
Return value as a list of
{'id': str, 'name': str}users.Accepts
None, a single user dict, or an iterable of them, and raisesTypeErrornaming param for anything else, so a malformed list fails when the Dag is parsed rather than when the task first asks for a review.
- class airflow.providers.common.ai.mixins.approval.DeferForApprovalProtocol[source]¶
Bases:
ProtocolProtocol for defer for approval mixin.
- approval_timeout: datetime.timedelta | None[source]¶
- approval_notifiers: collections.abc.Sequence[airflow.providers.common.compat.notifier.BaseNotifier][source]¶
- class airflow.providers.common.ai.mixins.approval.LLMApprovalMixin[source]¶
Mixin that pauses an operator for human review before returning output.
When
require_approval=Trueon the operator, the generated output is presented to a human reviewer via the Airflow Human-in-the-Loop (HITL) interface. The task waits (awaiting_inputon Airflow 3.3+, deferred on older versions) until the reviewer approves or rejects.If
allow_modifications=True, the reviewer can also edit the output before approving. The (possibly modified) output is then returned as the task result.on_approval_timeoutdecides what happens whenapproval_timeoutexpires without a response:"fail"raisesHITLTimeoutError, while"approve"and"reject"answer the review with that option so the task resumes as if a reviewer had chosen it. The chosen option is also pre-highlighted for the reviewer in the HITL form.approval_notifiersare called once the review is open, so a reviewer learns about it without watching the Required Actions page, the wayHITLOperatordoes withnotifiers. The reviewsubjectandbodyare exposed as{{ task.subject }}and{{ task.body }}in notifier templates. A notifier whose delivery raises is logged without failing the task, while a template error fails the task. A retry re-runs the LLM and re-notifies with the regenerated output. On Airflow 3.4+ the reopened review shows the regenerated output too; on Airflow 3.1 to 3.3 it keeps the original subject, body and editable output, so approving it unedited returns the first attempt’s output.approval_assigned_usersrestricts the review to the named users, the wayHITLOperatordoes withassigned_users. Leaving it empty lets any user with the permission respond. On Airflow 3.1 to 3.3 the list is stored when the review is first created, so clearing the task after changing it does not take effect; on 3.4+ a cleared or retried task replaces it.Operators that use this mixin must set the following attributes:
require_approval(bool)allow_modifications(bool)approval_timeout(timedelta | None)on_approval_timeout(Literal["fail", "approve", "reject"])approval_notifiers(Sequence[BaseNotifier])approval_assigned_users(list[HITLUser])prompt(str)
- validate_approval_prompt()[source]¶
Fail fast when the prompt cannot be rendered as text in the approval review body.
- defer_for_approval(context, output, *, subject=None, body=None, modification_schema=None, decision=None)[source]¶
Write HITL detail, then pause the task for human review.
On Airflow 3.3+ the task parks in the
awaiting_inputstate (no trigger or triggerer involved); on older versions it defers toHITLTrigger. Either way it resumes inexecute_completeonce a response (or timeout default) arrives.on_approval_timeoutsupplies that timeout default;"fail"supplies none, so the review times out as an error.- Parameters:
context (airflow.sdk.Context) – Airflow task context.
output (Any) – The generated output to present for review.
subject (str | None) – Headline shown on the Required Actions page. Defaults to
"Review output for task `<task_id>`".body (str | None) – Markdown body shown below the headline. Defaults to the prompt and output wrapped in a code block.
modification_schema (dict[str, Any] | None) – JSON schema for the editable
outputparam whenallow_modifications=True. Defaults to{"type": "string"}. Pass e.g.{"type": "string", "enum": [...]}to render a dropdown of valid values in the review form, or{"type": "array", "items": {"type": "string", "enum": [...]}, "examples": [...]}to render a multi-select (JSON Schema forbidsenumat the array level, so the options come fromexamples); a list submitted by the reviewer is returned fromexecute_completere-serialized as a compact JSON string.decision (dict[str, Any] | None) – The pending decision record, when the operator wrote one. It is carried in the continuation the task resumes from, next to
generated_output, soexecute_completefinalizes the record from what was checkpointed with the pause and not from a copy a reader could have edited or deleted in the meantime.
- execute_complete(context, generated_output, event, decision=None)[source]¶
Resume after human review.
Called automatically by Airflow when the HITL trigger fires. Returns the original or reviewer-modified output on approval.
- Parameters:
context (airflow.sdk.Context) – Airflow task context.
generated_output (str) – The output that was deferred for review.
event (dict[str, Any]) – Trigger event payload containing
chosen_options,params_input,responded_by_user, andtimedout.decision (dict[str, Any] | None) – The pending decision record passed to
defer_for_approval, if any. The mixin does not read it; an operator that writes a record finalizes it.
- Raises:
HITLRejectException – If the reviewer, or the
on_approval_timeout="reject"default, rejected the output.HITLTriggerEventError – If the trigger reported an error.
HITLTimeoutError – If the approval timed out.