Skip to content

Python: Treat a tool call argument named settings as a function argument - #14680

Open
Dmitry Voropaev (v0ropaev) wants to merge 1 commit into
microsoft:mainfrom
v0ropaev:fix/python-settings-arg-name
Open

Dmitry Voropaev (v0ropaev) wants to merge 1 commit into
microsoft:mainfrom
v0ropaev:fix/python-settings-arg-name

Conversation

@v0ropaev

Copy link
Copy Markdown

Motivation and Context

KernelArguments.init takes a settings keyword for prompt execution settings. FunctionCallContent.to_kernel_arguments builds the arguments with KernelArguments(**args), so when a kernel function has a parameter called settings, the value the model sends for it goes into that keyword and not into the dict.

With a string value the constructor calls .service_id on it and raises AttributeError: 'str' object has no attribute 'service_id'. Kernel.invoke_function_call does not catch that, so it escapes from get_chat_message_content and the whole auto function calling request fails. I reproduced it with OpenAIChatCompletion on top of an httpx mock transport that returns one tool call with {"settings": "dark"} and FunctionChoiceBehavior.Auto(). With a dict value nothing raises, but the dict is moved into execution_settings, the argument is gone, and the model gets back "Missing required argument(s): ['settings']".

settings is not one of the reserved parameter names (kernel, service, execution_settings, arguments), and the function metadata advertises the parameter to the model, so the model is expected to send it.

The same splat shows up in a few other places. KernelArguments(a=1) | {"settings": "x"} raises TypeError: KernelArguments() got multiple values for keyword argument 'settings', and so does the reflected form. Agent._merge_arguments fails the same way when both the agent and the call have arguments and one of them has a settings key. The MCP server built by create_mcp_server_from_kernel passes the client's tool arguments to function.invoke(**arguments), so calling a tool with a settings parameter returns 'str' object has no attribute 'service_id' as a tool error, and its get_prompt handler fails for a prompt variable called settings.

Description

to_kernel_arguments now creates an empty KernelArguments and adds the parsed arguments with update(**args). Keeping the ** matters. If the model sends something that parses to a JSON string or list, for example double encoded arguments, it still raises TypeError, and invoke_function_call still answers with "The tool call arguments are malformed" so the model can retry. A plain update(args) would raise ValueError there, or quietly accept a list of pairs.

or, ror and Agent._merge_arguments create the result with the merged execution settings and then update(**...) it with the merged values, so they behave exactly as before apart from the settings key. The MCP server's call_tool path now builds a KernelArguments from the client arguments and passes it as arguments=, and get_prompt does the same. No signatures change.

I left Kernel.invoke(**kwargs) and KernelFunction.invoke(**kwargs) as they are. There settings= is written by the caller and reading it as execution settings is the intended behavior.

New tests cover a string, a dict and an already parsed mapping in to_kernel_arguments, arguments that are not a JSON object in to_kernel_arguments and invoke_function_call, | with a settings key from both sides with and without execution settings, invoke_function_call with a settings: str | dict parameter, Agent._merge_arguments with a settings key, and MCP call_tool and get_prompt with a settings argument. Without the source change 11 of the 27 tests in the touched test functions fail with the errors above. The 16 that pass are the existing | cases and the not a JSON object cases, which pin the malformed reply. With the change all 27 pass.

python -m pytest tests/unit/contents tests/unit/functions tests/unit/kernel tests/unit/connectors/mcp tests/unit/prompt_template tests/unit/agents gives 1479 passed, with 7 modules not collected because autogen, boto3 and google packages are not installed here. On the whole tests/unit folder I get 3571 passed and 24 failed, and the same 24 (onnx chat and text completion, openapi DNS pinning) fail on main in my environment. ruff check and ruff format are clean on the changed files, and mypy -p semantic_kernel --config-file mypy.ini reports nothing in them.

Contribution Checklist

FunctionCallContent.to_kernel_arguments built the arguments with
KernelArguments(**args). KernelArguments.__init__ has a settings keyword
for execution settings, so a kernel function parameter called settings
was read as execution settings. A string value raised AttributeError
('str' object has no attribute 'service_id') out of auto function
calling, and a dict value was moved into execution_settings so the
function reported a missing argument.

Add the parsed arguments with update(**args) instead, which keeps the
TypeError for arguments that are not a JSON object, so those still get
the malformed arguments reply. Do the same in KernelArguments.__or__
and __ror__ and in Agent._merge_arguments, where a settings key raised
TypeError for multiple values, and in the MCP server call_tool and
get_prompt handlers.
@v0ropaev
Dmitry Voropaev (v0ropaev) requested a review from a team as a code owner October 29, 2026 17:13
Copilot AI balanced review requested due to automatic review settings October 29, 2026 17:13

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 insufficient remaining quota.

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

This branch was successfully deployed

1 active deployment
github-app-auth — 46b2bc49 Deployed Oct 29, 2026 by v0ropaev via add_label #29488
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.

2 participants