airflow.providers.common.ai.mixins.approval

Attributes

log

Classes

DeferForApprovalProtocol

Protocol for defer for approval mixin.

LLMApprovalMixin

Mixin that pauses an operator for human review before returning output.

Module Contents

airflow.providers.common.ai.mixins.approval.log[source]
class airflow.providers.common.ai.mixins.approval.DeferForApprovalProtocol[source]

Bases: Protocol

Protocol for defer for approval mixin.

approval_timeout: datetime.timedelta | None[source]
allow_modifications: bool[source]
on_approval_timeout: Literal['fail', 'approve', 'reject'][source]
approval_notifiers: collections.abc.Sequence[airflow.providers.common.compat.notifier.BaseNotifier][source]
approval_assigned_users: list[airflow.sdk.execution_time.hitl.HITLUser][source]
prompt: str[source]
task_id: str[source]
defer: Any[source]
validate_approval_prompt()[source]
class airflow.providers.common.ai.mixins.approval.LLMApprovalMixin[source]

Mixin that pauses an operator for human review before returning output.

When require_approval=True on the operator, the generated output is presented to a human reviewer via the Airflow Human-in-the-Loop (HITL) interface. The task waits (awaiting_input on 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_timeout decides what happens when approval_timeout expires without a response: "fail" raises HITLTimeoutError, 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_notifiers are called once the review is open, so a reviewer learns about it without watching the Required Actions page, the way HITLOperator does with notifiers. The review subject and body are 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, while the open review keeps the original subject and body.

approval_assigned_users restricts the review to the named users, the way HITLOperator does with assigned_users. Leaving it empty lets any user with the permission respond. The list is stored when the review is first created; clearing the task re-runs it against the existing review row, so a changed list does not take effect.

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)

APPROVE = 'Approve'[source]
REJECT = 'Reject'[source]
TIMEOUT_DEFAULTS: ClassVar[dict[str, list[str]]][source]
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_input state (no trigger or triggerer involved); on older versions it defers to HITLTrigger. Either way it resumes in execute_complete once a response (or timeout default) arrives. on_approval_timeout supplies 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 output param when allow_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 forbids enum at the array level, so the options come from examples); a list submitted by the reviewer is returned from execute_complete re-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, so execute_complete finalizes 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, and timedout.

  • 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.

Was this entry helpful?