langchain-ai/deepagents · error · ValueError
modes can only be provided when agent is a factory
Error message
modes can only be provided when agent is a factory
What it means
`ModelSpec` validates itself in `__post_init__`: a spec must name both a provider and a model. This error means a `ModelSpec` was constructed with an empty `provider` string (e.g. `ModelSpec(provider='', model='claude-sonnet-4-5')` or `ModelSpec.parse(':model')`... actually `:model` yields provider `''`). The library throws it early so an unusable spec never reaches model construction.
Source
Thrown at libs/acp/deepagents_acp/server.py:257
Args:
agent: Either a compiled state graph or a factory function that creates one
modes: Optional mode configuration (deprecated, use config_options instead)
models: Optional list of available models with 'value', 'name', and optionally
'description'
load_sessions: Advertise and implement durable `session/load`. The agent graph
must use a checkpointer that survives server restarts.
"""
super().__init__()
self._cwd = ""
self._agent_factory = agent
self._agent: CompiledStateGraph | None = None
self._agent_session_id: str | None = None
self._load_sessions = load_sessions
if isinstance(agent, CompiledStateGraph):
if modes is not None:
msg = "modes can only be provided when agent is a factory"
raise ValueError(msg)
if models is not None:
msg = "models can only be provided when agent is a factory"
raise ValueError(msg)
self._modes: SessionModeState | None = None
self._models: list[dict[str, str]] | None = None
else:
self._modes = modes
self._models = models
self._session_modes: dict[str, str] = {}
self._session_mode_states: dict[str, SessionModeState] = {}
self._session_models: dict[str, str] = {} # Track current model per session
self._cancelled = False
self._session_plans: dict[str, list[dict[str, Any]]] = {}
self._session_cwds: dict[str, str] = {}
self._session_mcp_servers: dict[str, list[McpServer]] = {}
self._allowed_command_types: dict[
str, set[tuple[str, str | None]]View on GitHub (pinned to a1af029e6e)
Solutions
- Include the provider prefix: use `anthropic:claude-sonnet-4-5`, not just the model id
- If constructing programmatically, check the provider is non-empty before building the `ModelSpec`
- Use `ModelSpec.try_parse(...)` and handle `None` instead of letting it raise
Example fix
// before
spec = ModelSpec.parse(":claude-sonnet-4-5")
// after
spec = ModelSpec.parse("anthropic:claude-sonnet-4-5") Defensive patterns
Strategy: validation
Validate before calling
def has_provider(spec: str) -> bool:
return bool(spec) and bool(spec.split(":", 1)[0].strip())
if not has_provider(raw):
raise ValueError(f"spec {raw!r} is missing the provider prefix")
spec = ModelSpec.parse(raw) Type guard
def is_valid_model_spec(obj: object) -> bool:
return isinstance(obj, ModelSpec) and bool(obj.provider) and bool(obj.model) Try / catch
try:
spec = ModelSpec.parse(raw)
except ValueError as exc:
logger.error("bad model spec %r: %s", raw, exc)
spec = ModelSpec.parse(f"anthropic:{raw}") # or a sane default Prevention
- Always build specs from the `provider:model` string form rather than hand-assembling fields
- Validate provider detection results for emptiness before constructing a `ModelSpec`
- Prefer `ModelSpec.try_parse` when input is user-supplied
When it happens
Trigger: Calling `ModelSpec(provider='', model=...)`, `ModelSpec.parse(':gpt-5')`, or `ModelSpec.parse('')` — a spec string whose text before the first colon is empty. Also reachable when callers build specs by slicing a `provider:model` string at a wrong separator.
Common situations: Hand-editing `[models]` config keys with `:model` instead of `provider:model`; programmatic spec construction where the provider variable is empty because detection (`detect_provider`) failed or an env var was blank; string splitting on the wrong delimiter.
Related errors
- models can only be provided when agent is a factory
- -32601
- -32602
- recursion_limit must be None or a positive integer
- Invalid class_path '{class_path}': must be in module.path:Cl
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/58f85ad656622662.
Report an issue: GitHub.