microsoft/semantic-kernel · error · AgentInitializationException

If no client_secret is provided, a client_certificate is req

Error message

If no client_secret is provided, a client_certificate is required for service-to-service auth.

What it means

Raised by _CopilotStudioAgentTokenFactory._acquire_service_token (an AgentInitializationException) in the certificate branch when client_cert_path is falsy. This is a defensive re-check: the branch is only entered when client_secret is absent, and the code requires a certificate path to build the client_credential dict (private_key + thumbprint).

Source

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

        return ConfidentialClientApplication(
            client_id=self.settings.app_client_id,
            authority=f"https://login.microsoftonline.com/{self.settings.tenant_id}",
            token_cache=self.cache,
            **extra_kwargs,
        )

    def _acquire_service_token(self) -> str:
        if not self.client_secret and not self.client_cert_path:
            raise AgentInitializationException(
                "client_secret *or* client_certificate is required for service-to-service auth."
            )

        kwargs: dict[str, Any] = {}
        if self.client_secret:
            kwargs["client_credential"] = self.client_secret
        else:  # certificate
            if not self.client_cert_path:
                raise AgentInitializationException(
                    "If no client_secret is provided, a client_certificate is required for service-to-service auth."
                )
            kwargs["client_credential"] = {
                "private_key": Path(self.client_cert_path).read_text(),
                "thumbprint": self._cert_thumbprint(self.client_cert_path),
            }

        app = self._new_confidential_client(**kwargs)

        # proactive caching
        result = app.acquire_token_silent(self.scopes, account=None) or app.acquire_token_for_client(scopes=self.scopes)

        return self._unwrap(result)

    # interactive
    def _acquire_interactive_token(self) -> str:
        app = PublicClientApplication(
            self.settings.app_client_id,

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Provide a client_certificate Path when not using a client_secret.
  2. Load the certificate path from your secret/config store and confirm it is non-empty before building the factory.
  3. Since SERVICE mode is currently gated (error 797), prefer INTERACTIVE until supported; if SERVICE is needed later, supply exactly one of secret or cert.
  4. Ensure the cert file path is valid and readable so downstream private_key/thumbprint extraction works.

Example fix

// before
factory = _CopilotStudioAgentTokenFactory(settings=..., mode=SERVICE, cache_path=...)  # no creds
// after
from pathlib import Path
factory = _CopilotStudioAgentTokenFactory(
    settings=..., mode=SERVICE, cache_path=..., client_certificate=Path('/etc/cs/cert.pem'))
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
def validate_cert(client_cert_path):
    if not client_cert_path:
        raise ValueError('client_certificate path required when no client_secret is provided')
    p = Path(client_cert_path)
    if not p.is_file():
        raise FileNotFoundError(f'Certificate not found: {client_cert_path}')
    return p

Try / catch

from semantic_kernel.exceptions.agent_exceptions import AgentInitializationException
try:
    token = factory._acquire_service_token()
except AgentInitializationException as e:
    if 'client_certificate is required' in str(e):
        raise RuntimeError('Provide a client_certificate Path for service auth')
    raise

Prevention

When it happens

Trigger: SERVICE auth configured with neither a client_secret nor a client_certificate path; client_cert_path is None/empty inside the certificate branch. Effectively the same misconfiguration as 798, caught by the secondary guard.

Common situations: Omitting both credentials; certificate path not loaded from config; logic that sets client_secret conditionally leaving it None while also not setting client_certificate.

Understand the failure class

Related errors


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