Skip to content

Support custom redaction and message length cap in LLMRetryPolicy - #70830

Merged
Lee-W merged 5 commits into
apache:mainfrom
astronomer:llm-retry-redaction-hardening
Aug 7, 2026
Merged

Support custom redaction and message length cap in LLMRetryPolicy#70830
Lee-W merged 5 commits into
apache:mainfrom
astronomer:llm-retry-redaction-hardening

Conversation

@Lee-W

@Lee-W Lee-W commented Jul 31, 2026

Copy link
Copy Markdown
Member

Airflow's secrets masker only masks values already registered via mask_secret(), so free-text PII in an exception message — email addresses, customer names, account numbers — still reached the external LLM provider verbatim. Users who handle that kind of data need a way to apply their own redaction rules before the prompt leaves the worker.

Nothing bounded the message size either, so a long traceback could inflate token cost without limit on every retry decision.

The redact_exception flag this replaces was merged but has not shipped in any release, so it is removed outright rather than deprecated.


Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: [Claude] following the guidelines


  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {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.

@Lee-W
Lee-W force-pushed the llm-retry-redaction-hardening branch from d685c71 to 268fe6f Compare July 31, 2026 13:20
@Lee-W Lee-W self-assigned this Aug 3, 2026
@Lee-W
Lee-W marked this pull request as ready for review August 5, 2026 04:42
@Lee-W
Lee-W force-pushed the llm-retry-redaction-hardening branch 3 times, most recently from 9f4ac87 to 5fd7b26 Compare August 5, 2026 08:19
Comment thread providers/common/ai/src/airflow/providers/common/ai/policies/retry.py Outdated
Comment thread providers/common/ai/docs/retry_policies.rst Outdated
Comment thread providers/common/ai/tests/unit/common/ai/policies/test_retry.py
@Lee-W
Lee-W force-pushed the llm-retry-redaction-hardening branch 3 times, most recently from 7bc6b44 to 1c44094 Compare August 6, 2026 09:23
Lee-W added 5 commits August 7, 2026 15:23
Airflow's secrets masker only masks values already registered via
mask_secret(), so free-text PII in an exception message — email
addresses, customer names, account numbers — still reached the external
LLM provider verbatim. Users who handle that kind of data need a way to
apply their own redaction rules before the prompt leaves the worker.

Nothing bounded the message size either, so a long traceback could
inflate token cost without limit on every retry decision.

The redact_exception flag this replaces was merged but has not shipped in
any release, so it is removed outright rather than deprecated.
Previously, turning off redaction required passing the non-obvious
lambda s: s as a custom redactor. Passing redactor=None now disables
redaction explicitly, while the default behaviour (Airflow's secrets
masker) is unchanged.
Every other optional LLMRetryPolicy parameter treats None as "use the
default", so redactor=None meaning "send the exception text unredacted"
was a footgun: assembling kwargs programmatically, as in
redactor=cfg.get("redactor"), silently shipped raw exception text to the
LLM provider whenever that key was absent. Disabling redaction is now
spelled redact_exception=False, and combining it with an explicit
redactor is rejected at construction time instead of one of the two
settings quietly winning.

The default masker also had no name a Dag author could import. The docs
pointed at airflow.sdk.log.redact, which is not part of the Task SDK's
documented public surface and has moved home four times -- which is why
common.compat.sdk carries a fallback chain for it. Exporting
default_redactor gives callers a stable path that survives the next move.
Two tests registered a secret without first resetting the masker, so they
inherited patterns left by earlier tests and leaked their own secret into
whatever ran next. That makes them order-dependent: passing or failing
depended on what the rest of the module had already registered.
default_redactor read as an attribute rather than a callable, against the
project's action-verb naming rule, and the docs example calls it directly.
The new name also carries the limitation that matters most here: it masks
only values already registered via mask_secret(), so a Dag author reading
redactor=redact_registered_secrets learns the boundary from the name
instead of having to reach the warning block to find it.
@Lee-W
Lee-W force-pushed the llm-retry-redaction-hardening branch from 1c44094 to 60b2ce0 Compare August 7, 2026 07:23
@Lee-W
Lee-W merged commit 787e323 into apache:main Aug 7, 2026
82 checks passed
@Lee-W
Lee-W deleted the llm-retry-redaction-hardening branch August 7, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants