This is an automated email from the ASF dual-hosted git repository.

Lee-W 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 10529542d48 Update retired model ids and fill doc gaps in common.ai 
provider docs (#69711)
10529542d48 is described below

commit 10529542d482c6293f454748fa87cd46d93c0aef
Author: Wei Lee <[email protected]>
AuthorDate: Tue Jul 14 23:08:02 2026 +0800

    Update retired model ids and fill doc gaps in common.ai provider docs 
(#69711)
---
 providers/common/ai/docs/connections/mcp.rst       |  8 ++---
 .../common/ai/docs/connections/pydantic_ai.rst     | 11 ++++--
 providers/common/ai/docs/hitl_review.rst           |  6 ++--
 providers/common/ai/docs/hooks/index.rst           |  4 +++
 providers/common/ai/docs/hooks/langchain.rst       |  2 +-
 providers/common/ai/docs/operators/agent.rst       | 39 +++++++++++++++++-----
 providers/common/ai/docs/operators/index.rst       |  2 +-
 .../ai/docs/operators/llamaindex_retrieval.rst     |  2 +-
 providers/common/ai/docs/operators/llm.rst         | 12 +++----
 providers/common/ai/docs/operators/llm_branch.rst  |  4 +--
 .../common/ai/docs/operators/llm_file_analysis.rst | 15 +++++++--
 providers/common/ai/docs/quickstart.rst            |  4 +--
 providers/common/ai/docs/retry_policies.rst        |  5 +--
 providers/common/ai/docs/toolsets.rst              | 18 +++++-----
 providers/common/ai/provider.yaml                  |  4 +--
 .../providers/common/ai/get_provider_info.py       |  4 +--
 .../providers/common/ai/hooks/pydantic_ai.py       |  6 ++--
 .../tests/unit/common/ai/hooks/test_pydantic_ai.py | 34 +++++++++----------
 18 files changed, 111 insertions(+), 69 deletions(-)

diff --git a/providers/common/ai/docs/connections/mcp.rst 
b/providers/common/ai/docs/connections/mcp.rst
index 07be621e9a1..a324bbdffe6 100644
--- a/providers/common/ai/docs/connections/mcp.rst
+++ b/providers/common/ai/docs/connections/mcp.rst
@@ -150,9 +150,9 @@ into task logs) without ever being written to the 
connection:
         token_provider=mint_snowflake_jwt,
     )
 
-``token_provider`` is resolved in DAG code (it is a Python callable, not a 
stored
+``token_provider`` is resolved in Dag code (it is a Python callable, not a 
stored
 connection field), so the signing key stays in your environment and is never 
baked
-into the serialized DAG.
+into the serialized Dag.
 
 Secrets in stdio subprocess environments
 -----------------------------------------
@@ -193,5 +193,5 @@ managed as its own Airflow connection:
     :start-after: [START howto_toolset_mcp_env_provider]
     :end-before: [END howto_toolset_mcp_env_provider]
 
-Like ``token_provider``, ``env_provider`` is resolved in DAG code, so the 
secret is
-fetched at task-execution time and never baked into the serialized DAG.
+Like ``token_provider``, ``env_provider`` is resolved in Dag code, so the 
secret is
+fetched at task-execution time and never baked into the serialized Dag.
diff --git a/providers/common/ai/docs/connections/pydantic_ai.rst 
b/providers/common/ai/docs/connections/pydantic_ai.rst
index a7aa0c85a50..a77fce140a6 100644
--- a/providers/common/ai/docs/connections/pydantic_ai.rst
+++ b/providers/common/ai/docs/connections/pydantic_ai.rst
@@ -38,9 +38,14 @@ Model
     dedicated input in the connection form (via ``conn-fields``) and stores its
     value in ``extra["model"]``.
 
-    Examples: ``openai:gpt-5.3``, ``anthropic:claude-sonnet-4-20250514``,
+    Examples: ``openai:gpt-5.6-sol``, ``anthropic:claude-sonnet-5``,
     ``bedrock:us.anthropic.claude-opus-4-6-v1:0``, ``google:gemini-2.0-flash``
 
+    See `Anthropic's models overview 
<https://platform.claude.com/docs/en/about-claude/models/overview#latest-models-comparison>`__
+    for the current list of Claude model IDs across the Claude API, Amazon 
Bedrock, and Google Cloud.
+    See `OpenAI's models reference 
<https://developers.openai.com/api/docs/models/all>`__
+    for the current list of OpenAI model IDs.
+
     The model can also be overridden at the hook/operator level via the
     ``model_id`` parameter.
 
@@ -64,7 +69,7 @@ Extra (JSON, optional)
 
     .. code-block:: json
 
-        {"model": "openai:gpt-5.3"}
+        {"model": "openai:gpt-5.6-sol"}
 
     When using the UI, the "Model" field above writes to this same location
     automatically.
@@ -79,7 +84,7 @@ Examples
     {
         "conn_type": "pydanticai",
         "password": "sk-...",
-        "extra": "{\"model\": \"openai:gpt-5.3\"}"
+        "extra": "{\"model\": \"openai:gpt-5.6-sol\"}"
     }
 
 **Anthropic**
diff --git a/providers/common/ai/docs/hitl_review.rst 
b/providers/common/ai/docs/hitl_review.rst
index 26735622e96..699d51c5e56 100644
--- a/providers/common/ai/docs/hitl_review.rst
+++ b/providers/common/ai/docs/hitl_review.rst
@@ -131,7 +131,7 @@ instance page. Use the **HITL Review** extra link on the 
task instance, or
 navigate to
 ``/dags/{dag_id}/runs/{run_id}/tasks/{task_id}/plugin/hitl-review``.
 
-**Example DAG**
+**Example Dag**
 
 .. exampleinclude:: 
/../../ai/src/airflow/providers/common/ai/example_dags/example_agent.py
     :language: python
@@ -150,8 +150,8 @@ The plugin exposes a FastAPI app at ``/hitl-review``. Base 
URL:
 
 **Common query parameters** (where applicable):
 
-- ``dag_id`` — DAG ID.
-- ``run_id`` — DAG run ID.
+- ``dag_id`` — Dag ID.
+- ``run_id`` — Dag run ID.
 - ``task_id`` — Task ID.
 - ``map_index`` — Map index for mapped tasks. Use ``-1`` for non-mapped tasks 
or index for dynamic mapping.
 
diff --git a/providers/common/ai/docs/hooks/index.rst 
b/providers/common/ai/docs/hooks/index.rst
index 2786cd1b0ce..13455cdf896 100644
--- a/providers/common/ai/docs/hooks/index.rst
+++ b/providers/common/ai/docs/hooks/index.rst
@@ -47,6 +47,10 @@ Choosing a hook
        by default). For non-OpenAI vendors, pass a pre-built
        ``BaseEmbedding`` / ``LLM`` instance straight to the operator and
        bypass the hook.
+   * - :class:`~airflow.providers.common.ai.hooks.mcp.MCPHook`
+     - Backs ``MCPToolset`` (see :doc:`../toolsets`) for agent tasks that call
+       tools on a remote MCP server. Configure the connection via
+       :doc:`../connections/mcp`.
 
 Hook guides
 -----------
diff --git a/providers/common/ai/docs/hooks/langchain.rst 
b/providers/common/ai/docs/hooks/langchain.rst
index e7ee2e95d7d..5485f39ab2a 100644
--- a/providers/common/ai/docs/hooks/langchain.rst
+++ b/providers/common/ai/docs/hooks/langchain.rst
@@ -57,7 +57,7 @@ Any model identifier accepted by
 works out of the box. Common identifiers:
 
 - ``openai:gpt-4o``, ``openai:gpt-4o-mini`` -- requires ``langchain-openai``
-- ``anthropic:claude-3-7-sonnet`` -- requires ``langchain-anthropic``
+- ``anthropic:claude-sonnet-5`` -- requires ``langchain-anthropic``
 - ``groq:llama-3.3-70b-versatile`` -- requires ``langchain-groq``
 - ``mistralai:mistral-large-latest`` -- requires ``langchain-mistralai``
 - ``ollama:llama3`` -- requires ``langchain-ollama`` (point ``host`` at the 
Ollama URL)
diff --git a/providers/common/ai/docs/operators/agent.rst 
b/providers/common/ai/docs/operators/agent.rst
index 63cf575c131..578513469e2 100644
--- a/providers/common/ai/docs/operators/agent.rst
+++ b/providers/common/ai/docs/operators/agent.rst
@@ -125,11 +125,11 @@ attribute access (``result.field``).
 
 The declared ``output_type`` (and any ``BaseModel`` reachable from
 ``Union``/``Optional``/``list`` shapes) is registered for XCom deserialization 
by
-the worker when it loads the DAG, before any task runs. The Pydantic class must
+the worker when it loads the Dag, before any task runs. The Pydantic class must
 be defined at **module scope** and bound to an attribute matching its
-``__name__``. Same-DAG downstream tasks need no configuration. The UI's XCom
+``__name__``. Same-Dag downstream tasks need no configuration. The UI's XCom
 viewer renders the value via the ``stringify`` path (no configuration needed;
-see the ``LLMOperator`` guide for the exact representation). Cross-DAG
+see the ``LLMOperator`` guide for the exact representation). Cross-Dag
 ``xcom_pull`` consumers still need the class ``qualname`` added to
 ``[core] allowed_deserialization_classes``.
 
@@ -309,9 +309,9 @@ invalidate cached responses -- clear the cache to force a 
fully fresh run.
 After the run, a single INFO summary line reports how many steps were
 replayed vs executed fresh. Per-step detail is available at DEBUG level.
 
-The cache is scoped to a single task instance (DAG id, run id, task id, and
+The cache is scoped to a single task instance (Dag id, run id, task id, and
 map index), so each run replays only its own steps. On Airflow >= 3.3 the cache
-lives in the task state store and is removed when the DAG run is cleaned up; on
+lives in the task state store and is removed when the Dag run is cleaned up; on
 Airflow < 3.3 it is a JSON file named ``{dag_id}_{task_id}_{run_id}.json`` 
(with
 ``_{map_index}`` appended for mapped tasks) under the configured
 ``durable_cache_path``.
@@ -319,8 +319,8 @@ Airflow < 3.3 it is a JSON file named 
``{dag_id}_{task_id}_{run_id}.json`` (with
 .. note::
 
     Runs that fail permanently (exhaust all retries) leave their cached steps
-    behind. These do not affect future DAG runs (each run is scoped 
separately).
-    On Airflow >= 3.3 they are reclaimed when the DAG run is removed; on 
Airflow
+    behind. These do not affect future Dag runs (each run is scoped 
separately).
+    On Airflow >= 3.3 they are reclaimed when the Dag run is removed; on 
Airflow
     < 3.3 the orphaned JSON files consume storage until cleaned up, so add a
     lifecycle policy to the storage backend or remove them periodically.
 
@@ -380,7 +380,7 @@ Capabilities compose with toolsets -- pydantic-ai merges 
tools from both.
 
     ``agent_params`` is a templated field, which Airflow serializes by calling
     ``str()`` on values it doesn't natively understand. Capability instances
-    are not yet round-trip-safe through DAG serialization, so the examples
+    are not yet round-trip-safe through Dag serialization, so the examples
     below construct them inside the ``@dag`` function -- not at module level.
     First-class ``capabilities=`` support on ``AgentOperator`` (with proper
     serializer hooks) is tracked as a follow-up.
@@ -489,6 +489,29 @@ Parameters
   When set, the post-run transcript is pushed to XCom under the key
   ``message_history`` for the next run to resume. Default ``None`` 
(single-turn).
   See `Multi-turn Sessions`_.
+- ``serialize_output``: If ``True`` and ``output_type`` is a Pydantic
+  ``BaseModel`` subclass, the model instance is dumped to a ``dict`` via
+  ``model_dump()`` before being pushed to XCom. Default ``False`` -- the
+  Pydantic instance flows through XCom unchanged. Set to ``True`` when a
+  downstream consumer needs the dict shape.
+
+**HITL Review parameters** (requires the ``hitl_review`` plugin -- see
+:doc:`../hitl_review` for the full review workflow):
+
+- ``enable_hitl_review``: When ``True``, the operator enters an iterative
+  review loop after the first generation. A human reviewer can approve,
+  reject, or request changes via the plugin's REST API at ``/hitl-review``
+  or through the **HITL Review** extra link on the task instance. Default
+  ``False``.
+- ``max_hitl_iterations``: Maximum outputs shown to the reviewer (1 = initial
+  output). When the reviewer requests changes at iteration >= this limit, the
+  task fails with ``HITLMaxIterationsError`` without calling the LLM. E.g. 5
+  allows changes at iterations 1-4. Default ``5``.
+- ``hitl_timeout``: Maximum wall-clock time to wait for all review rounds
+  combined. ``None`` means no timeout (the operator blocks until a terminal
+  action).
+- ``hitl_poll_interval``: Seconds between XCom polls while waiting for a
+  human response. Default ``10``.
 
 
 Logging
diff --git a/providers/common/ai/docs/operators/index.rst 
b/providers/common/ai/docs/operators/index.rst
index 7eaf414fe3a..e8b043bf374 100644
--- a/providers/common/ai/docs/operators/index.rst
+++ b/providers/common/ai/docs/operators/index.rst
@@ -62,7 +62,7 @@ via an ``output_type`` Pydantic model.
 
 **LLMFileAnalysisOperator / @task.llm_file_analysis** — stateless, single-turn 
file analysis.
 Use this when the prompt should reason over file contents or multimodal 
attachments already chosen
-by the DAG author. The operator resolves files via ``ObjectStoragePath`` and 
keeps the interaction
+by the Dag author. The operator resolves files via ``ObjectStoragePath`` and 
keeps the interaction
 read-only.
 
 **AgentOperator / @task.agent** — multi-turn tool-calling loop. The model 
decides which tools to
diff --git a/providers/common/ai/docs/operators/llamaindex_retrieval.rst 
b/providers/common/ai/docs/operators/llamaindex_retrieval.rst
index 6e0793604ab..3f064a2b825 100644
--- a/providers/common/ai/docs/operators/llamaindex_retrieval.rst
+++ b/providers/common/ai/docs/operators/llamaindex_retrieval.rst
@@ -40,7 +40,7 @@ Basic usage
     :start-after: [START howto_hook_llamaindex_retrieve]
     :end-before: [END howto_hook_llamaindex_retrieve]
 
-``query`` is templated, so DAG-run params, XCom, and Variables all flow
+``query`` is templated, so Dag-run params, XCom, and Variables all flow
 through cleanly.
 
 Cloud-persisted indexes
diff --git a/providers/common/ai/docs/operators/llm.rst 
b/providers/common/ai/docs/operators/llm.rst
index 28187d1c183..426a2573206 100644
--- a/providers/common/ai/docs/operators/llm.rst
+++ b/providers/common/ai/docs/operators/llm.rst
@@ -51,7 +51,7 @@ so downstream tasks can type-hint the class directly
 
 The declared ``output_type`` (and any ``BaseModel`` reachable from
 ``Union``/``Optional``/``list`` shapes) is registered for XCom deserialization 
by
-the worker when it loads the DAG, before any task runs -- so no edit to
+the worker when it loads the Dag, before any task runs -- so no edit to
 ``[core] allowed_deserialization_classes`` is needed. The Pydantic class must 
be
 defined at **module scope** and bound to an attribute matching its 
``__name__``;
 classes nested inside a function or ``@dag``-decorated body, parameterized
@@ -69,9 +69,9 @@ warning at worker startup and the value fails to deserialize 
at the consumer.
     :start-after: [START howto_operator_llm_structured]
     :end-before: [END howto_operator_llm_structured]
 
-Registration covers downstream tasks in the **same DAG**: every worker walks 
the
-loaded DAG's tasks at startup and registers each declared class, so it also 
works
-for mapped producers (``.expand(...)``) and for workers that load DAGs from a
+Registration covers downstream tasks in the **same Dag**: every worker walks 
the
+loaded Dag's tasks at startup and registers each declared class, so it also 
works
+for mapped producers (``.expand(...)``) and for workers that load Dags from a
 cache that bypasses operator construction.
 
 The Airflow UI's XCom viewer renders Pydantic instances via the
@@ -80,8 +80,8 @@ The Airflow UI's XCom viewer renders Pydantic instances via 
the
 allow-list. It is not pretty (no field-by-field rendering today), but the value
 shows up; no configuration is required.
 
-The remaining gap is **cross-DAG** ``xcom_pull`` -- a task in a different DAG
-that pulls this XCom only parses its own DAG file, not the producer's, so the
+The remaining gap is **cross-Dag** ``xcom_pull`` -- a task in a different Dag
+that pulls this XCom only parses its own Dag file, not the producer's, so the
 class is not auto-registered. Add the class qualified name to
 ``[core] allowed_deserialization_classes`` (or a glob that matches it) to make
 that pattern work.
diff --git a/providers/common/ai/docs/operators/llm_branch.rst 
b/providers/common/ai/docs/operators/llm_branch.rst
index 3c9e6490823..42db970427a 100644
--- a/providers/common/ai/docs/operators/llm_branch.rst
+++ b/providers/common/ai/docs/operators/llm_branch.rst
@@ -24,7 +24,7 @@ Use 
:class:`~airflow.providers.common.ai.operators.llm_branch.LLMBranchOperator`
 for LLM-driven branching — where the LLM decides which downstream task(s) to
 execute.
 
-The operator discovers downstream tasks automatically from the DAG topology
+The operator discovers downstream tasks automatically from the Dag topology
 and presents them to the LLM as a constrained enum via pydantic-ai structured
 output. No text parsing or manual validation is needed.
 
@@ -80,7 +80,7 @@ How It Works
 
 At execution time, the operator:
 
-1. Reads ``self.downstream_task_ids`` from the DAG topology.
+1. Reads ``self.downstream_task_ids`` from the Dag topology.
 2. Creates a dynamic ``Enum`` with one member per downstream task ID.
 3. Passes that enum as ``output_type`` to ``pydantic-ai``, constraining the 
LLM to
    valid task IDs only.
diff --git a/providers/common/ai/docs/operators/llm_file_analysis.rst 
b/providers/common/ai/docs/operators/llm_file_analysis.rst
index 5e38851ef86..8b2733ab05a 100644
--- a/providers/common/ai/docs/operators/llm_file_analysis.rst
+++ b/providers/common/ai/docs/operators/llm_file_analysis.rst
@@ -80,12 +80,12 @@ back from the LLM instead of a plain string. The model 
instance is pushed to
 XCom unchanged so downstream tasks can type-hint the class directly. The
 declared ``output_type`` (and any ``BaseModel`` reachable from
 ``Union``/``Optional``/``list`` shapes) is registered for deserialization by 
the
-worker when it loads the DAG. Define the class at **module scope** and bind it 
to
+worker when it loads the Dag. Define the class at **module scope** and bind it 
to
 an attribute matching its ``__name__``: nested-in-function and 
dynamically-built
 classes cannot be re-imported, so they are skipped at worker startup and fail 
to
-deserialize at the consumer. Same-DAG downstream tasks need no configuration; 
the
+deserialize at the consumer. Same-Dag downstream tasks need no configuration; 
the
 UI XCom viewer renders the value
-via the ``stringify`` path (no configuration needed). Cross-DAG ``xcom_pull``
+via the ``stringify`` path (no configuration needed). Cross-Dag ``xcom_pull``
 consumers still need the class ``qualname`` added to
 ``[core] allowed_deserialization_classes`` (see the ``LLMOperator`` guide for
 details).
@@ -140,6 +140,15 @@ Parameters
   ``BaseModel`` for structured output.
 - ``agent_params``: Additional keyword arguments passed to the pydantic-ai
   ``Agent`` constructor (e.g. ``retries``, ``model_settings``).
+- ``serialize_output``: If ``True`` and ``output_type`` is a Pydantic
+  ``BaseModel`` subclass, the model instance is dumped to a ``dict`` via
+  ``model_dump()`` before being pushed to XCom. Default ``False`` -- the
+  Pydantic instance flows through XCom unchanged. Set to ``True`` when a
+  downstream consumer needs the dict shape.
+
+This operator also inherits ``LLMOperator``'s HITL review parameters --
+``require_approval``, ``approval_timeout``, and ``allow_modifications`` -- see
+:doc:`llm` for details.
 
 Supported Formats
 -----------------
diff --git a/providers/common/ai/docs/quickstart.rst 
b/providers/common/ai/docs/quickstart.rst
index ec3d07941eb..450932e3cb2 100644
--- a/providers/common/ai/docs/quickstart.rst
+++ b/providers/common/ai/docs/quickstart.rst
@@ -49,12 +49,12 @@ for the full reference, including providers that
 don't need an API key (Bedrock, Vertex AI).
 
 The quickest way to set one up is an environment variable. Replace
-``openai:gpt-5.3`` with a model you have access to and ``sk-...`` with your
+``openai:gpt-5.6-sol`` with a model you have access to and ``sk-...`` with your
 actual API key:
 
 .. code-block:: bash
 
-    export AIRFLOW_CONN_PYDANTICAI_DEFAULT='{"conn_type": "pydanticai", 
"password": "sk-...", "extra": {"model": "openai:gpt-5.3"}}'
+    export AIRFLOW_CONN_PYDANTICAI_DEFAULT='{"conn_type": "pydanticai", 
"password": "sk-...", "extra": {"model": "openai:gpt-5.6-sol"}}'
 
 Or add it through the Airflow UI (``Admin > Connections``) or the CLI 
(``airflow connections add``).
 
diff --git a/providers/common/ai/docs/retry_policies.rst 
b/providers/common/ai/docs/retry_policies.rst
index 036bc8e5908..8456b1262aa 100644
--- a/providers/common/ai/docs/retry_policies.rst
+++ b/providers/common/ai/docs/retry_policies.rst
@@ -18,7 +18,8 @@
 LLM Retry Policies
 ===================
 
-.. versionadded:: 3.3.0
+.. note::
+    Requires Airflow >= 3.3.0.
 
 The ``LLMRetryPolicy`` uses an LLM to classify task errors and make intelligent
 retry decisions. It works with any LLM provider supported by pydantic-ai
@@ -40,7 +41,7 @@ Setup
    - **Connection Id**: ``pydanticai_default``
    - **Connection Type**: ``Pydantic AI``
    - **Password**: Your API key
-   - **Extra**: ``{"model": "anthropic:claude-haiku-4-5-20251001"}``
+   - **Extra**: ``{"model": "anthropic:claude-haiku-4-5"}``
 
 Usage
 -----
diff --git a/providers/common/ai/docs/toolsets.rst 
b/providers/common/ai/docs/toolsets.rst
index d97a8fece2b..faa407d6676 100644
--- a/providers/common/ai/docs/toolsets.rst
+++ b/providers/common/ai/docs/toolsets.rst
@@ -364,7 +364,7 @@ For prototyping or when you want full PydanticAI control, 
you can pass
     )
 
 This works because PydanticAI's ``MCPToolset`` implements ``AbstractToolset``.
-The tradeoff: URLs and credentials are hardcoded in DAG code instead of being
+The tradeoff: URLs and credentials are hardcoded in Dag code instead of being
 managed through Airflow connections and secret backends.
 
 
@@ -392,8 +392,8 @@ extra to use it:
 
 Each source is a local directory or a connection-resolved
 :class:`~airflow.providers.common.ai.skills.GitSkills`. Sources are resolved 
when
-the agent enters the toolset, on the worker -- never while the DAG processor
-parses the file -- so a Git token is never baked into the serialized DAG, and
+the agent enters the toolset, on the worker -- never while the Dag processor
+parses the file -- so a Git token is never baked into the serialized Dag, and
 cloned repositories are removed when the run ends.
 
 A local directory of ``SKILL.md`` bundles:
@@ -425,7 +425,7 @@ need strict isolation.
 
     Skill bundles can contain scripts that the agent may run on the worker via
     the ``run_skill_script`` tool. For a remote source, anyone who can modify 
the
-    repository can introduce code that executes on your worker, outside DAG
+    repository can introduce code that executes on your worker, outside Dag
     review and versioning. Point ``GitSkills`` at a trusted repository, pin
     ``branch`` to a trusted ref, and treat skill contents as code that runs in
     your environment.
@@ -544,8 +544,8 @@ before it runs. If no registered tool can read the 
environment, the
 filesystem, or other connections, the model cannot reach them, regardless of
 what the prompt instructs it to do.
 
-This is what "untrusted" means in this context. The DAG file itself is
-author-written and trusted, exactly like any other DAG. What is untrusted is
+This is what "untrusted" means in this context. The Dag file itself is
+author-written and trusted, exactly like any other Dag. What is untrusted is
 the model's *output*: the tool-call requests and text it generates. That output
 is confined to your registered tools and bounded by the tool-call budget. An
 agent cannot create a new connection, read another connection's credentials, or
@@ -570,13 +570,13 @@ No single layer is sufficient — they work together.
      - What it does
      - What it does NOT do
    * - **Airflow Connections**
-     - Credentials are stored in Airflow's secret backend, never in DAG code.
+     - Credentials are stored in Airflow's secret backend, never in Dag code.
        The LLM agent cannot see API keys or database passwords.
      - Does not prevent the agent from using the connection to access data
        the connection has access to.
    * - **HookToolset: explicit allow-list**
      - Only methods listed in ``allowed_methods`` are exposed as tools.
-       Auto-discovery is not supported. Methods are validated at DAG parse
+       Auto-discovery is not supported. Methods are validated at Dag parse
        time.
      - Does not restrict what arguments the agent passes to allowed methods.
    * - **SQLToolset: read-only by default**
@@ -719,7 +719,7 @@ Production Checklist
 Before deploying an agent task to production:
 
 1. **Connection credentials**: Use Airflow's secret backend. Never hardcode
-   API keys in DAG files.
+   API keys in Dag files.
 2. **Database permissions**: Create a dedicated database user with minimum
    required grants. Don't reuse the admin connection.
 3. **Tool allow-list**: Review ``allowed_methods`` / ``allowed_tables``. The
diff --git a/providers/common/ai/provider.yaml 
b/providers/common/ai/provider.yaml
index 0d63e6f4202..e5c26e60a55 100644
--- a/providers/common/ai/provider.yaml
+++ b/providers/common/ai/provider.yaml
@@ -158,7 +158,7 @@ connection-types:
     conn-fields:
       model:
         label: Model
-        description: "Model in provider:name format (e.g. 
anthropic:claude-sonnet-4-20250514, openai:gpt-5)"
+        description: "Model in provider:name format (e.g. 
anthropic:claude-sonnet-5, openai:gpt-5)"
         schema:
           type:
             - string
@@ -388,7 +388,7 @@ connection-types:
         description: >
           Chat model in provider:name format dispatched via
           langchain.chat_models.init_chat_model
-          (e.g. openai:gpt-4o, anthropic:claude-3-7-sonnet).
+          (e.g. openai:gpt-4o, anthropic:claude-sonnet-5).
         schema:
           type:
             - string
diff --git 
a/providers/common/ai/src/airflow/providers/common/ai/get_provider_info.py 
b/providers/common/ai/src/airflow/providers/common/ai/get_provider_info.py
index 4f31d62e84e..89d96737d94 100644
--- a/providers/common/ai/src/airflow/providers/common/ai/get_provider_info.py
+++ b/providers/common/ai/src/airflow/providers/common/ai/get_provider_info.py
@@ -128,7 +128,7 @@ def get_provider_info():
                 "conn-fields": {
                     "model": {
                         "label": "Model",
-                        "description": "Model in provider:name format (e.g. 
anthropic:claude-sonnet-4-20250514, openai:gpt-5)",
+                        "description": "Model in provider:name format (e.g. 
anthropic:claude-sonnet-5, openai:gpt-5)",
                         "schema": {"type": ["string", "null"]},
                     }
                 },
@@ -305,7 +305,7 @@ def get_provider_info():
                 "conn-fields": {
                     "model": {
                         "label": "Chat Model",
-                        "description": "Chat model in provider:name format 
dispatched via langchain.chat_models.init_chat_model (e.g. openai:gpt-4o, 
anthropic:claude-3-7-sonnet).\n",
+                        "description": "Chat model in provider:name format 
dispatched via langchain.chat_models.init_chat_model (e.g. openai:gpt-4o, 
anthropic:claude-sonnet-5).\n",
                         "schema": {"type": ["string", "null"]},
                     },
                     "embed_model": {
diff --git 
a/providers/common/ai/src/airflow/providers/common/ai/hooks/pydantic_ai.py 
b/providers/common/ai/src/airflow/providers/common/ai/hooks/pydantic_ai.py
index c46f974a59c..8f4e71a9a69 100644
--- a/providers/common/ai/src/airflow/providers/common/ai/hooks/pydantic_ai.py
+++ b/providers/common/ai/src/airflow/providers/common/ai/hooks/pydantic_ai.py
@@ -53,10 +53,10 @@ class PydanticAIHook(BaseHook):
     Connection fields:
         - **password**: API key
         - **host**: Base URL (optional, e.g. ``https://api.openai.com/v1``)
-        - **extra** JSON: ``{"model": "openai:gpt-5.3"}``
+        - **extra** JSON: ``{"model": "openai:gpt-5.6-sol"}``
 
     :param llm_conn_id: Airflow connection ID for the LLM provider.
-    :param model_id: Model identifier in ``provider:model`` format (e.g. 
``"openai:gpt-5.3"``).
+    :param model_id: Model identifier in ``provider:model`` format (e.g. 
``"openai:gpt-5.6-sol"``).
         Overrides the model stored in the connection's extra field.
     """
 
@@ -90,7 +90,7 @@ class PydanticAIHook(BaseHook):
             "relabeling": {"password": "API Key"},
             "placeholders": {
                 "host": "https://api.openai.com/v1  (optional, for custom 
endpoints / Ollama)",
-                "extra": '{"model": "openai:gpt-5.3"}',
+                "extra": '{"model": "openai:gpt-5.6-sol"}',
             },
         }
 
diff --git a/providers/common/ai/tests/unit/common/ai/hooks/test_pydantic_ai.py 
b/providers/common/ai/tests/unit/common/ai/hooks/test_pydantic_ai.py
index 4d7baf9b4e7..0290da3c133 100644
--- a/providers/common/ai/tests/unit/common/ai/hooks/test_pydantic_ai.py
+++ b/providers/common/ai/tests/unit/common/ai/hooks/test_pydantic_ai.py
@@ -41,9 +41,9 @@ class TestPydanticAIHookInit:
         assert hook.model_id is None
 
     def test_custom_conn_id(self):
-        hook = PydanticAIHook(llm_conn_id="my_llm", model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="my_llm", 
model_id="openai:gpt-5.6-sol")
         assert hook.llm_conn_id == "my_llm"
-        assert hook.model_id == "openai:gpt-5.3"
+        assert hook.model_id == "openai:gpt-5.6-sol"
 
     def test_azure_hook_uses_own_default_conn_name(self):
         """Subclass default_conn_name is used, not the base class value."""
@@ -69,7 +69,7 @@ class TestPydanticAIHookGetConn:
         mock_provider = MagicMock()
         mock_infer_provider_class.return_value = 
MagicMock(return_value=mock_provider)
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(
             conn_id="test_conn",
             conn_type="pydanticai",
@@ -82,7 +82,7 @@ class TestPydanticAIHookGetConn:
         assert result is mock_model
         mock_infer_model.assert_called_once()
         call_args = mock_infer_model.call_args
-        assert call_args[0][0] == "openai:gpt-5.3"
+        assert call_args[0][0] == "openai:gpt-5.6-sol"
         # provider_factory should be passed as keyword arg
         assert "provider_factory" in call_args[1]
 
@@ -120,7 +120,7 @@ class TestPydanticAIHookGetConn:
         mock_infer_model.return_value = MagicMock(spec=Model)
         mock_infer_provider_class.return_value = 
MagicMock(return_value=MagicMock())
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(
             conn_id="test_conn",
             conn_type="pydanticai",
@@ -131,7 +131,7 @@ class TestPydanticAIHookGetConn:
             hook.get_conn()
 
         # model_id param takes priority over extra
-        assert mock_infer_model.call_args[0][0] == "openai:gpt-5.3"
+        assert mock_infer_model.call_args[0][0] == "openai:gpt-5.6-sol"
 
     def test_get_conn_raises_when_no_model(self):
         hook = PydanticAIHook(llm_conn_id="test_conn")
@@ -188,7 +188,7 @@ class TestPydanticAIHookGetConn:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         with patch.object(hook, "get_connection", return_value=conn):
             first = hook.get_conn()
@@ -205,7 +205,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(
             conn_id="test_conn",
             conn_type="pydanticai",
@@ -225,7 +225,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(
             conn_id="test_conn",
             conn_type="pydanticai",
@@ -245,7 +245,7 @@ class TestPydanticAIHookCreateAgent:
         )
 
     def test_create_agent_without_instructions_or_spec_file_raises(self):
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         with pytest.raises(ValueError, match="instructions is required"):
             hook.create_agent()
 
@@ -256,7 +256,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         with patch.object(hook, "get_connection", return_value=conn):
             hook.create_agent(spec_file="/path/to/agent.yaml")
@@ -293,7 +293,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         spec_path = Path("/path/to/agent.yaml")
         with patch.object(hook, "get_connection", return_value=conn):
@@ -314,7 +314,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         with patch.object(hook, "get_connection", return_value=conn):
             hook.create_agent(
@@ -336,7 +336,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         with patch.object(hook, "get_connection", return_value=conn):
             hook.create_agent(output_type=dict, 
spec_file="/path/to/agent.yaml")
@@ -354,7 +354,7 @@ class TestPydanticAIHookCreateAgent:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(conn_id="test_conn", conn_type="pydanticai")
         with patch.object(hook, "get_connection", return_value=conn):
             hook.create_agent(
@@ -377,7 +377,7 @@ class TestPydanticAIHookCreateAgentInstrumentation:
 
     @staticmethod
     def _hook() -> PydanticAIHook:
-        return PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        return PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
 
     
@patch("airflow.providers.common.ai.hooks.pydantic_ai.genai_instrumentation_settings")
     def test_instrument_set_when_settings_returned(self, mock_settings):
@@ -430,7 +430,7 @@ class TestPydanticAIHookTestConnection:
         mock_model = MagicMock(spec=Model)
         mock_infer_model.return_value = mock_model
 
-        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.3")
+        hook = PydanticAIHook(llm_conn_id="test_conn", 
model_id="openai:gpt-5.6-sol")
         conn = Connection(
             conn_id="test_conn",
             conn_type="pydanticai",


Reply via email to