langchain-ai/deepagents · error · TypeError

Expected PreCompactDecision, got {type(decision).__name__}

Error message

Expected PreCompactDecision, got {type(decision).__name__}

What it means

ClientHookService.pre_compact validates that the hook handler returned a PreCompactDecision instance before the context-compaction flow continues. Any other return type (dict, None, wrong decision class) raises TypeError. This enforces the typed contract for the pre-compact hook so custom compaction instructions are well-formed.

Source

Thrown at libs/code/deepagents_code/hooks/client_lifecycle.py:254

        Returns:
            Aggregated pre-compaction decision.

        Raises:
            TypeError: If the runtime returns a mismatched decision type.
        """
        if not self.has_handlers(HookEvent.PRE_COMPACT):
            return PreCompactDecision(event=HookEvent.PRE_COMPACT)
        decision = await self._invoke(
            context,
            PreCompactEvent(
                event=HookEvent.PRE_COMPACT,
                trigger=trigger,
                custom_instructions=custom_instructions,
            ),
        )
        if not isinstance(decision, PreCompactDecision):
            msg = f"Expected PreCompactDecision, got {type(decision).__name__}"
            raise TypeError(msg)
        return decision

    async def permission_request(
        self,
        context: ClientHookContext,
        call: ToolCallData,
    ) -> PermissionRequestDecision:
        """Invoke `PermissionRequest` before client approval resolution.

        Args:
            context: Current client session context.
            call: Tool action awaiting approval.

        Returns:
            Aggregated permission decision.

        Raises:
            TypeError: If the runtime returns a mismatched decision type.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Return PreCompactDecision (constructed via its allow/custom_instructions helpers or model_validate) from the PRE_COMPACT hook
  2. Convert raw return values with the pydantic adapter before returning them from the hook
  3. Verify the registered callback is specific to the pre-compact event, not shared with other events
  4. Check imports: use the decision class exported for pre_compact, not UserPromptSubmitDecision/NotificationDecision

Example fix

// before
def on_pre_compact(context, event):
    return {"custom_instructions": "summarize tools"}

// after
from deepagents_code.hooks import PreCompactDecision

def on_pre_compact(context, event):
    return PreCompactDecision(custom_instructions="summarize tools")
Defensive patterns

Strategy: type-guard

Validate before calling

from deepagents_code.hooks import PreCompactDecision

result = my_pre_compact_hook(context, event)
if not isinstance(result, PreCompactDecision):
    result = PreCompactDecision.model_validate(result)

Type guard

def is_pre_compact_decision(value: object) -> bool:
    return isinstance(value, PreCompactDecision)

Try / catch

try:
    decision = await service.pre_compact(context, trigger, custom_instructions)
except TypeError as exc:
    logger.warning("pre_compact hook returned invalid decision: %s", exc)
    decision = PreCompactDecision.allow()

Prevention

When it happens

Trigger: Calling pre_compact() (or on_pre_compact) when a registered PRE_COMPACT hook returns a plain dict like {'custom_instructions': '...'}, None, or a decision object belonging to another hook event instead of PreCompactDecision.

Common situations: Hooks written against an older untyped API; copying a callback from another hook event; constructing the decision with the wrong class name imported from a sibling module; JSON round-trips that lose the concrete type.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/fbb074648cf34804. Report an issue: GitHub.