{"record":{"id":"b395d2f08b2c7de0","repo":"langchain-ai/langchain","slug":"invalid-args-schema-expected-basemodel-or-dict-g","errorCode":null,"errorMessage":"Invalid args_schema: expected BaseModel or dict, got {args_schema}","messagePattern":"Invalid args_schema: expected BaseModel or dict, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/structured.py","lineNumber":232,"sourceCode":"            description_ = source_function.__doc__ or None\n        if description_ is None and args_schema:\n            if isinstance(args_schema, type) and is_basemodel_subclass(args_schema):\n                description_ = args_schema.__doc__\n                if (\n                    description_\n                    and \"A base class for creating Pydantic models\" in description_\n                ):\n                    description_ = \"\"\n                elif not description_:\n                    description_ = None\n            elif isinstance(args_schema, dict):\n                description_ = args_schema.get(\"description\")\n            else:\n                msg = (\n                    \"Invalid args_schema: expected BaseModel or dict, \"\n                    f\"got {args_schema}\"\n                )\n                raise TypeError(msg)\n        if description_ is None:\n            msg = \"Function must have a docstring if description not provided.\"\n            raise ValueError(msg)\n        if description is None:\n            # Only apply if using the function's docstring\n            description_ = textwrap.dedent(description_).strip()\n\n        # Description example:\n        # search_api(query: str) - Searches the API for the query.\n        description_ = f\"{description_.strip()}\"\n        return cls(\n            name=name,\n            func=func,\n            coroutine=coroutine,\n            args_schema=args_schema,\n            description=description_,\n            return_direct=return_direct,\n            response_format=response_format,","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/structured.py#L214-L250","documentation":"StructuredTool.from_function accepts args_schema only as a pydantic BaseModel class or a JSON-schema-ish dict. Any other type (a TypedDict, an instance instead of a class, a string, a dataclass) raises TypeError with the offending value.","triggerScenarios":"StructuredTool.from_function(fn, args_schema=MyTypedDict); passing an instantiated model args_schema=MyModel(...); passing a JSON schema string.","commonSituations":"Teams using TypedDicts for tool schemas (works with @tool type inference, not here); passing schema instances rather than classes; migrating schemas from JSON strings.","solutions":["Pass a pydantic BaseModel subclass: args_schema=MyArgs (class, not instance)","Or pass a dict schema: args_schema={'title': 'MyArgs', 'type': 'object', 'properties': {...}, 'required': [...]}","Convert TypedDicts: args_schema=create_model from the TypedDict's annotations, or redeclare as a pydantic model"],"exampleFix":"# before\nclass MyArgs(TypedDict):\n    query: str\n\ntool = StructuredTool.from_function(fn, args_schema=MyArgs)  # TypeError\n\n# after\nfrom pydantic import BaseModel, Field\n\nclass MyArgs(BaseModel):\n    query: str = Field(description=\"Search query\")\n\ntool = StructuredTool.from_function(fn, args_schema=MyArgs)","handlingStrategy":"type-guard","validationCode":"from pydantic import BaseModel\n\ndef is_valid_args_schema(schema: object) -> bool:\n    return (\n        (isinstance(schema, type) and issubclass(schema, BaseModel))\n        or isinstance(schema, dict)\n    )\n\n# use before construction:\nassert is_valid_args_schema(args_schema), f\"bad args_schema: {args_schema!r}\"","typeGuard":"from pydantic import BaseModel\n\ndef is_pydantic_schema_or_dict(x: object) -> bool:\n    if isinstance(x, type):\n        return issubclass(x, BaseModel)\n    return isinstance(x, dict)","tryCatchPattern":"try:\n    t = StructuredTool.from_function(fn, args_schema=schema, name=\"t\")\nexcept TypeError as e:\n    if \"Invalid args_schema\" in str(e):\n        from pydantic import create_model\n        fields = {k: (v, ...) for k, v in schema.__annotations__.items()}  # TypedDict case\n        t = StructuredTool.from_function(\n            fn, args_schema=create_model(\"t_args\", **fields), name=\"t\"\n        )\n    else:\n        raise","preventionTips":["Standardize on pydantic BaseModel classes for args_schema in shared code","Pass the class, never an instance","Convert TypedDict schemas to pydantic models at module definition time"],"tags":["langchain","tools","schema","pydantic","type-error"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}