langchain-ai/deepagents · error · ValueError
Tool call ID is required for subagent invocation
Error message
Tool call ID is required for subagent invocation
What it means
The synchronous `task` tool must attribute its result to the invoking tool call. `runtime.tool_call_id` is required to construct the returning `Command`; if it is empty/None the method raises `ValueError` since the result could not be routed back to the model.
Source
Thrown at libs/deepagents/deepagents/middleware/subagents.py:554
"""Prepare state for invocation."""
subagent = _select_subagent(subagent_type, runtime)
# Create a new state dict to avoid mutating the original
subagent_state = {k: v for k, v in runtime.state.items() if k not in _EXCLUDED_STATE_KEYS}
subagent_state = {k: v for k, v in subagent_state.items() if k not in private_state_keys}
subagent_state["messages"] = [HumanMessage(content=description)]
return subagent, subagent_state
def task(
description: str,
subagent_type: str,
runtime: ToolRuntime,
) -> str | Command:
if subagent_type not in subagent_graphs:
allowed_types = ", ".join([f"`{k}`" for k in subagent_graphs])
return f"We cannot invoke subagent {subagent_type} because it does not exist, the only allowed types are {allowed_types}"
if not runtime.tool_call_id:
value_error_msg = "Tool call ID is required for subagent invocation"
raise ValueError(value_error_msg)
subagent, subagent_state = _validate_and_prepare_state(
subagent_type,
description,
runtime,
)
# The parent's callbacks, tags and configurable reach the subagent
# automatically: langgraph's `ensure_config` seeds each run from the
# ambient parent config and (as of langgraph#7926) merges it per-key, so
# the subagent's bound config still wins collisions (e.g. `lc_agent_name`,
# `recursion_limit`) and parent metadata propagates (deepagents#3634).
# Forwarding those keys explicitly would double-count under the merge
# (e.g. duplicate `tags`), so we only stamp the subagent tracing tag.
subagent_config: RunnableConfig = {"configurable": {"ls_agent_type": "subagent"}}
with _subagent_tracing_context():
result = subagent.invoke(subagent_state, subagent_config)
return _return_command_with_state_update(result, runtime.tool_call_id)
async def atask(View on GitHub (pinned to a1af029e6e)
Solutions
- Invoke `task` through the agent so the framework supplies `tool_call_id`
- If calling directly, set a non-empty `tool_call_id` on the runtime/tool-call object
- Update tests to simulate a proper ToolCall/InstrumentedRuntime
Example fix
// before runtime = SimpleNamespace(tool_call_id=None) task(runtime, description="do it", subagent_type="researcher") // after runtime = SimpleNamespace(tool_call_id="call_123") task(runtime, description="do it", subagent_type="researcher")
Defensive patterns
Strategy: try-catch
Validate before calling
if not getattr(runtime, "tool_call_id", None):
raise RuntimeError("task() must be invoked within a tool call context") Type guard
def in_tool_call_context(runtime) -> bool:
return bool(getattr(runtime, "tool_call_id", None)) Try / catch
try:
result = task(runtime, description=desc, subagent_type=kind)
except ValueError as e:
if "Tool call ID" in str(e):
logger.error("task() called outside a tool-call context")
raise Prevention
- Always invoke `task` through the agent loop, never call its body directly with a hand-built runtime
- In direct-call tests, populate `tool_call_id` with a realistic value
- Wrap raw runtimes in a typed harness that enforces the field
When it happens
Trigger: Calling the sync `task` tool implementation outside a real tool-call context (e.g. invoking the tool's `func` directly with a fabricated `Runtime` whose `tool_call_id` is None or empty).
Common situations: Unit tests invoking the tool function manually; custom runners executing tool bodies without a tool-call id; reusing a runtime object across calls.
Related errors
- SubAgent '{spec['name']}' must specify 'model'
- SubAgent '{spec['name']}' must specify 'tools'
- Invalid interpreter_ptc string {ptc!r}; expected 'safe', 'al
- interpreter_ptc list entries cannot include 'all'; use 'all'
- response_schema cannot be used with compiled subagent "{spec
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/53dd3b1cd727805f.
Report an issue: GitHub.