langchain-ai/deepagents · error · RuntimeError

Received hook invocation interrupt without a HooksRuntime

Error message

Received hook invocation interrupt without a HooksRuntime

What it means

HookManager.fulfill_interrupt resolves a Hooks v2 invocation interrupt by delegating to a HooksRuntime via fulfill_hook_interrupt. If the manager was constructed without a runtime (self._runtime is None), there is no engine able to execute the hook callback, so it raises RuntimeError rather than silently failing.

Solutions

  1. Ensure the HooksRuntime is attached to the manager (build/set the runtime via _build_service's configuration path) before resuming
  2. Complete runtime initialization before calling execute/fulfill paths — hooks require the client hook service to be configured
  3. If hooks are intentionally unused, clear the pending hook interrupts instead of fulfilling them
  4. Check process startup/config so the hook runtime is constructed in the same process that fulfills interrupts

Example fix

// before
manager = HookManager(...)  # no runtime attached
await manager.fulfill_interrupt(payload)

// after
manager = HookManager(...)
manager.set_runtime(HooksRuntime(config=hook_config))  # attach runtime first
await manager.fulfill_interrupt(payload)
Defensive patterns

Strategy: fallback

Validate before calling

if manager._runtime is None:  # prefer a public accessor if available
    raise RuntimeError("hooks runtime not initialized; cannot fulfill hook interrupt")

Type guard

def can_fulfill_hooks(manager) -> bool:
    return manager._runtime is not None

Try / catch

try:
    resume = await manager.fulfill_interrupt(payload)
except RuntimeError as exc:
    if "without a HooksRuntime" in str(exc):
        manager.set_runtime(build_hooks_runtime(hook_config))
        resume = await manager.fulfill_interrupt(payload)
    else:
        raise

Prevention

When it happens

Trigger: Calling fulfill_interrupt (e.g. from execute_task_textual) on a HookManager whose HooksRuntime was never attached — such as a manager created before runtime initialization, or one running in a mode where hooks are disabled.

Common situations: Resuming an agent graph that contains pending hook interrupts while the client-side runtime isn't wired (misconfiguration, runtime not started, or a long-lived manager whose runtime was closed); replaying persisted thread state with hook interrupts in a fresh process where hooks weren't configured.

Related errors


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

Appendix: source

Thrown at libs/code/deepagents_code/hooks/manager.py:537

    async def fulfill_interrupt(self, payload: object) -> dict[str, object]:
        """Execute one server-owned hook interrupt on the client runtime.

        Args:
            payload: Raw LangGraph interrupt value.

        Returns:
            Resume value for `Command(resume=...)`.

        Raises:
            RuntimeError: If hooks are unavailable, or the payload is not a
                parseable hook invocation.
        """
        from deepagents_code.hooks.client import fulfill_hook_interrupt

        runtime = self._runtime
        if runtime is None:
            msg = "Received hook invocation interrupt without a HooksRuntime"
            raise RuntimeError(msg)
        resume = await fulfill_hook_interrupt(runtime, payload)
        if resume is None:
            msg = "Failed to parse hook interrupt"
            raise RuntimeError(msg)
        return resume

    async def fulfill_pending_interrupts(
        self,
        pending: Mapping[str, object],
    ) -> dict[str, dict[str, object]]:
        """Execute a batch of server-owned hook interrupts.

        Args:
            pending: LangGraph interrupt id to raw interrupt payload.

        Returns:
            Resume values keyed by interrupt id.

View on GitHub (pinned to a1af029e6e)