{"record":{"id":"eb7b679dbc8c35d9","repo":"langchain-ai/deepagents","slug":"models-can-only-be-provided-when-agent-is-a-factor","errorCode":null,"errorMessage":"models can only be provided when agent is a factory","messagePattern":"models can only be provided when agent is a factory","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/acp/deepagents_acp/server.py","lineNumber":260,"sourceCode":"            models: Optional list of available models with 'value', 'name', and optionally\n              'description'\n            load_sessions: Advertise and implement durable `session/load`. The agent graph\n              must use a checkpointer that survives server restarts.\n        \"\"\"\n        super().__init__()\n        self._cwd = \"\"\n        self._agent_factory = agent\n        self._agent: CompiledStateGraph | None = None\n        self._agent_session_id: str | None = None\n        self._load_sessions = load_sessions\n\n        if isinstance(agent, CompiledStateGraph):\n            if modes is not None:\n                msg = \"modes can only be provided when agent is a factory\"\n                raise ValueError(msg)\n            if models is not None:\n                msg = \"models can only be provided when agent is a factory\"\n                raise ValueError(msg)\n            self._modes: SessionModeState | None = None\n            self._models: list[dict[str, str]] | None = None\n        else:\n            self._modes = modes\n            self._models = models\n\n        self._session_modes: dict[str, str] = {}\n        self._session_mode_states: dict[str, SessionModeState] = {}\n        self._session_models: dict[str, str] = {}  # Track current model per session\n        self._cancelled = False\n        self._session_plans: dict[str, list[dict[str, Any]]] = {}\n        self._session_cwds: dict[str, str] = {}\n        self._session_mcp_servers: dict[str, list[McpServer]] = {}\n        self._allowed_command_types: dict[\n            str, set[tuple[str, str | None]]\n        ] = {}  # Track allowed command types per session\n\n    def on_connect(self, conn: Client) -> None:","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/acp/deepagents_acp/server.py#L242-L278","documentation":"The model half of a `ModelSpec` is required; `__post_init__` raises `ValueError` when `model` is empty. This guarantees every spec resolves to a concrete model so downstream `create_model` calls never receive a blank model id.","triggerScenarios":"Calling `ModelSpec(provider='anthropic', model='')`, `ModelSpec.parse('anthropic:')`, or `ModelSpec.parse('anthropic')`... (the latter hits parse's format error; the colon-only case hits this). Any spec string ending at the colon with no model text.","commonSituations":"Typing `provider:` in a config field with the model name forgotten; a truncated spec after copy/paste; empty value interpolated into a spec template like `f\"{provider}:{model}\"` where `model` came from missing config.","solutions":["Supply the model id: `anthropic:claude-sonnet-4-5`, not `anthropic:`","Check the source of the model value (config key, env var) — it is empty or missing","Use `ModelSpec.try_parse(...)` for non-raising validation"],"exampleFix":"// before\nspec = ModelSpec.parse(\"anthropic:\")\n// after\nspec = ModelSpec.parse(\"anthropic:claude-sonnet-4-5\")","handlingStrategy":"validation","validationCode":"provider, _, model = raw.partition(\":\")\nif not model.strip():\n    raise ValueError(f\"spec {raw!r} is missing the model id\")\nspec = ModelSpec(provider=provider, model=model)","typeGuard":"def is_valid_model_spec(obj: object) -> bool:\n    return isinstance(obj, ModelSpec) and bool(obj.provider) and bool(obj.model)","tryCatchPattern":"try:\n    spec = ModelSpec.parse(raw)\nexcept ValueError as exc:\n    logger.error(\"bad model spec %r: %s\", raw, exc)\n    spec = DEFAULT_MODEL_SPEC","preventionTips":["Check config values for emptiness before interpolating them into spec strings","Use `try_parse` for user-facing input paths","Keep model ids in one config source so they cannot be silently dropped"],"tags":["python","validation","model-spec","config"],"backgroundTag":"invalid-model-spec","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}