@@ -45,6 +45,25 @@ def emit_warning(self, kind: JsonSchemaWarningKind, detail: str) -> None:
4545 raise ValueError (f"JSON schema warning: { kind } - { detail } " )
4646
4747
48+ _LOCAL_DEFS_PREFIX = "#/$defs/"
49+
50+
51+ def _inline_root_ref (schema : dict [str , Any ]) -> dict [str , Any ]:
52+ """Give a schema whose root is a bare `$ref` into `$defs` an inline root.
53+
54+ pydantic emits a self-referential model as `{"$defs": {...}, "$ref": "#/$defs/Model"}`, with no
55+ `type` at the root; `Tool.outputSchema` requires `type: object` at the root. The referenced
56+ definition is copied onto the root and `$defs` is kept, since nested references still point into
57+ it. Root siblings of the `$ref` win over the definition's keys.
58+ """
59+ ref = schema .get ("$ref" )
60+ if not isinstance (ref , str ) or not ref .startswith (_LOCAL_DEFS_PREFIX ):
61+ return schema
62+ definition = cast (dict [str , Any ], schema ["$defs" ][ref .removeprefix (_LOCAL_DEFS_PREFIX )])
63+ siblings = {key : value for key , value in schema .items () if key != "$ref" }
64+ return {** definition , ** siblings }
65+
66+
4867class ArgModelBase (BaseModel ):
4968 """A model representing the arguments to a function."""
5069
@@ -428,7 +447,7 @@ def _try_create_model_and_schema(
428447 logger .info (f"Cannot create schema for type { type_expr } in { func_name } : { type (e ).__name__ } : { e } " )
429448 return None , None , False
430449
431- return model , schema , wrap_output
450+ return model , _inline_root_ref ( schema ) , wrap_output
432451
433452 return None , None , False
434453
0 commit comments