agentscope-ai/agentscope · error · RuntimeError

Agent did not produce a final message.

Error message

Agent did not produce a final message.

What it means

Agent.reply() consumes the reasoning/acting event stream and records the last Msg produced. If the whole loop finishes without the agent ever emitting a final Msg (final_msg stays None), reply raises this RuntimeError. It signals the agent's loop terminated abnormally — usually max_iters exhausted during reasoning or an empty model response — rather than a normal API misuse.

Source

Thrown at src/agentscope/agent/_agent.py:346

                  continue from the current state).
            structured_schema (`Type[BaseModel] | None`, optional):
                The Pydantic model class that the reply's structured output
                must conform to, with the validated result carried on the
                final message's ``structured_output`` attribute as a dict.

        Returns:
            `Msg`:
                A final reply message.
        """
        final_msg: Msg | None = None
        async for evt_or_msg in self._reply(
            inputs=inputs,
            structured_schema=structured_schema,
        ):
            if isinstance(evt_or_msg, Msg):
                final_msg = evt_or_msg
        if final_msg is None:
            raise RuntimeError("Agent did not produce a final message.")
        return final_msg

    async def observe(self, msgs: Msg | list[Msg] | None = None) -> None:
        """Receive external observation message(s) and save them into
        context."""
        await self._handle_incoming_messages(msgs)

    async def compress_context(
        self,
        context_config: ContextConfig | None = None,
        instructions: HintBlock | None = None,
    ) -> None:
        """Compress the agent's context if the token count exceeds the
        threshold.

        Args:
            context_config (`ContextConfig | None`, optional):
                If provided, compress the context with the given context

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Increase max_iters so the agent can finish reasoning and produce a final message
  2. Inspect the conversation context before the failure to see whether the model is emitting only thinking content, and if so adjust the model/prompt to require a final answer
  3. Wrap reply() in try/except RuntimeError and retry with a nudge message (e.g. 'Please provide your final answer')
  4. If using a custom subagent, ensure it actually yields a Msg from its reasoning step

Example fix

# before
msg = await agent.reply(inputs)

# after
try:
    msg = await agent.reply(inputs)
except RuntimeError:
    await agent.observe(Msg("user", "Please give your final answer now.", role="user"))
    msg = await agent.reply()

# or preemptively: agent = ReActAgent(..., max_iters=20)
Defensive patterns

Strategy: try-catch

Validate before calling

if agent._iters >= agent.max_iters and not agent.state.final_message:
    # about to exhaust the budget; raise max_iters proactively
    agent.max_iters += 10

Type guard

null

Try / catch

try:
    final = await agent.reply(inputs)
except RuntimeError as e:
    if "did not produce a final message" in str(e):
        await agent.observe(
            Msg("user", "Please provide your final answer now.", role="user")
        )
        final = await agent.reply()
    else:
        raise

Prevention

When it happens

Trigger: Calling await agent.reply(...) (directly or via ask) when the agent hits its iteration limit while still in reasoning mode, or the model returns empty/no-message responses repeatedly (seen in tests like test_max_iters_counts_reasoning_acting_round_once and test_thinking_only_response_continues_reasoning).

Common situations: max_iters set too low for chains that need many reasoning rounds; a thinking-only model response loop that never produces a final answer; malformed model outputs causing rounds to be skipped; token limits truncating responses before content is produced.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/8cbc4fabee600b50. Report an issue: GitHub.