langchain-ai/deepagents · error · TypeError
Expected PermissionRequestDecision, got {type(decision).__na
Error message
Expected PermissionRequestDecision, got {type(decision).__name__} What it means
ClientHookService.permission_request validates that the hook handler returned a PermissionRequestDecision before the permission flow resolves a tool call. If the handler returns any other object (dict, None, wrong class), the service raises TypeError. This keeps the permission pipeline typed: downstream code expects fields like allow/deny on the decision.
Source
Thrown at libs/code/deepagents_code/hooks/client_lifecycle.py:285
Returns:
Aggregated permission decision.
Raises:
TypeError: If the runtime returns a mismatched decision type.
"""
if not self.has_handlers(HookEvent.PERMISSION_REQUEST):
return PermissionRequestDecision(
event=HookEvent.PERMISSION_REQUEST,
permission=PermissionEffect(behavior="none"),
)
decision = await self._invoke(
context,
PermissionRequestEvent(event=HookEvent.PERMISSION_REQUEST, call=call),
)
if not isinstance(decision, PermissionRequestDecision):
msg = f"Expected PermissionRequestDecision, got {type(decision).__name__}"
raise TypeError(msg)
return decision
async def resolve_permission(
self,
context: ClientHookContext,
call: ToolCallData,
) -> PermissionHookOutcome:
"""Resolve a permission hook and present user-facing attribution once.
The returned HITL decision carries the raw hook reason (or stop reason)
for model-visible resume payloads. Attribution text is emitted only
through the shared presenter.
Args:
context: Current client session context.
call: Tool action awaiting approval.
Returns:View on GitHub (pinned to a1af029e6e)
Solutions
- Return PermissionRequestDecision.allow()/deny() (or model_validate the raw dict) from the PERMISSION_REQUEST hook
- Re-validate any deserialized decisions with PermissionRequestDecision before returning
- Ensure the callback is registered for permission_request and not reused from another hook event
- If a custom wrapper strips types, change it to pass through the original decision object
Example fix
// before
def check_perm(context, event):
return {"allow": True}
// after
from deepagents_code.hooks import PermissionRequestDecision
def check_perm(context, event):
return PermissionRequestDecision.allow() Defensive patterns
Strategy: type-guard
Validate before calling
from deepagents_code.hooks import PermissionRequestDecision
result = my_permission_hook(context, event)
if not isinstance(result, PermissionRequestDecision):
result = PermissionRequestDecision.model_validate(result)
Type guard
def is_permission_decision(value: object) -> bool:
return isinstance(value, PermissionRequestDecision)
Try / catch
try:
decision = await service.permission_request(context, call)
except TypeError as exc:
logger.warning("permission hook returned invalid decision: %s", exc)
decision = PermissionRequestDecision.deny(reason="invalid hook response")
Prevention
- Return PermissionRequestDecision.allow()/deny() helpers rather than hand-building dicts
- Annotate permission hook callbacks with the concrete return type
- Fail closed: validate hook output before trusting allow/deny fields
When it happens
Trigger: Calling permission_request() (or resolve_permission) when a registered PERMISSION_REQUEST hook returns {'allow': True}, None, or a decision class from another event instead of PermissionRequestDecision.
Common situations: Generic permission callbacks shared across tools returning ad-hoc dicts; older hook code written before the typed decision API; building the decision from persisted JSON without re-validating to the concrete class.
Related errors
- Expected UserPromptSubmitDecision, got {type(decision).__nam
- Expected PreCompactDecision, got {type(decision).__name__}
- Permission interrupted by hook
- Unsupported hook event: {type(event).__name__}
- Unsupported hook-specific output: {type(specific).__name__}
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/ef3cb8395d8d21cb.
Report an issue: GitHub.