Skip to content

Python: Bug: KernelFunctionSelectionStrategy and KernelFunctionTerminationStrategy default result_parser raises TypeError #14589

Open

Description

Describe the bug

KernelFunctionSelectionStrategy and KernelFunctionTerminationStrategy (python/semantic_kernel/agents/strategies) both declare a default for result_parser that cannot be called the way the strategy calls it. The default is a zero-argument lambda, but select_agent and should_agent_terminate call self.result_parser(result) with one argument. If you do not pass your own result_parser, the strategy always fails with a TypeError.

Selection strategy:

result_parser: Callable[..., str] = Field(default_factory=lambda: (lambda: ""))
...
agent_name = self.result_parser(result)

Termination strategy:

result_parser: Callable[..., bool] = Field(default_factory=lambda: (lambda: True))
...
result_parsed = self.result_parser(result)

To Reproduce

Run against current main (5b4a326):

import asyncio
from semantic_kernel import Kernel
from semantic_kernel.agents.strategies import KernelFunctionSelectionStrategy, KernelFunctionTerminationStrategy
from semantic_kernel.functions import kernel_function

class P:
    @kernel_function(name="pick")
    def pick(self) -> str:
        return "B"

    @kernel_function(name="stop")
    def stop(self) -> str:
        return "true"

class A:
    def __init__(self, n):
        self.name = n
        self.id = n

k = Kernel()
k.add_plugin(P(), "p")

async def main():
    sel = KernelFunctionSelectionStrategy(function=k.get_function("p", "pick"), kernel=k)
    try:
        await sel.select_agent([A("A"), A("B")], [])
    except Exception as e:
        print("SEL", type(e).__name__, e)
    term = KernelFunctionTerminationStrategy(function=k.get_function("p", "stop"), kernel=k)
    try:
        await term.should_agent_terminate(A("A"), [])
    except Exception as e:
        print("TERM", type(e).__name__, e)

asyncio.run(main())

Output:

SEL TypeError KernelFunctionSelectionStrategy.<lambda>.<locals>.<lambda>() takes 0 positional arguments but 1 was given
TERM TypeError KernelFunctionTerminationStrategy.<lambda>.<locals>.<lambda>() takes 0 positional arguments but 1 was given

Expected behavior

Constructing either strategy without a result_parser should work, or the field should be required. Today the field looks optional but is not.

Proposed fix

I would keep the field optional and give it a default that takes the function result:

  • Selection: return str(result).strip(), so a function that returns an agent name selects that agent.
  • Termination: return str(result).strip().lower() == "true", so a function that returns true ends the chat.

I picked this over making result_parser a required field because it does not break any caller that passes its own parser, and the behavior is easy to predict. For termination I did not keep "always return True" as the default, because that would stop the chat after the first check regardless of the function output, which makes the kernel function pointless.

I have a fix with tests ready and can open a PR if this direction is acceptable.

Platform

  • Language: Python
  • Source: main branch (5b4a326)
  • OS: Windows, Python 3.13

Activity

  1. Li-john1021 commented on Oct 14, 2026

    @Li-john1021

    Hi! I'd like to work on this if nobody is already on it.

    I plan a small fix so the default result_parser accepts the function result (selection: str(result).strip(); termination: treat "true" as terminate), plus regression tests for the current TypeError. Happy to adjust if maintainers prefer a different default.

    Please assign me (Li-john1021) if that sounds alright — and sorry if I stepped on anyone who was already preparing a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pythonPull requests for the Python Semantic Kerneltriage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions