microsoft/semantic-kernel · error · AgentInvokeException

Invalid response from DirectLine Bot.\n{response_data}

Error message

Invalid response from DirectLine Bot.\n{response_data}

What it means

An AgentInvokeException raised at the start of invoke() when _send_message returns None or a dict lacking the 'activities' key. The agent requires a well-formed activities payload to extract bot replies; without it the conversation cannot continue. The raw response_data is interpolated into the message for diagnosis.

Source

Thrown at python/samples/demos/copilot_studio_agent/src/direct_line_agent.py:122

    @override
    async def invoke(
        self,
        history: ChatHistory,
        arguments: dict[str, Any] | None = None,
        **kwargs: Any,
    ) -> AsyncIterable[ChatMessageContent]:
        """
        Send the latest message from the chat history to the DirectLine Bot
        and yield responses. This sends the payload after ensuring that:
          1. The token is fetched.
          2. A conversation is started.
          3. The activity payload is posted.
          4. Activities are polled until an event "DynamicPlanFinished" is received.
        """
        payload = self._build_payload(history, arguments, **kwargs)
        response_data = await self._send_message(payload)
        if response_data is None or "activities" not in response_data:
            raise AgentInvokeException(f"Invalid response from DirectLine Bot.\n{response_data}")

        logger.debug("DirectLine Bot response: %s", response_data)

        # NOTE DirectLine Activities have different formats
        # than ChatMessageContent. We need to convert them and
        # remove unsupported activities.
        for activity in response_data["activities"]:
            if activity.get("type") != "message" or activity.get("from", {}).get("role") == "user":
                continue
            role = activity.get("from", {}).get("role", "assistant")
            if role == "bot":
                role = "assistant"
            message = ChatMessageContent(
                role=role,
                content=activity.get("text", ""),
                name=activity.get("from", {}).get("name", self.name),
            )
            yield message

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Examine the interpolated response_data in the message to see the actual body.
  2. Verify the payload built by _build_payload is correct and the conversation/activity post succeeded.
  3. Check that the activities polling URL and watermark logic match the DirectLine version.

Example fix

// before
response_data = await self._send_message(payload)
if response_data is None or "activities" not in response_data:
    raise AgentInvokeException(f"Invalid response from DirectLine Bot.\n{response_data}")

// after  # distinguish null vs malformed
response_data = await self._send_message(payload)
if response_data is None:
    raise AgentInvokeException("No data returned from DirectLine Bot.")
if "activities" not in response_data:
    logger.error("Unexpected DirectLine body: %s", response_data)
    raise AgentInvokeException(f"Invalid response from DirectLine Bot.\n{response_data}")
Defensive patterns

Strategy: validation

Validate before calling

payload = agent._build_payload(history, arguments, **kwargs)
# ensure payload is well-formed before sending
assert payload and isinstance(payload, dict), "Invalid payload for DirectLine"

Type guard

def has_activities(data) -> bool:
    return isinstance(data, dict) and isinstance(data.get('activities'), list)

Try / catch

try:
    async for msg in agent.invoke(history, arguments, **kwargs):
        yield msg
except AgentInvokeException as e:
    if "Invalid response" in str(e):
        logger.error("DirectLine returned malformed body: %s", e)
    raise

Prevention

When it happens

Trigger: _send_message(payload) returns None (request failed/null) or a JSON object without 'activities' (e.g. an error envelope like {'error': {...}}).

Common situations: The post-activity or poll step returned an error body that wasn't detected as a status failure; the endpoint schema changed; watermark polling returned a terminal non-activities object.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/197b1f7d570a5697. Report an issue: GitHub.