Repository navigation
Python: Treat a tool call argument named settings as a function argument - #14680
Open
Dmitry Voropaev (v0ropaev) wants to merge 1 commit into
Open
Dmitry Voropaev (v0ropaev) wants to merge 1 commit into
Dmitry Voropaev (v0ropaev) wants to merge 1 commit into
Conversation
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.
Dmitry Voropaev (v0ropaev)
deployed
to
github-app-auth
October 29, 2026 17:13 — with
GitHub Actions
Active
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
KernelArguments.init takes a
settingskeyword for prompt execution settings. FunctionCallContent.to_kernel_arguments builds the arguments withKernelArguments(**args), so when a kernel function has a parameter calledsettings, the value the model sends for it goes into that keyword and not into the dict.With a string value the constructor calls
.service_idon it and raisesAttributeError: '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']".settingsis 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"}raisesTypeError: 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 asettingskey. The MCP server built by create_mcp_server_from_kernel passes the client's tool arguments tofunction.invoke(**arguments), so calling a tool with asettingsparameter returns'str' object has no attribute 'service_id'as a tool error, and its get_prompt handler fails for a prompt variable calledsettings.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 plainupdate(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 thesettingskey. The MCP server's call_tool path now builds a KernelArguments from the client arguments and passes it asarguments=, 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 asettingskey from both sides with and without execution settings, invoke_function_call with asettings: str | dictparameter, Agent._merge_arguments with asettingskey, and MCP call_tool and get_prompt with asettingsargument. 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/agentsgives 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, andmypy -p semantic_kernel --config-file mypy.inireports nothing in them.Contribution Checklist