{"record":{"id":"6f6ed24014eabc89","repo":"microsoft/autogen","slug":"return-not-found-in-function-signature","errorCode":null,"errorMessage":"return not found in function signature","messagePattern":"return not found in function signature","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-core/src/autogen_core/_closure_agent.py","lineNumber":38,"sourceCode":"from .exceptions import CantHandleException\n\nT = TypeVar(\"T\")\nClosureAgentType = TypeVar(\"ClosureAgentType\", bound=\"ClosureAgent\")\n\n\ndef get_handled_types_from_closure(\n    closure: Callable[[ClosureAgent, T, MessageContext], Awaitable[Any]],\n) -> Sequence[type]:\n    args = inspect.getfullargspec(closure)[0]\n    if len(args) != 3:\n        raise AssertionError(\"Closure must have 4 arguments\")\n\n    message_arg_name = args[1]\n\n    type_hints = get_type_hints(closure)\n\n    if \"return\" not in type_hints:\n        raise AssertionError(\"return not found in function signature\")\n\n    # Get the type of the message parameter\n    target_types = get_types(type_hints[message_arg_name])\n    if target_types is None:\n        raise AssertionError(\"Message type not found\")\n\n    # print(type_hints)\n    return_types = get_types(type_hints[\"return\"])\n\n    if return_types is None:\n        raise AssertionError(\"Return type not found\")\n\n    return target_types\n\n\nclass ClosureContext(Protocol):\n    @property\n    def id(self) -> AgentId: ...","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-core/src/autogen_core/_closure_agent.py#L20-L56","documentation":"get_handled_types_from_closure() calls typing.get_type_hints(closure) and requires a 'return' entry to determine the closure's response type. A closure declared without a return annotation produces no 'return' key and AssertionError is raised. Note get_type_hints evaluates annotations, so string/forward-reference annotations that fail to resolve can also strip entries.","triggerScenarios":"async def handler(agent, message, ctx): ... with no '-> SomeType' annotation; annotations given as unresolvable forward references (e.g. strings referencing names not imported at call time).","commonSituations":"Quick prototype closures written without annotations; using TYPE_CHECKING-only imports referenced in annotations; tools that strip annotations.","solutions":["Annotate the return type explicitly: async def handler(agent, message, ctx) -> None (or the actual response type).","Make sure any names used in annotations are importable in the closure's module scope (not under TYPE_CHECKING only).","from __future__ import annotations is fine, but the referenced names must still resolve."],"exampleFix":"# before\nasync def handler(agent, message, ctx):  # no return annotation\n    agent.publish_message(...)\n\n# after\nasync def handler(agent: ClosureContext, message: str, ctx: MessageContext) -> None:\n    await agent.publish_message(..., ctx=ctx)","handlingStrategy":"validation","validationCode":"from typing import get_type_hints\n\nhints = get_type_hints(my_closure)\nassert \"return\" in hints, \"closure needs a return annotation (e.g. -> None)\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fully annotate closures including the return type (-> None counts).","Keep annotation-referenced types importable at runtime (not TYPE_CHECKING-only).","Add a smoke test that constructs each ClosureAgent once to surface annotation errors early."],"tags":["autogen-core","closure-agent","type-hints","annotations"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}