Skip to content

Reject unsupported output_type and bound HITL XCom pull retries - #74450

Merged
Lee-W merged 4 commits into
apache:mainfrom
astronomer:common-ai-operators-fixes
Oct 9, 2026
Merged

Lee-W merged 4 commits into
apache:mainfrom
astronomer:common-ai-operators-fixes

Conversation

@Lee-W

@Lee-W Lee-W commented Oct 8, 2026

Copy link
Copy Markdown
Member

Why

  • LLMBranchOperator builds its output type from its downstream task IDs, but it silently dropped any output_type the caller passed (kwargs.pop("output_type", None)). A user who sets it gets no signal that it has no effect.
  • The HITL review loop in run_hitl_review swallowed xcom_pull errors with a warning and kept polling. Since hitl_timeout can be None, persistent failures (for example an unreachable API server) made the task spin forever.
  • LLMOperator.output_type was annotated as type, which is narrower than what pydantic-ai accepts.

What

  • LLMBranchOperator: passing output_type now raises TypeError instead of being silently dropped. This is a behaviour change: callers who passed it before (and had it rror.
  • HITL review (mixins/hitl_review.py): added _MAX_CONSECUTIVE_XCOM_PULL_FAILURES = 10 and a consecutive_pull_failures counter in the run_hitl_review loop. Each `xcom_pit. On the 10th consecutive failure the originalexception is re-raised unchanged. Otherwise it logs a warning and continues. A successful pull resets the counter to 0.
  • When hitl_timeout is set, persistent XCom faial error on the 10th failure instead of waiting forthe deadline and raising HITLTimeoutError. - LLMOperator: output_type: type = str becomes ny] = str, with OutputSpec imported frompydantic_ai.outputunderTYPE_CHECKING`. This accepts union and list forms, ma- Tests:
  • test_hitl_review.py: added test_xcom_pull_failures_raise_after_limit and test_xcom_pull_failure_counter_resets_on_success.
  • test_llm_branch.py: test_output_type_ignored becomes test_output_type_rejected.

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: [Claude] following the guidelines


  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

Comment thread providers/common/ai/src/airflow/providers/common/ai/operators/llm.py Outdated
Lee-W added 4 commits October 9, 2026 05:54
…forever on XCom errors

LLMBranchOperator now raises TypeError when output_type is passed instead of silently
dropping it, since the operator builds the output type from its downstream task IDs.

The HITL review loop re-raises the XCom pull error after 10 consecutive failures, so a task
with hitl_timeout=None no longer spins forever when the API server is unreachable.
When hitl_timeout is set, persistent XCom failures now raise the original error on the 10th failure
instead of waiting for the deadline to raise HITLTimeoutError.

LLMOperator's output_type annotation now matches pydantic-ai's OutputSpec, accepting union
and list forms as well as plain types.
- `output_type` is annotated as `type | UnionType` instead of `OutputSpec[Any]`, so list
  forms such as `[A, B]` and marker forms such as `ToolOutput(A)` are no longer advertised;
  they cannot be rehydrated when `require_approval=True` resumes the task
- the `output_type` parameter docs describe the accepted shapes
- the HITL review loop logs an error with the failure count before it re-raises the XCom
  pull error, so the task log shows the loop gave up rather than a one-off failure
- the `HITLReviewMixin` docstring, `run_hitl_review` `:raises:`, `hitl_review.rst` and the
  `AgentOperator` `hitl_timeout` docs no longer say `hitl_timeout=None` blocks until a
  terminal action
- passing `output_type` to `LLMSQLQueryOperator` or `LLMSchemaCompareOperator` (or their
  `@task.llm_sql` / `@task.llm_schema_compare` forms) raises `TypeError` instead of being
  silently dropped or overwritten, matching `LLMBranchOperator`
- mapped tasks (`.partial()` / `.expand()`) raise when the task is unmapped on the worker
@Lee-W
Lee-W force-pushed the common-ai-operators-fixes branch from 117eea3 to f663106 Compare October 9, 2026 04:54
@Lee-W Lee-W changed the title Reject output_type on LLMBranchOperator and bound HITL XCom retries Reject unsupported output_type and bound HITL XCom pull retries Oct 9, 2026
@Lee-W
Lee-W merged commit 7811cba into apache:main Oct 9, 2026
85 checks passed
@Lee-W
Lee-W deleted the common-ai-operators-fixes branch October 9, 2026 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants