Python: Update runtime handling#14135
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR tightens Python runtime behavior around function resolution and remote invocation so defaults are safer (fail-closed) while still preserving existing functionality via explicit opt-ins and clearer diagnostics.
Changes:
Kernel.get_function(None, name)now detects ambiguity across plugins, logs a warning, and deterministically resolves to the first-registered match.- MCP sampling now denies by default when no consent callback is configured, with an explicit
sampling_auto_approve=Trueopt-in. - OpenAI Realtime function-call handling now fails closed when function-choice behavior isn’t configured, preventing unallowlisted invocation while still returning a safe result event.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| python/semantic_kernel/functions/kernel_function_extension.py | Adds ambiguity detection + warning when resolving bare function names across plugins. |
| python/tests/unit/kernel/test_kernel.py | Adds coverage for bare-name function lookup (single match and ambiguous warning). |
| python/semantic_kernel/connectors/mcp.py | Introduces sampling_auto_approve and changes default sampling behavior to deny without explicit consent/opt-in. |
| python/tests/unit/connectors/mcp/test_mcp.py | Updates tests to reflect deny-by-default and adds test for opt-in auto-approve warning. |
| python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py | Prevents function invocation when no function-choice behavior exists (allowlist can’t be enforced) and simplifies receive loop. |
| python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py | Adds coverage verifying the realtime path does not invoke functions when settings are missing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Flagged issue
Source: automated DevFlow PR review |
There was a problem hiding this comment.
Automated Code Review
Reviewers: 5 | Confidence: 91%
✓ Correctness
This PR implements three security-hardening changes: (1) fail-closed for realtime function calls without function choice behavior, (2) deny-by-default for MCP sampling requests without a consent callback, and (3) ambiguity warnings when resolving bare function names across multiple plugins. All changes are logically correct, properly tested, and backward-compatible (with the intended breaking change for MCP users who relied on implicit auto-approve being mitigated by the new sampling_auto_approve flag).
✓ Security Reliability
This PR makes three well-designed security improvements: fail-closed function invocation in OpenAI Realtime when no allowlist (function_choice_behavior) is configured, default-deny for MCP sampling requests without a consent callback, and an ambiguity warning for bare function-name lookups. The implementations are correct, properly tested, and do not introduce new security or reliability concerns.
✓ Test Coverage
Test coverage for this PR is generally strong. All three production code changes (realtime fail-closed, MCP deny-by-default, kernel ambiguous lookup) have corresponding tests with meaningful assertions. One gap exists: the realtime fail-closed guard is only tested when
_current_settingsis None, but not when_current_settingsexists with a Nonefunction_choice_behavior— a distinct code path that reaches the same security check.
✓ Failure Modes
This PR hardens three failure paths: (1) the OpenAI realtime handler now fails closed when no function_choice_behavior is configured, preventing unauthenticated function execution; (2) MCP sampling requests are denied by default unless explicitly opted in via sampling_auto_approve; (3) ambiguous bare-name function lookups log a warning. All three changes are well-tested and correctly implemented with no new failure modes introduced.
✗ Design Approach
The MCP default-deny change is directionally reasonable, but in its current form it breaks an existing in-repo sampling workflow: the
agent_with_mcp_sampling.pysample still constructsMCPStdioPluginwithout either a consent callback or the new opt-in flag, so the sampling request path it demonstrates is now rejected by default.
Flagged Issues
-
python/semantic_kernel/connectors/mcp.py:395-405now denies sampling when no callback is configured, but the existing sampling sample atpython/samples/concepts/mcp/agent_with_mcp_sampling.py:46-55createsMCPStdioPlugin(...)withoutsampling_consent_callbackorsampling_auto_approve. That sample code path will now returnErrorData(message="Sampling denied: no consent callback configured.")instead of exercising MCP sampling.
Suggestions
- Update the affected sampling sample(s) such as
python/samples/concepts/mcp/agent_with_mcp_sampling.py:46-55to pass an explicit consent policy (sampling_auto_approve=Trueor a callback), or otherwise preserve compatibility for that documented code path before flipping the library default atpython/semantic_kernel/connectors/mcp.py:395-405.
Automated review by SergeyMenshykh's agents
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This PR updates Python runtime handling and related tests.