Repository navigation
Support Airflow 2.11 in the Common AI provider - #73991
Conversation
|
would be nice if we could drop the co-author in the latest commit. thanks! |
|
Quickest fix: git fetch upstream main && git rebase upstream/main
rm uv.lock && uv lock
git add uv.lock && git rebase --continue
git push --force-with-leaseAutomated nudge — ignore if you're not ready to rebase. This comment is updated in place on future |
vatsrahul1001
left a comment
There was a problem hiding this comment.
Need to fix conflicts.
b55be6a to
954c24f
Compare
Lower the provider's floor from Airflow 3.0 to 2.11, the floor the compat, standard and common-sql providers carry. The operators, decorators, hooks and toolsets run on 2.11 as they do on 3.0; features that need Airflow 3.1 or 3.3 (approval gates, HITL review, retry policies, tool approval, the task state store) keep their existing gates. - common.compat: export SET_DURING_EXECUTION, backed on Airflow 2 by an ArgNotSet that renders as Airflow 3's sentinel does, and resolve get_current_context through the standard provider first on Airflow 2, so it raises RuntimeError outside a task as Airflow 3 does. - PydanticAIHook.get_hook accepts hook_params on Airflow 2, mirroring Airflow 3. - The agent's per-attempt run key falls back to dag/run/task/map/try where the task instance has no id; spans then omit airflow.task_instance.id. - Declare structlog, which the provider imports but Airflow 2 does not ship, and route its output through the airflow.task logger on Airflow 2. - Declare the HITL review extra link only on Airflow 3.1+. - Run the provider's tests in the Airflow 2.11 compatibility job.
- Rename task_instance_run_key to make_task_instance_run_key. - Title the installation section "Airflow 2.11", so it does not read as covering every Airflow 2 release. - Silence the Airflow 2-only ArgNotSet import for mypy on Airflow 3.
954c24f to
de79909
Compare
|
Static check failure is unrelated |
Backport failed to create: v3-3-test. View the failure log Run detailsNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
You can attempt to backport this manually by running: cherry_picker 8f3e846 v3-3-testThis should apply the commit to the v3-3-test branch and leave the commit in conflict state marking After you have resolved the conflicts, you can continue the backport process by running: cherry_picker --continueIf you don't have cherry-picker installed, see the installation guide. |
Summary
The Common AI provider required Airflow 3.0, so an Airflow 2.11 deployment could not install it at all. This lowers the floor to
apache-airflow>=2.11.0, the floorcommon.compat,standardandcommon.sqlalready carry. When the community provider floor moves to 3.1, this provider moves with it.On 2.11 the operators, decorators, hooks and toolsets run as they do on Airflow 3.0. Features that need a newer core already have version gates, which this PR leaves in place: approval gates and HITL review (3.1), and retry policies, tool-approval pause and resume, and the task state store (3.3). Approval gates and HITL review fail at Dag parse time with a message naming the version.
LLMRetryPolicyfails at import. An approval-required tool fails the task, as it already does on 3.0 to 3.2. Durable execution falls back todurable_cache_pathas on 3.0 to 3.2.How this was checked
The branch ran on a real Airflow 2.11.2 in breeze, with the provider wheels built from this branch and a real model (Anthropic
claude-sonnet-5). One Dag was triggered through the REST API and run by the scheduler with the LocalExecutor:breeze release-management prepare-provider-distributions common.ai common.compat standard common.sql \ --distribution-format wheel --skip-tag-check breeze shell --python 3.12 --backend postgres --use-airflow-version 2.11.2 \ --airflow-constraints-reference constraints-2.11.2 --install-airflow-with-constraints \ --providers-skip-constraints --use-distributions-from-dist --distribution-format wheel # inside the container, with the Dag in /files/dags: AIRFLOW__SCHEDULER__STANDALONE_DAG_PROCESSOR=False airflow standaloneBreeze turns
STANDALONE_DAG_PROCESSORon for Airflow 3. Airflow 2'sairflow standalonedoes not start a separate Dag processor, so without that override it never parses a Dag.The LLM endpoint host is redacted in the HTTP request lines of the log screenshots.
Core 2.11.2 with this branch's providers (the list filtered to those four):
The run: every task succeeded;
path_awas skipped because the model pickedpath_b.AgentOperatorwithSQLToolset: the model lists the tables, writes a query, and the toolset runs it against SQLite.AgentOperator(durable=True)with a function toolset: the tool call and the durable cache on thedurable_cache_pathbackend.LLMBranchOperator:@task.agent(output_type=...)consumed downstream, which arrives as adictbefore Airflow 3.3:The Dag
The provider's unit tests now run in the existing
Compat 2.11.1job. Locally they pass on 2.11.1 (2313 passed) and on Airflow 3 (2890 passed);common.compatpasses on both.Design rationale
common.compat.sdk. The gaps were a few direct Airflow 3 imports and APIs:SET_DURING_EXECUTIONin the decoratorsBaseHook.get_hook(hook_params=...)TaskInstance.idObjectStoragePathfromairflow.sdkstructlog, which the provider imported but never declared; Airflow 3 brings it in through the Task SDK and Airflow 2 does not.common.compatchanges behaviour on Airflow 2, deliberately.get_current_contextnow resolves to the standard provider's Airflow 2 fallback before core's. Outside a task it raisesRuntimeError, as Airflow 3 does, instead of core'sAirflowException. Without the standard provider it still falls back to core. No caller in this repository catchesAirflowExceptionfrom the compat name;SandboxToolsetcatchesRuntimeError, so on Airflow 2 itsattach_tooutside a task failed instead of falling back toowner=.SET_DURING_EXECUTIONis new in compat. On Airflow 2 it is anArgNotSetwhosereprmatches Airflow 3's sentinel. With a bareNOTSET, Airflow 2 stores the decorator'sprompttemplate field as an object address, which differs per process and changes the serialized Dag's hash.common-compatline in the Common AIpyproject.tomlis marked# use next version, since the decorators need the new export.PydanticAIHook.get_hookmirrors Airflow 3'sBaseHook.get_hookbody (get_connection(conn_id).get_hook(hook_params=...)). Overriding the classmethod keeps the operators, and the tests that patchget_hook, unchanged. Callingget_connection().get_hook()from the operators instead would have bypassed those patches.run_id, therun_idXCom,gen_ai.agent.call.id) falls back todag_id/run_id/task_id/map_index/try_numberwhere the task instance has noid. Spans leave outairflow.task_instance.idthere, because a composite is not a task-instance id.debugincluded, into task logs.get_task_logger()wraps theairflow.taskstdlib logger on Airflow 2, so the task log's level and handlers apply and the record names the caller's line. It does not change the process-wide structlog configuration. On Airflow 3 it returns the same logger as before.AgentOperatordeclares the HITL review extra link only on 3.1+. On Airflow 2 the webserver logs an error for the unregistered link class on every Dag load, and the link can never render there.common.aiis removed fromremove-providersin theCompat 2.11.1row, so its tests run in the existing job. Test files that importedairflow.sdkdirectly now import throughcommon.compat.sdk. Two tests are gated to Airflow 3:AirflowException.MappedOperatorresolves an expansion through the metadata database and a task session, which a unit test with a dict context cannot drive.Gotchas
common-compatandcommon-sqlbelow this provider's floors. Airflow 2.11.0 installed without constraints can pick upuniversal-pathlib0.3, which itsObjectStoragePathrejects; 2.11.1 and later cap it. The installation page now says this.skillsandgitextras needapache-airflow-providers-git, which requires Airflow 3.dict, the same as on 3.0 to 3.2. The connection form's Model field needs 3.2; on older cores the model goes in Extra.{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.