microsoft/semantic-kernel · error · PermissionError

Received a request from a bot with an app ID of "{app_id}".

Error message

Received a request from a bot with an app ID of "{app_id}". To enable requests from this caller, add the app ID to your configuration file.

What it means

A PermissionError raised by the claims validator when an incoming skill request carries an app ID (from JWT claims) that is not in the configured ALLOWED_CALLERS set, and wildcard '*' is not configured. This is the core authorization gate: only explicitly allow-listed parent bots may invoke the skill.

Source

Thrown at python/samples/demos/copilot_studio_skill/src/api/auth.py:34

        # ALLOWED_CALLERS is the setting in config.py file
        # that consists of the list of parent bot ids that are allowed to access the skill
        # to add a new parent bot simply go to the AllowedCallers and add
        # the parent bot's microsoft app id to the list
        caller_list = getattr(config, self.config_key)
        if caller_list is None:
            raise TypeError(f'"{self.config_key}" not found in configuration.')
        self._allowed_callers = frozenset(caller_list)

    @property
    def claims_validator(self) -> Callable[[list[dict]], Awaitable]:
        async def allow_callers_claims_validator(claims: dict[str, object]):
            # if allowed_callers is None we allow all calls
            if "*" not in self._allowed_callers and SkillValidation.is_skill_claim(claims):
                # Check that the appId claim in the skill request is in the list of skills configured for this bot.
                app_id = JwtTokenValidation.get_app_id_from_claims(claims)
                if app_id not in self._allowed_callers:
                    raise PermissionError(
                        f'Received a request from a bot with an app ID of "{app_id}".'
                        f" To enable requests from this caller, add the app ID to your configuration file."
                    )

            return

        return allow_callers_claims_validator

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Add the offending app ID (shown in the message) to the ALLOWED_CALLERS env var / Config.
  2. Temporarily set ALLOWED_CALLERS to '*' only in trusted/dev environments to allow all (not for production).
  3. Verify the parent bot's app registration ID matches what was added.

Example fix

// before
ALLOWED_CALLERS=11111111-2222-3333-4444-555555555555
# requesting bot is 99999999-aaaa-bbbb-cccc-dddddddddddd

// after
ALLOWED_CALLERS=11111111-2222-3333-4444-555555555555,99999999-aaaa-bbbb-cccc-dddddddddddd
Defensive patterns

Strategy: try-catch

Try / catch

try:
    await claims_validator(claims)
except PermissionError as e:
    app_id = JwtTokenValidation.get_app_id_from_claims(claims)
    logger.warning("Unauthorized caller app_id=%s; add to ALLOWED_CALLERS if intended.", app_id)
    raise

Prevention

When it happens

Trigger: A parent bot sends a skill request; SkillValidation.is_skill_claim(claims) is true; the claim's appId is not in self._allowed_callers; ALLOWED_CALLERS is not ['*'].

Common situations: A new parent bot was deployed without adding its app ID to ALLOWED_CALLERS; wrong tenant/app registration used; misconfigured allowed callers; a legitimate partner bot not yet allow-listed.

Related errors


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