microsoft/semantic-kernel · error · AgentThreadInitializationException

CopilotClient cannot be None

Error message

CopilotClient cannot be None

What it means

Raised by CopilotStudioAgentThread.__init__ when the client argument is None. Although the type hint declares client as CopilotClient (non-optional), Python does not enforce this at runtime, so the constructor explicitly guards against None with an AgentThreadInitializationException. The thread needs a live CopilotClient to start conversations and ask questions.

Source

Thrown at python/semantic_kernel/agents/copilot_studio/copilot_studio_agent.py:213

@experimental
class CopilotStudioAgentThread(AgentThread):
    """The Copilot Studio Agent Thread."""

    def __init__(
        self,
        client: CopilotClient,
        conversation_id: str | None = None,
    ) -> None:
        """Initializes a new instance of the CopilotStudioAgentThread class.

        Args:
            client: The Copilot Client.
            conversation_id: The conversation ID. This is the Copilot Studio conversation ID.
        """
        super().__init__()
        if client is None:
            raise AgentThreadInitializationException("CopilotClient cannot be None")

        self._client = client
        self._conversation_id = conversation_id  # Copilot Studio conversation ID

    @property
    def conversation_id(self) -> str | None:
        """Get the conversation ID."""
        return self._conversation_id

    @conversation_id.setter
    def conversation_id(self, value: str | None) -> None:
        """Set the conversation ID."""
        self._conversation_id = value

    @override
    @property
    def id(self) -> str | None:
        """Get the thread ID."""

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Pass the agent's client instance: CopilotStudioAgentThread(agent.client).
  2. If constructing the thread before the agent, create the client first via CopilotStudioAgent.create_client(...) and pass it to both.
  3. Avoid manual thread construction — let CopilotStudioAgent.invoke/get_response create the thread internally by omitting the thread argument.

Example fix

# before
thread = CopilotStudioAgentThread(client=None)

# after
thread = CopilotStudioAgentThread(client=agent.client)
Defensive patterns

Strategy: validation

Validate before calling

if client is None:
    raise ValueError("client must not be None; create one via CopilotStudioAgent.create_client()")
thread = CopilotStudioAgentThread(client=client)

Type guard

from microsoft_agents.copilotstudio.client import CopilotClient

def is_valid_client(c) -> bool:
    return isinstance(c, CopilotClient)

Prevention

When it happens

Trigger: Manually constructing CopilotStudioAgentThread(client=None) or passing a variable that evaluated to None. Also possible if create_client() returned None unexpectedly (it never does in normal flow, but a monkeypatched or mocked path could).

Common situations: Calling code builds the thread separately from the agent and forgets to pass the agent's client; using a factory or lambda that yields None under an edge condition; test mocks that return None for the client.

Related errors


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