This is an automated email from the ASF dual-hosted git repository.
kaxil pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 2002ba522e6 Graduate durable agent execution to stable in Common AI
(#74704)
2002ba522e6 is described below
commit 2002ba522e69c122ccd06d145e38cc3559cdaae2
Author: Kaxil Naik <[email protected]>
AuthorDate: Wed Oct 14 09:50:09 2026 +0100
Graduate durable agent execution to stable in Common AI (#74704)
AirflowDurability (#74385) let a toolset declare whether its calls may be
replayed, which was the reason durable=True stayed experimental in #74679.
---
providers/common/ai/docs/durable_execution.rst | 5 -----
providers/common/ai/docs/stability.rst | 20 +++++++++++++++-----
providers/common/ai/docs/why_common_ai.rst | 7 +++----
.../airflow/providers/common/ai/operators/agent.py | 2 +-
4 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/providers/common/ai/docs/durable_execution.rst
b/providers/common/ai/docs/durable_execution.rst
index 10555ab20e1..59d4aaa7408 100644
--- a/providers/common/ai/docs/durable_execution.rst
+++ b/providers/common/ai/docs/durable_execution.rst
@@ -20,11 +20,6 @@
Durable execution
=================
-.. note::
-
- Experimental: this can change or be removed in a minor release of this
provider.
- See :ref:`howto/stability`.
-
An agent task makes several model calls and tool calls. When it fails partway
(a
network error, a timeout, a provider outage), a plain Airflow retry runs every
one of
them again: the model calls are paid for twice and the tools' side effects
happen
diff --git a/providers/common/ai/docs/stability.rst
b/providers/common/ai/docs/stability.rst
index 278377648fa..abf65413ff2 100644
--- a/providers/common/ai/docs/stability.rst
+++ b/providers/common/ai/docs/stability.rst
@@ -50,8 +50,8 @@ Pydantic AI toolsets, but the Pydantic AI class they inherit
from can change.
always dumped to a dict. ``decision_policy`` is experimental; see below.
* - ``@task.agent`` and
:class:`~airflow.providers.common.ai.operators.agent.AgentOperator`
- Runs an agent with the model from ``llm_conn_id`` and the given
toolsets, and
- returns its output under the same rules as ``@task.llm``. ``durable``
and
- code mode are experimental; see below.
+ returns its output under the same rules as ``@task.llm``. Code mode is
+ experimental; see below.
* - Per-tool approval on ``AgentOperator`` (:doc:`tool_approval`)
- On Airflow 3.3 and later, a call to a tool marked with Pydantic AI's
approval API
(``approval_required(...)`` on a toolset, or ``requires_approval=True``
on a
@@ -69,6 +69,19 @@ Pydantic AI toolsets, but the Pydantic AI class they inherit
from can change.
- Seeds the run with the given conversation, as a list of messages or its
JSON form,
and publishes the finished conversation under the ``message_history``
XCom key so a
later run can continue it. Cannot be combined with
``enable_hitl_review``.
+ * - ``durable=True`` on ``AgentOperator`` and ``@task.agent``, and
+ :class:`~airflow.providers.common.ai.durable.AirflowDurability`
+ (:doc:`durable_execution`)
+ - On a retry the agent runs from the start, and each model request and
tool call an
+ earlier attempt recorded is replayed from the journal kept for the task
instance,
+ without calling the model or running the tool again, as long as it
matches the step
+ recorded at the same point; from the first step that differs, every
step runs live.
+ The journal is kept in the task state store on Airflow 3.3 and later,
and under
+ ``[common.ai] durable_cache_path`` before. With ``durable=True``,
replayed steps
+ count nothing against ``usage_limits`` or in the ``usage`` XCom, the
agent's
+ ``run_id`` stays the first attempt's, and the journal is deleted when
the task
+ succeeds. In a plain ``@task``, ``AirflowDurability`` deletes a run's
steps when
+ that run succeeds.
* - ``@task.llm_branch`` and
:class:`~airflow.providers.common.ai.operators.llm_branch.LLMBranchOperator`
- The model picks among the task's direct downstream tasks, one by
default or several
@@ -192,9 +205,6 @@ Everything this provider ships that is not in the table
above is experimental.
(:doc:`operators/llm_batch`)
- No package outside this provider implements the contract yet, so it has
not been
tested by a second implementation.
- * - ``durable=True`` on ``AgentOperator`` (:doc:`durable_execution`)
- - Which tool results are replayed on retry will change, so that a tool
can declare
- whether its result may be reused.
* - Code mode (:doc:`code_mode`) and the ``shields`` extra (used in
:doc:`capabilities`)
- Thin integrations of ``pydantic-ai-harness`` and
``pydantic-ai-shields``, which are
diff --git a/providers/common/ai/docs/why_common_ai.rst
b/providers/common/ai/docs/why_common_ai.rst
index 447d3da00fe..992b54945fd 100644
--- a/providers/common/ai/docs/why_common_ai.rst
+++ b/providers/common/ai/docs/why_common_ai.rst
@@ -93,9 +93,8 @@ and a bucket of report files. What differs:
environment. ``AgentOperator`` takes both from a connection, so moving to
another vendor
or adding a fallback is a connection change. See :doc:`model_providers`.
- **A retry.** The plain task starts again from the beginning and pays for
every call
- again. ``durable=True`` replays the calls that finished and continues from
there. It is
- experimental, and before Airflow 3.3 it needs ``[common.ai]
durable_cache_path`` set; see
- :doc:`durable_execution`.
+ again. ``durable=True`` replays the calls that finished and continues from
there. Before
+ Airflow 3.3 it needs ``[common.ai] durable_cache_path`` set; see
:doc:`durable_execution`.
- **Spend.** In the plain task, Pydantic AI's default limit of 50 model
requests applies
to each attempt on its own, so three attempts can make up to 150. With
``usage_limits``
on Airflow 3.3 and later, one total covers all three attempts, and the task
fails once
@@ -120,7 +119,7 @@ What a plain task leaves to you
* - The task retries after the agent has already made model and tool calls.
- ``durable=True`` on ``AgentOperator`` replays the calls that finished
and runs
the rest live. If the prompt, model or tools changed since the failed
attempt,
- the affected calls run again. Experimental.
+ the affected calls run again.
- :doc:`durable_execution`
* - A run must not spend past a limit, retries included.
- ``usage_limits`` counts every attempt of the task instance together on
diff --git
a/providers/common/ai/src/airflow/providers/common/ai/operators/agent.py
b/providers/common/ai/src/airflow/providers/common/ai/operators/agent.py
index 6215733d224..9078c2e9f85 100644
--- a/providers/common/ai/src/airflow/providers/common/ai/operators/agent.py
+++ b/providers/common/ai/src/airflow/providers/common/ai/operators/agent.py
@@ -341,7 +341,7 @@ class AgentOperator(CancellableAgentRunMixin, BaseOperator,
HITLReviewMixin, Usa
:ref:`the cross-attempt usage budget <agent-usage-budget>` for how
it is persisted, reset, and how ``durable`` replay and HITL
regeneration interact with it.
- :param durable: Experimental. When ``True``, attaches
+ :param durable: When ``True``, attaches
:class:`~airflow.providers.common.ai.durable.AirflowDurability`, which
records each step the agent completes -- model responses, tool calls
from
any toolset or capability, tool discovery, and other capabilities'