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 a1c3755a23d Graduate ClassifierRetryPolicy to stable in Common AI 
(#74707)
a1c3755a23d is described below

commit a1c3755a23d6f30f98795486929543b1d0a347be
Author: Kaxil Naik <[email protected]>
AuthorDate: Wed Oct 14 10:17:07 2026 +0100

    Graduate ClassifierRetryPolicy to stable in Common AI (#74707)
    
    Its fallback order (fallback_policy, then fallback_rules, then the task's
    own retry settings) shipped and has not changed since, so the stated reason
    for keeping it experimental no longer holds. Only the typesafe extra stays
    experimental, because typesafe-sdk is pre-1.0. Also drop the stale
    experimental labels the Why Common AI page still carried for features that
    are already stable.
---
 providers/common/ai/docs/decision_models.rst       |  5 +++--
 providers/common/ai/docs/retry_policies.rst        |  5 -----
 providers/common/ai/docs/stability.rst             | 16 +++++++++++---
 providers/common/ai/docs/why_common_ai.rst         | 25 ++++++++++------------
 .../airflow/providers/common/ai/policies/retry.py  | 10 ---------
 5 files changed, 27 insertions(+), 34 deletions(-)

diff --git a/providers/common/ai/docs/decision_models.rst 
b/providers/common/ai/docs/decision_models.rst
index 337b306d1a6..8320806ffb5 100644
--- a/providers/common/ai/docs/decision_models.rst
+++ b/providers/common/ai/docs/decision_models.rst
@@ -20,8 +20,9 @@ Decision models
 
 .. note::
 
-    Experimental: this can change or be removed in a minor release of this 
provider.
-    See :ref:`howto/stability`.
+    Experimental: the ``typesafe`` extra can change or be removed in a minor 
release of this
+    provider, because the ``typesafe-sdk`` it installs is before its 1.0 
release. See
+    :ref:`howto/stability`.
 
 Every other model in this provider writes text. A decision model does not: you 
give it
 some text and a typed question, and it answers with a value from a set you 
named in
diff --git a/providers/common/ai/docs/retry_policies.rst 
b/providers/common/ai/docs/retry_policies.rst
index 686eb5c7e0f..5b19a1f2966 100644
--- a/providers/common/ai/docs/retry_policies.rst
+++ b/providers/common/ai/docs/retry_policies.rst
@@ -162,11 +162,6 @@ an attempt is a separate mechanism on the connection; see
 ClassifierRetryPolicy
 ---------------------
 
-.. note::
-
-    Experimental: this can change or be removed in a minor release of this 
provider.
-    See :ref:`howto/stability`.
-
 ``ClassifierRetryPolicy`` takes the retry decision away from the model. Its
 ``categories`` maps a category name to an
 :class:`~airflow.providers.common.ai.policies.retry.ErrorCategory`: what
diff --git a/providers/common/ai/docs/stability.rst 
b/providers/common/ai/docs/stability.rst
index abf65413ff2..70ce591b8cb 100644
--- a/providers/common/ai/docs/stability.rst
+++ b/providers/common/ai/docs/stability.rst
@@ -173,6 +173,17 @@ Pydantic AI toolsets, but the Pydantic AI class they 
inherit from can change.
        ``redact_exception=False`` or a custom ``redactor`` replaces the 
masking. If the
        model call fails, it falls back to ``fallback_rules`` and then to the 
task's own
        retry settings; it never fails the task itself.
+   * - 
:class:`~airflow.providers.common.ai.policies.retry.ClassifierRetryPolicy` and
+       :class:`~airflow.providers.common.ai.policies.retry.ErrorCategory`
+     - The model can only answer with one of the names in ``categories``, and 
that name's
+       ``ErrorCategory`` decides whether the task retries and after what 
``delay``.
+       Without ``categories`` the policy uses
+       :data:`~airflow.providers.common.ai.policies.retry.DEFAULT_CATEGORIES`, 
whose seven
+       names and their retry or fail split stay the same. When the model call 
fails, or
+       ``min_confidence`` is set and the answer is under it or carries no 
confidence, the
+       policy uses the RETRY or FAIL of ``fallback_policy``, then 
``fallback_rules``, then
+       the task's own retry settings. Secrets are masked in the exception text 
as for
+       ``LLMRetryPolicy``.
    * - Output review: ``require_approval``, ``enable_hitl_review`` and the 
review plugin
      - With ``require_approval=True``, the task defers after generating output 
and returns
        it only once a person approves it on the Required Actions page. A 
rejection, or a
@@ -191,9 +202,8 @@ Everything this provider ships that is not in the table 
above is experimental.
 
    * - Feature
      - Why it is experimental
-   * - 
:class:`~airflow.providers.common.ai.policies.retry.ClassifierRetryPolicy`
-       (:doc:`decision_models`)
-     - What it does when the classifier is unsure or unavailable is changing.
+   * - The ``typesafe`` extra (:doc:`decision_models`)
+     - It installs ``typesafe-sdk``, which is before its 1.0 release.
    * - :class:`~airflow.providers.common.ai.policies.decision.DecisionPolicy`, 
and
        ``min_confidence`` on
        :class:`~airflow.providers.common.ai.policies.decision.BranchOption`
diff --git a/providers/common/ai/docs/why_common_ai.rst 
b/providers/common/ai/docs/why_common_ai.rst
index 992b54945fd..cfd3e7fa9f8 100644
--- a/providers/common/ai/docs/why_common_ai.rst
+++ b/providers/common/ai/docs/why_common_ai.rst
@@ -85,10 +85,9 @@ and a bucket of report files. What differs:
 - **The tools.** The hand-written ``query`` runs any SQL the model writes, 
including
   ``DELETE``, on any table the connection can reach, and returns every row it 
gets.
   ``SQLToolset`` allows only the ``orders`` table, rejects statements that 
write, and caps
-  the rows and bytes it returns. ``ObjectStorageToolset`` (experimental) keeps 
reads under
-  the prefix you gave it. Both run Airflow's secrets masker over results, 
which hides
-  values Airflow knows are secret, such as connection passwords, not personal 
data in your
-  tables.
+  the rows and bytes it returns. ``ObjectStorageToolset`` keeps reads under 
the prefix you
+  gave it. Both run Airflow's secrets masker over results, which hides values 
Airflow knows
+  are secret, such as connection passwords, not personal data in your tables.
 - **The model.** The plain task names a vendor in code and reads its key from 
the
   environment. ``AgentOperator`` takes both from a connection, so moving to 
another vendor
   or adding a fallback is a connection change. See :doc:`model_providers`.
@@ -137,7 +136,7 @@ What a plain task leaves to you
     * - A person has to approve a tool call before it runs, such as a refund 
or a write
         to a production table.
       - A tool marked with Pydantic AI's approval API pauses ``AgentOperator`` 
before the
-        call, without holding a worker slot. Airflow 3.3 and later. 
Experimental. Not with
+        call, without holding a worker slot. Airflow 3.3 and later. Not with
         ``durable=True`` or ``enable_hitl_review=True``; with either, a tool 
marked for
         approval fails the task.
       - :doc:`tool_approval`
@@ -150,10 +149,10 @@ What a plain task leaves to you
       - :doc:`hitl_review`
     * - The agent needs your databases, object storage or an API you already 
have a
         hook for.
-      - ``SQLToolset``, ``HookToolset`` and ``ObjectStorageToolset`` 
(experimental) build
-        tools from an Airflow connection, with table allow-lists, read-only 
SQL and size
-        limits. Results pass through Airflow's secrets masker before the model 
sees
-        them. They work in an agent you run yourself too.
+      - ``SQLToolset``, ``HookToolset`` and ``ObjectStorageToolset`` build 
tools from an
+        Airflow connection, with table allow-lists, read-only SQL and size 
limits. Results
+        pass through Airflow's secrets masker before the model sees them. They 
work in an
+        agent you run yourself too.
       - :doc:`toolsets/index`
     * - A model vendor is down.
       - ``fallback_conn_ids`` fails over to other connections in order.
@@ -162,11 +161,10 @@ What a plain task leaves to you
       - The batch operator sends them through the OpenAI or Anthropic batch 
API at
         roughly half the per-token cost. A retry re-attaches to the batch 
already
         submitted if the prompts, model, output schema and connection are 
unchanged.
-        With ``deferrable=True`` the wait does not hold a worker slot. 
Experimental.
+        With ``deferrable=True`` the wait does not hold a worker slot.
       - :doc:`operators/llm_batch`
 
 The provider runs on Airflow 2.11 and later; a row that needs a newer Airflow 
says so.
-Experimental features can change in a minor release; see :doc:`stability`.
 
 Decide whether a failed task retries
 ------------------------------------
@@ -187,9 +185,8 @@ When the task fails, the model reads the exception and 
decides whether to retry
 long to wait, so it can decide to wait out a rate limit and to fail a revoked 
credential
 at once. The exception text goes through the secrets masker before the model 
sees it,
 and ``fallback_rules`` decide when the model cannot be reached. 
``ClassifierRetryPolicy``
-(experimental) has a cheaper model pick from categories you define, and can 
hand the
-cases it is unsure of to an ``LLMRetryPolicy``. Both need Airflow 3.3 or 
later. See
-:doc:`retry_policies`.
+has a cheaper model pick from categories you define, and can hand the cases it 
is unsure
+of to an ``LLMRetryPolicy``. Both need Airflow 3.3 or later. See 
:doc:`retry_policies`.
 
 When a plain task is enough
 ---------------------------
diff --git 
a/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py 
b/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py
index cccdfbe4593..bb72791d0e6 100644
--- a/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py
+++ b/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py
@@ -129,11 +129,6 @@ class ErrorCategory:
     """
     One kind of failure a :class:`ClassifierRetryPolicy` may name, and what it 
does when it does.
 
-    .. note::
-
-        Experimental: this can change or be removed in a minor release of this 
provider.
-        See :ref:`howto/stability`.
-
     The value of the policy's ``categories`` mapping, keyed by the category 
name the model
     answers with.
 
@@ -459,11 +454,6 @@ class ClassifierRetryPolicy(_ModelRetryPolicy):
     """
     Retry policy where the model names the kind of failure and the author's 
table decides.
 
-    .. note::
-
-        Experimental: this can change or be removed in a minor release of this 
provider.
-        See :ref:`howto/stability`.
-
     The model's only job is to pick one of ``categories``; it reads each one's 
description
     from the output schema. Whether that category is retried, after how long, 
and how sure
     the model has to be all come from the :class:`ErrorCategory` in the worker 
process.

Reply via email to