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

  1. Include the provider prefix: use `anthropic:claude-sonnet-4-5`, not just the model id
  2. If constructing programmatically, check the provider is non-empty before building the `ModelSpec`
  3. 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

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


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