airflow.providers.common.ai.hooks.pydantic_ai¶
Attributes¶
Classes¶
Hook for LLM access via pydantic-ai. |
|
Hook for Azure OpenAI via pydantic-ai. |
|
Hook for AWS Bedrock via pydantic-ai. |
|
Hook for Google Vertex AI (or Generative Language API) via pydantic-ai. |
Module Contents¶
- airflow.providers.common.ai.hooks.pydantic_ai.FALLBACK_CONN_IDS_EXTRA_KEY = 'fallback_conn_ids'[source]¶
- class airflow.providers.common.ai.hooks.pydantic_ai.PydanticAIHook(llm_conn_id=None, model_id=None, fallback_conn_ids=None, **kwargs)[source]¶
Bases:
airflow.providers.common.compat.sdk.BaseHookHook for LLM access via pydantic-ai.
Covers providers that use a standard
api_key+ optionalbase_url(OpenAI, Anthropic, Groq, Mistral, DeepSeek, Ollama, vLLM, …).For cloud providers with non-standard auth use the dedicated subclasses:
PydanticAIAzureHook,PydanticAIBedrockHook,PydanticAIVertexHook.- Connection fields:
password: API key
host: Base URL (optional, e.g.
https://api.openai.com/v1)extra JSON:
{"model": "openai:gpt-5.6-sol", "fallback_conn_ids": ["anthropic_prod", "bedrock_dr"]}
- Parameters:
llm_conn_id (str | None) – Airflow connection ID for the LLM provider.
model_id (str | None) – Model identifier. A name whose segment before the first
:is itself a pydantic-ai provider (e.g."openai:gpt-5.6-sol") pins the platform and is used verbatim – a plain:alone is not enough, since some vendors’ native model ids contain one of their own (e.g. Bedrock’s version-suffixed"us.anthropic.claude-opus-4-6-v1:0", which is still a bare name here). A bare name is resolved against this connection’s own platform: vendor subclasses (PydanticAIAzureHook,PydanticAIBedrockHook,PydanticAIVertexHook) each default to their own platform viamodel_provider; the generic connection type has none, so a bare name there raisesValueErrorinstead of reaching pydantic-ai’s own, less actionableUnknown modelerror. Overrides the model stored in the connection’s extra field. Whichever of the two configures the primary’s model is forwarded (only while still bare) down the fallback chain – see_resolve_fallback_models().fallback_conn_ids (list[str] | None) – Connection IDs to fail over to, in order, when the primary provider is unavailable. Overrides the
fallback_conn_idslist stored in the connection’s extra field; pass an empty list to disable a chain configured there. Blank or whitespace-only entries (including a trailing blank line from the Fallback Connections textarea) are dropped; a chain left entirely blank is treated the same as passing[]. Each entry may point at anypydanticai*connection type, so the chain can span providers (for example OpenAI, then Bedrock). Seeget_conn()for the failover semantics and their cost.
- static get_ui_field_behaviour()[source]¶
Return custom field behaviour for the Airflow connection form.
- get_conn()[source]¶
Return a configured pydantic-ai
Model.Resolution order for this hook’s own connection:
Explicit credentials — when
_get_provider_kwargs()returns a non-empty dict the provider class is instantiated with those kwargs and wrapped in aprovider_factory.Default resolution — delegates to pydantic-ai
infer_modelwhich reads standard env vars (OPENAI_API_KEY,AWS_PROFILE, …).
A bare
model_id(one with no recognized platform prefix) is qualified with this connection’s own platform before either of the above – see the class docstring’smodel_identry for the resolution and fallback-forwarding rules.When
fallback_conn_idsis configured (on the hook or in the connection’s extra) the resolved models are wrapped in a pydantic-aiFallbackModel, so a provider outage moves to the next connection within the same task attempt instead of failing the task.Two costs of that wrapping are worth knowing before configuring a long chain. A
timeoutinModelSettingsis applied by pydantic-ai to every model in the chain rather than to the chain as a whole, so the worst-case wait is the timeout multiplied by the number of connections. And there is no circuit breaker: every call retries the primary first, so during an outage each task instance pays the primary’s timeout again. Keep the primary’s timeout short to bound both.The resolved model is cached for the lifetime of this hook instance.
- create_agent(output_type: type[OutputT], *, instructions: str, **agent_kwargs) pydantic_ai.Agent[object, OutputT][source]¶
- create_agent(*, instructions: str, **agent_kwargs) pydantic_ai.Agent[object, str]
- create_agent(output_type: type[OutputT], *, spec_file: str | pathlib.Path, instructions: str | None = ..., **agent_kwargs) pydantic_ai.Agent[object, OutputT]
- create_agent(*, spec_file: str | pathlib.Path, instructions: str | None = ..., **agent_kwargs) pydantic_ai.Agent[object, str]
Create a pydantic-ai Agent configured with this hook’s model.
When
[common.ai] otel_export_enabledis set and the worker has an OpenTelemetry exporter configured, the agent is instrumented to emit GenAI spans through Airflow’s tracing pipeline. Seeairflow.providers.common.ai.observability.- Parameters:
output_type – The expected output type from the agent (default:
str).instructions – System-level instructions for the agent. Required when spec_file is not given. When spec_file is given, this value is merged with the instructions in the file; omit it to use only the file value.
spec_file – Path to a YAML or JSON
AgentSpecfile. When supplied, delegates toAgent.from_file. Ifmodel_idor the connection’smodelextra is set, that model is passed to pydantic-ai; otherwise the spec file’smodelis used. A connection that declaresfallback_conn_idsbut nomodelraisesValueErrorinstead: a model resolved from the spec file cannot be wrapped in a fallback chain, so the chain would otherwise be dropped silently.agent_kwargs – Additional keyword arguments passed to the Agent constructor.
- test_connection()[source]¶
Test connection by resolving the model.
A success here can come from this connection’s own credentials, or – when a provider class rejects them with a
TypeError– from a silent retry against the standard environment variables, which ignores those credentials entirely. See Provider fallback’s Verifying a chain section for how to tell the two apart. Does NOT make an LLM API call — that would be expensive and fail for reasons unrelated to connectivity (quotas, billing, rate limits).Every connection in
fallback_conn_idsis resolved too, so a misconfigured fallback is reported here rather than discovered during the outage it was meant to cover.
- class airflow.providers.common.ai.hooks.pydantic_ai.PydanticAIAzureHook(llm_conn_id=None, model_id=None, fallback_conn_ids=None, **kwargs)[source]¶
Bases:
PydanticAIHookHook for Azure OpenAI via pydantic-ai.
- Connection fields:
password: Azure API key
host: Azure endpoint (e.g.
https://<resource>.openai.azure.com/openai/v1)extra JSON:
{"model": "azure:gpt-4o"}
api_versionmust be omitted when the endpoint path ends in/v1or the host is*.models.ai.azure.com. For other endpoints, set it here or withOPENAI_API_VERSION.
- Parameters:
- class airflow.providers.common.ai.hooks.pydantic_ai.PydanticAIBedrockHook(llm_conn_id=None, model_id=None, fallback_conn_ids=None, **kwargs)[source]¶
Bases:
PydanticAIHookHook for AWS Bedrock via pydantic-ai.
Credentials are resolved in order:
Bearer token in
extra(api_key, maps to envAWS_BEARER_TOKEN_BEDROCK). Takes precedence over IAM keys if both are set.IAM keys from
extra(aws_access_key_id+aws_secret_access_key, optionallyaws_session_token).Environment-variable / instance-role chain (
AWS_PROFILE, IAM role, …) when no explicit keys are provided.
- Connection fields:
extra JSON:
{ "model": "bedrock:us.anthropic.claude-opus-4-5", "region_name": "us-east-1", "aws_access_key_id": "AKIA...", "aws_secret_access_key": "...", "aws_session_token": "...", "profile_name": "my-aws-profile", "api_key": "bearer-token", "base_url": "https://custom-bedrock-endpoint", "aws_read_timeout": 60.0, "aws_connect_timeout": 10.0 }
Leave
aws_access_key_id/aws_secret_access_keyandapi_keyempty to use the default AWS credential chain.
- Parameters:
- class airflow.providers.common.ai.hooks.pydantic_ai.PydanticAIVertexHook(llm_conn_id=None, model_id=None, fallback_conn_ids=None, **kwargs)[source]¶
Bases:
PydanticAIHookHook for Google Vertex AI (or Generative Language API) via pydantic-ai.
Credentials are resolved in order:
service_account_info(JSON object) inextra— loaded into agoogle.auth.credentials.Credentialsobject and passed ascredentialstoGoogleProvider.api_keyinextra— for Generative Language API (non-Vertex) or Vertex API-key auth.Application Default Credentials (
GOOGLE_APPLICATION_CREDENTIALS,gcloud auth application-default login, Workload Identity, …) when no explicit credentials are provided.
- Connection fields:
extra JSON:
{ "model": "google-cloud:gemini-2.0-flash", "project": "my-gcp-project", "location": "us-central1", "service_account_info": {...}, }
Use
"service_account_info"to embed the service-account JSON directly (as an object, not a string path)."vertexai"is accepted for backward compatibility but has no effect: pydantic-ai now selects Vertex AI vs. the Generative Language API from the model prefix (google-cloud:vs.google:) rather than a constructor flag, so there is nothing left for this field to control.
A bare
model_id(or Extramodel) always defaults to Vertex AI (google-cloud:) – this default is not inferred from which credential fields are set.api_keyinextracan mean either the Generative Language API or Vertex API-key auth (see credential order above), so its presence alone cannot tell the two platforms apart; guessing would risk silently authenticating against the wrong endpoint. To use the Generative Language API, set an explicitgoogle:-prefixed model id (on the hook or the connection’smodelextra) – that spelling already works today.- Parameters: