langchain-ai/deepagents · error · RuntimeError
hooks_snapshot_id is required to emit server-owned hook even
Error message
hooks_snapshot_id is required to emit server-owned hook events
What it means
Server-owned hook events (progress, audit) are keyed by a hooks_snapshot_id carried in the session gate/context. Without it the middleware cannot attribute emitted events to a validated hook snapshot, so _invoke_hook raises RuntimeError rather than emitting events with unknown provenance. This indicates the middleware was driven outside a properly snapshot-initialized session.
Source
Thrown at libs/code/deepagents_code/hooks/server_middleware.py:912
context: HookContext,
event: (
PreToolUseEvent
| PostToolUseEvent
| PostToolUseFailureEvent
| PreCompactEvent
| StopEvent
| SubagentStartEvent
| SubagentStopEvent
),
*,
gate: _SessionHookGate | None,
config: Mapping[str, Any] | None,
deadline: timedelta,
logical_event_id: str | None = None,
) -> HookDecision:
if gate is None:
msg = "hooks_snapshot_id is required to emit server-owned hook events"
raise RuntimeError(msg)
run_id = _run_id(config, context.thread_id)
invocation_id = _invocation_id(
snapshot_id=gate["snapshot_id"],
context=context,
event=event,
logical_event_id=logical_event_id,
)
request = HookInvocationRequest(
protocol_version=1,
invocation_id=invocation_id,
snapshot_id=gate["snapshot_id"],
run_id=run_id,
invocation=HookInvocation(context=context, event=event),
deadline=datetime.now(UTC) + deadline,
)
operation_responses = _HOOK_RESPONSES.get()
if operation_responses is None:
raw = interrupt(build_hook_interrupt_payload(request))View on GitHub (pinned to a1af029e6e)
Solutions
- Ensure the agent is created/run through the standard entry point that builds a hook snapshot and injects hooks_snapshot_id into the runtime context (e.g. the server session bootstrap).
- If constructing config manually, include the hooks_snapshot_id produced by HooksSnapshot.from_config/create in the context fields.
- Update client/server together so both sides agree on snapshot propagation.
- Catch RuntimeError during development and assert gate presence to fail fast on misconfiguration.
Example fix
// before
config = {"configurable": {"thread_id": tid}}
agent.invoke(state, config) # RuntimeError: no hooks_snapshot_id
// after
snapshot = HooksSnapshot.create(config_with_hooks)
config = {"configurable": {"thread_id": tid, "hooks_snapshot_id": snapshot.snapshot_id}}
agent.invoke(state, config) Defensive patterns
Strategy: validation
Validate before calling
gate = _session_gate(runtime_context)
if gate is None or not gate.get("snapshot_id"):
raise RuntimeError("run agent through a snapshot-initialized session") Type guard
def has_hooks_snapshot(context: Mapping[str, Any]) -> TypeGuard[Mapping[str, Any]]:
return isinstance(context.get("hooks_snapshot_id"), str) and bool(context["hooks_snapshot_id"]) Try / catch
try:
agent.invoke(state, config)
except RuntimeError as exc:
if "hooks_snapshot_id" in str(exc):
reinitialize_session_with_snapshot() Prevention
- Create agents via the standard bootstrap that builds a HooksSnapshot
- Never hand-build runtime context without hooks_snapshot_id when hooks are enabled
- Keep client and server versions in sync
- Assert snapshot presence in integration tests
When it happens
Trigger: Calling _invoke_hook (via any of _maybe_subagent_start, _after_model, _maybe_post_tool_use, _maybe_subagent_stop, _after_agent, _pre_auto_compact) when the resolved session gate is None — i.e. the runtime context/config carries no hooks_snapshot_id field.
Common situations: Invoking the agent graph directly with a hand-built config that omits hooks snapshot metadata; running a stale client against a newer server that requires snapshot ids; constructing the middleware without going through the snapshot-creation entry point.
Related errors
- Agent initialization failed
- shell.allow_list is missing from the configuration manifest
- Server process is not running
- A workspace is required to start the remote agent.
- Permission interrupted by hook
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/6b91a4181896fe25.
Report an issue: GitHub.