{"record":{"id":"33006212f3a27ccb","repo":"microsoft/autogen","slug":"the-agent-did-not-produce-a-final-response-check-330062","errorCode":null,"errorMessage":"The agent did not produce a final response. Check the agent's on_messages_stream method.","messagePattern":"The agent did not produce a final response\\. Check the agent's on_messages_stream method\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_chat_agent_container.py","lineNumber":140,"sourceCode":"                raise\n        else:\n            # If the agent is not a team, handle it as a single agent.\n            with trace_invoke_agent_span(\n                agent_name=self._agent.name,\n                agent_description=self._agent.description,\n                agent_id=str(self.id),\n            ):\n                try:\n                    # Pass the messages in the buffer to the delegate agent.\n                    response: Response | None = None\n                    async for msg in self._agent.on_messages_stream(self._message_buffer, ctx.cancellation_token):\n                        if isinstance(msg, Response):\n                            await self._log_message(msg.chat_message)\n                            response = msg\n                        else:\n                            await self._log_message(msg)\n                    if response is None:\n                        raise RuntimeError(\n                            \"The agent did not produce a final response. Check the agent's on_messages_stream method.\"\n                        )\n                    # Publish the response to the group chat.\n                    self._message_buffer.clear()\n                    await self.publish_message(\n                        GroupChatAgentResponse(response=response, name=self._agent.name),\n                        topic_id=DefaultTopicId(type=self._parent_topic_type),\n                        cancellation_token=ctx.cancellation_token,\n                    )\n                except Exception as e:\n                    # Publish the error to the group chat.\n                    error_message = SerializableException.from_exception(e)\n                    await self.publish_message(\n                        GroupChatError(error=error_message),\n                        topic_id=DefaultTopicId(type=self._parent_topic_type),\n                        cancellation_token=ctx.cancellation_token,\n                    )\n                    # Raise the error to the runtime.","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_chat_agent_container.py#L122-L158","documentation":"Raised inside ChatAgentContainer when a participant agent's on_messages_stream completed without ever producing a final Response object. The ChatAgent streaming contract requires the stream to end with a Response carrying the chat message; an empty stream (early return, exception swallowed, or a broken custom agent) leaves the container with no result to publish to the group chat.","triggerScenarios":"A custom ChatAgent whose on_messages_stream yields only intermediate events (e.g. tool calls) and returns; an inner agent whose stream is cancelled or short-circuited before the final Response; subclass overrides that forget to yield the closing Response.","commonSituations":"Writing custom agents to use inside RoundRobinGroupChat/SelectorGroupChat; upgrading autogen versions where the on_messages_stream contract was tightened; wrapping third-party agents that end streams abruptly.","solutions":["Make your custom agent's on_messages_stream always end with yield Response(chat_message=...) on every path.","Wrap the body in try/finally and emit a fallback Response in finally if none was produced.","Use the built-in agents (AssistantAgent, etc.) or carefully follow their streaming pattern when implementing custom ones."],"exampleFix":"// before\nclass MyAgent(ChatAgent):\n    async def on_messages_stream(self, messages, cancellation_token):\n        for ev in self._steps(messages):\n            yield ev  # no final Response\n\n// after\nclass MyAgent(ChatAgent):\n    async def on_messages_stream(self, messages, cancellation_token):\n        for ev in self._steps(messages):\n            yield ev\n        yield Response(chat_message=TextMessage(content=self._final_text, source=self.name))","handlingStrategy":"validation","validationCode":"async def stream_ends_with_response(agent: ChatAgent, msgs: list[BaseChatMessage]) -> bool:\n    saw_response = False\n    async for ev in agent.on_messages_stream(msgs, CancellationToken()):\n        if isinstance(ev, Response):\n            saw_response = True\n    return saw_response\n# unit-test this for each custom agent","typeGuard":null,"tryCatchPattern":"try:\n    async for ev in team.run_stream(task):\n        ...\nexcept RuntimeError as e:\n    if \"did not produce a final response\" in str(e):\n        # fix the offending agent's on_messages_stream to end with yield Response(...)\n        ...","preventionTips":["Every custom agent's on_messages_stream must end with yield Response(chat_message=...).","Cover custom agents with a streaming-contract unit test before adding them to teams.","Mirror AssistantAgent's stream structure when implementing custom agents."],"tags":["agents","streaming","contract","custom-agent"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}