[Bug]: DashScope FunctionTool conversion drops nested JSON Schema definitions
Bug description
llama-index-llms-dashscope==0.7.0 corrupts valid nested JSON Schema when it converts a FunctionTool for DashScope.
DashScope._convert_tool_to_dashscope_format() retains only type and properties from tool.metadata.get_parameters_dict(). For Pydantic schemas with nested models, this removes root $defs but leaves items.$ref pointing to it. It also puts required under function, instead of under function.parameters.
This makes the wire-schema internally inconsistent and weakens tool-argument constraints. Agent traces that record tool.metadata.to_openai_tool() can look valid even though the adapter sends the damaged version.
Version
llama-index-llms-dashscope==0.7.0llama-index-core==0.14.24(resolved by an isolateduv run --no-project --with ...environment)- Python 3.14
Minimal reproduction
from pydantic import BaseModel, Field
from jsonschema import Draft202012Validator
from llama_index.core.tools import FunctionTool
from llama_index.llms.dashscope import DashScope
class Item(BaseModel):
entity: str
entity_type: str
class Batch(BaseModel):
entities: list[Item] = Field(max_length=128)
def validate_entities(entities: list[Item]) -> str:
return "ok"
tool = FunctionTool.from_defaults(fn=validate_entities, fn_schema=Batch)
original = tool.metadata.get_parameters_dict()
converted = DashScope._convert_tool_to_dashscope_format(None, tool)
arguments = {"entities": [{"entity": "Example", "entity_type": "Organization"}]}
print(sorted(original))
print(sorted(converted["function"]["parameters"]))
print(converted["function"].get("required"))
print(list(Draft202012Validator(original).iter_errors(arguments)))
print(list(Draft202012Validator(converted["function"]["parameters"]).iter_errors(arguments)))
Observed output before the final line raises:
['$defs', 'properties', 'required', 'type']
['properties', 'type']
['entities']
[]
jsonschema.exceptions._WrappedReferencingError:
PointerToNowhere: '/$defs/Item' does not exist within
{'type': 'object', 'properties': {'entities': {'items': {'$ref': '#/$defs/Item'}, ...}}}
Expected behavior
The converted function.parameters should remain a valid schema. At minimum it should preserve $defs together with $ref, and place required inside parameters:
parameters = tool.metadata.get_parameters_dict()
tool_spec = {
"type": "function",
"function": {
"name": tool.metadata.name,
"description": tool.metadata.description,
"parameters": parameters,
},
}
If the target DashScope endpoint cannot accept $defs/$ref, the adapter should inline or otherwise resolve references before sending the request, with tests for nested Pydantic schemas. A regression test should validate the outgoing schema, not only ToolMetadata.to_openai_tool().
I found related DashScope tool-call issues but no existing issue covering this $defs/$ref plus misplaced-required conversion defect.
Source: run-llama/llama_index