Python: Bound abandoned PolicyEnforcement pending approvals - #7893
Python: Bound abandoned PolicyEnforcement pending approvals#7893Shivani . (Shivani767) wants to merge 2 commits into
Conversation
Prevent unbounded memory growth by capping and expiring unconsumed policy-approval bindings, and clear pending state when an approval is explicitly rejected.
There was a problem hiding this comment.
Pull request overview
Bounds abandoned policy-approval state in long-lived Python middleware instances.
Changes:
- Adds FIFO size limits and TTL expiration.
- Adds rejection cleanup logic and regression tests.
- Rejection cleanup is not reached by the normal agent approval flow.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
python/packages/core/agent_framework/security.py |
Implements bounded pending-approval lifecycle. |
python/packages/core/tests/test_security.py |
Tests eviction, expiration, and direct rejection handling. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| "approved execution." | ||
| ), | ||
| ) | ||
| elif self._discard_rejected_pending_approval(context): |
There was a problem hiding this comment.
Good catch — rejected approvals never re-enter process().
Updated to notify middleware from _resolve_approval_responses via FunctionMiddlewarePipeline.notify_rejected_approvals → PolicyEnforcementFunctionMiddleware.discard_rejected_policy_approvals, and replaced the direct-process test with a resolver resume regression that asserts pending state is cleared without executing the tool.
Rejected approvals never re-enter function middleware, so notify PolicyEnforcement from _resolve_approval_responses and cover that path with a resume regression test.
|
Shivani . (@Shivani767) Nice work on this! I was actually working on #7890 too and had a fix ready locally, but saw your draft first and compared against it instead of duplicating the effort. I verified locally against the original repro — 5,000 unapproved calls are bounded at 256 instead of growing unbounded — and the A few optional thoughts from comparing the approaches, none blocking:
The resolver-side rejection cleanup is a nice catch — I hadn't considered that rejected approvals skip the normal middleware path. To be clear, these are just suggestions, so take or leave them. I won't open a competing PR — I just want to see #7890 fixed correctly, and it doesn't matter whose PR it is. Nice work! |
|
Patel Namraa (@Namraa310806) Thanks a lot, Namraa! Really appreciate you taking the time to verify the fix against the original repro and for sharing these suggestions. I’ll take a closer look at the deterministic clock approach, the optional debug logging for FIFO eviction, and the defense-in-depth check in Glad we can get #7890 fixed without duplicating the work. Thanks again for the review and validation! |
Motivation & Context
PolicyEnforcementFunctionMiddlewareretains pending policy-approval entries until they are successfully consumed. Whenapproval_on_violation=Trueand approvals are abandoned, rejected, or never returned,_pending_policy_approvalscan grow without bound on a long-lived middleware instance.Description & Review Guide
What are the major changes?
max_pending_policy_approvals, default 256).pending_policy_approval_ttl, default 1 hour;Nonedisables).What is the impact of these changes?
What do you want reviewers to focus on?
_resolve_approval_responsesis the right seam for rejection cleanup.Related Issue
Fixes #7890
Note: Patel Namraa (@Namraa310806) previously offered to work on this; there was no open PR when this was started. Happy to coordinate if preferred.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.