Fix PydanticAIHook.get_hook losing the caller's conn_id with secrets-backend aliases#69969
Fix PydanticAIHook.get_hook losing the caller's conn_id with secrets-backend aliases#69969dabla wants to merge 11 commits into
PydanticAIHook.get_hook losing the caller's conn_id with secrets-backend aliases#69969Conversation
…ets-backend aliases
…ethod in BaseHook which in turn is sued by get_hook and aget_hook, so this issue is then solved at a global level for sync and async hook retrieval
…connection aliases
…need the onwards word which isn't present in the spelling wordlist
amoghrajesh
left a comment
There was a problem hiding this comment.
Before making the BaseHookchange, it is worth checking whether this is actually needed. Airflow's secrets-backend contract already guarantees that Connection.conn_id on the object returned by get_connection() matches the requested lookup key, see: https://github.com/apache/airflow/blob/main/shared/secrets_backend/src/airflow_shared/secrets_backend/base.py#L121-L157
Both construct the Connection using the requested conn_id, not anything derived from the secret's contents. Every stock backend such as EnvironmentVariablesBackend, MetastoreBackend, LocalFilesystemBackend, and the Hashicorp VaultBackend only override get_conn_valueand never touches conn_id. That is how alias style translation is supposed to work: the backend uses the alias to find the right underlying secret, but the Connection object it hands back still identifies itself by the alias.
The custom backend that you describe in this PR might be overriding get_connection/deserialize_connection (or constructing Connection some other way) and explicitly stamping the canonical, environment specific id onto conn_id which is a deviation from the contract every other backend honors, not a gap in BaseHook as I see it
Can you check in the custom backend for above and have it return Connection(conn_id=<alias>, ...) and keep the canonical/resolved id purely as an internal lookup detail?
…ntic_ai.py Co-authored-by: Wei Lee <hello@wei-lee.me>
Co-authored-by: Wei Lee <hello@wei-lee.me>
Good point @amoghrajesh, I will try this change in our custom provider, if it fixes the issue, then I'll close this PR. |
Fix
LLMOperator/@task.agentfailing with secrets-backend connection aliasesContext
We use a custom secrets backend provider built on top of HashiCorp Vault that
introduces environment-independent connection aliases.
Dag authors never hardcode environment-specific connection ids
(e.g.
openai-dev,openai-prod). Instead they reference a single logicalalias (e.g.
my-llm) that is stable across every environment. The secretsbackend knows at runtime which environment it is deployed in and resolves the
alias to the correct underlying Vault secret — returning a
Connectionwhoseconn_idis the canonical, environment-specific id (openai-prod,openai-dev, …).This keeps Dags 100% environment-agnostic: the same
conn_id="my-llm"worksin development, staging, and production without any per-environment
configuration in the Dag code.
Problem
When
get_connection("my-llm")is called, the secrets backend returns aConnectionobject whoseconn_idhas been rewritten to the resolved,canonical id (e.g.
"openai-prod").BaseHook.get_hookpassed thatConnectionstraight toconnection.get_hook(),which instantiated the hook with
llm_conn_id = "openai-prod". Any subsequentget_conn()call (e.g. insideLLMOperator/@task.agent) then tried tofetch
"openai-prod"from the secrets backend — a key it does not recognise,because only the alias
"my-llm"is registered — and raisedAirflowNotFoundException.Fix
Override
get_hookinPydanticAIHookto callsuper().get_hook()and thenimmediately restore the caller's original
conn_id(the alias) on the hook:Why override here and not only in
BaseHook?BaseHookapplies the same fix starting from Airflow 3.4. However,providers are independently releasable — a user on Airflow 3.2 or 3.3 can
upgrade this provider without upgrading Airflow core. Keeping the override in
PydanticAIHookensures the fix is available on all supported Airflowversions as soon as the provider is updated.
The two fixes are intentionally complementary:
BaseHookrekeyed?PydanticAIHookoverride rekeyed?setattr)BaseHookImpact
LLMOperatorand@task.agentwhen connections are stored underenvironment-independent aliases in a custom secrets backend, on any supported
Airflow version.
conn_id(the
setattris a no-op in that case).Was generative AI tooling used to co-author this PR?
Claude Sonnet 4.6
{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.