Skip to content

Python: fix kernel_function decorator mutating shared Annotated metadata dicts - #14442

Open
Manohar Paturi (ManoharPaturi) wants to merge 3 commits into
microsoft:mainfrom
ManoharPaturi:fix/kernel-function-metadata-mutation
Open

Manohar Paturi (ManoharPaturi) wants to merge 3 commits into
microsoft:mainfrom
ManoharPaturi:fix/kernel-function-metadata-mutation

Conversation

@ManoharPaturi

@ManoharPaturi Manohar Paturi (ManoharPaturi) commented Sep 13, 2026 •

Copy link
Copy Markdown

Fixes #14441

Main already fixed the shared metadata mutation in #14496 with a local dict copy. This PR now changes no implementation; it pins the two contracts around that fix with regression tests:

A later dict metadata entry overrides an earlier string description (Annotated[int, "earlier string", {"description": "later dictionary"}] yields the dict description), with the caller-owned dict left untouched by decoration.
One shared metadata dict can decorate multiple kernel functions and keeps its description for each.

Both tests target current main behavior and pass against it.

…ata dicts

_parse_parameter() called meta.pop("description") on dict metadata used
in typing.Annotated, mutating the user-provided dict. When the same
metadata dict is reused across multiple kernel functions (shared
parameter docs), every function after the first silently lost its
parameter description, and the dict itself was permanently modified.

Use meta.get() instead of meta.pop() and filter the description key out
when applying the remaining metadata keys, so semantics are unchanged
but the caller's dict is left untouched.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original mutation issue is fixed on main. The inline comment identifies an additional behavior change that is not described in this PR. Its old label/review/gate runs also need fresh validation if this is retained as a separate fix.

if "description" not in ret and (description := meta.get("description", None)):
ret["description"] = description
ret.update(meta)
ret.update({key: value for key, value in meta.items() if key != "description"})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mutation bug is already fixed on main by #14496 using a local dict copy. This version also changes description precedence: Annotated[int, "earlier string", {"description": "later dictionary"}] currently produces "later dictionary", but this filtering produces "earlier string". I reproduced both results. Is that additional behavior change intentional? Please clarify the remaining bug and cover the precedence rule before rebasing; otherwise the original shared-metadata fix is already delivered.

@ManoharPaturi

Copy link
Copy Markdown
Author

The precedence change was not intentional, and you were right to flag it: filtering the description key out of the update silently flipped which entry wins. The branch now carries main's implementation from #14496 unchanged and reduces to two regression tests: the precedence rule you reproduced, where the later dict description overrides the earlier string while the caller-owned dict stays untouched, and the shared metadata contract, where one dict decorates two functions and keeps working. So the PR no longer changes behavior at all, it only pins the rules.

@semantic-kernel-automation semantic-kernel-automation Bot added the python Pull requests for the Python Semantic Kernel label Nov 5, 2026

This branch was previously deployed

1 inactive deployment
github-app-auth — 930efb08 Deployed Nov 5, 2026 by ManoharPaturi via add_label #29601
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Pull requests for the Python Semantic Kernel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: @kernel_function mutates shared Annotated metadata dicts (description lost after first use)

3 participants