Repository navigation
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes Python KernelFunction.as_agent_framework_tool() so Agent Framework tool input models preserve parameter defaults (instead of incorrectly making optional parameters required), and adds a regression test to validate the behavior.
Changes:
- Prevent overwriting Pydantic fields that already include a non-
Nonedefault when building the Agent Framework tool input model. - Add a unit test asserting a parameter with
default=5remains optional in the generated tool schema.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
python/semantic_kernel/functions/kernel_function.py |
Adjusts field-building logic in as_agent_framework_tool() to avoid overwriting defaulted fields. |
python/tests/unit/functions/test_kernel_function_from_method.py |
Adds a regression test verifying optionality is preserved when a default value is present. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: No findings
Scope: full PR (1 commit(s)): a60b81246da8
Model: claude-opus-4.8
Overview
The PR converts an unconditional field-overwrite into an else branch in
KernelFunction.as_agent_framework_tool(), so a Semantic Kernel parameter carrying a
non-None default is preserved as an optional field instead of being clobbered into a
required one. The change is minimal, API-compatible, and touches no shared state,
serialization, or trust boundary. It is backed by a focused regression test that fails
against the pre-fix code and passes after, and the full test_kernel_function_from_method
suite stays green. No Critical/High/Medium defect introduced by the PR was found.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.
424431c to
f58bb39
Compare
|
已将分支变基到当前 本地验证:
新提交触发的 Python、.NET、拼写与合并门禁工作流目前均为 该分支的变基、测试与说明由 AI 辅助完成。 |
5cb90de to
c7e75d3
Compare
b91001f to
ff7fbf2
Compare
| if param.default_value is not None: | ||
| # Requiredness is explicit metadata: None can be a legitimate | ||
| # default for optional parameters and must remain a Pydantic default. | ||
| if param.is_required: |
There was a problem hiding this comment.
param.is_required does not distinguish x: str | None from x: str | None = None: the decorator marks both optional. With a nullable annotation but no Python default, this branch now creates Field(default=None), and tool.input_model() accepts the missing required argument. I reproduced this with a decorated def f(x: str | None). Preserve the missing-default distinction from the callable signature (or metadata) and add a regression for nullable-but-required parameters.
There was a problem hiding this comment.
Fixed in 87a81fd: as_agent_framework_tool now builds Fields from the underlying callable's inspect.signature when available. A parameter annotated str | None with no default stays required (no Field default), while str | None = None remains optional with a real None default. Added a regression that expects ValidationError when the nullable-without-default field is omitted.
(AI-assisted reply.)
| fields[param.name] = (param.type_, Field(description=param.description)) | ||
| else: | ||
| fields[param.name] = ( | ||
| param.type_, |
There was a problem hiding this comment.
Preserving the None default also needs a nullable field annotation. For the new test function, metadata stores label as type_="str"; the generated model therefore advertises a string-only field with default null, and tool.input_model(label=None) raises ValidationError. The current test checks the default object but never validates an explicit None. Please retain the nullable annotation and cover both omitted and explicitly-null values.
There was a problem hiding this comment.
Addressed in the same 87a81fd change: the Field annotation now comes from the callable signature (unwrapping Annotated when needed), so a nullable parameter keeps a nullable type in the generated input model instead of collapsing to a string-only field with a null default.
(AI-assisted reply.)
Build agent-framework Fields from the underlying method signature so nullable annotations without a default stay required, while `T | None = None` remains optional with a real None default.
Motivation and Context
KernelFunction.as_agent_framework_tool()currently builds a field with a parameter default and then immediately overwrites it with a required field. As a result, optional Semantic Kernel parameters become required in the Agent Framework tool schema.Description
is_requiredas the source of truth, including explicitNonedefaultsdefault=5anddefault=Noneremain optionalValidation:
uv run pytest tests/unit/functions/test_kernel_function_from_method.py -q— 37 passeduv run ruff check semantic_kernel/functions/kernel_function.py tests/unit/functions/test_kernel_function_from_method.py— passeduv run ruff format --check semantic_kernel/functions/kernel_function.py tests/unit/functions/test_kernel_function_from_method.py— passedgit diff --check— passedContribution Checklist