agentscope-ai/agentscope · error · ValueError

The $defs key `{def_key}` conflicts with existing definition

Error message

The $defs key `{def_key}` conflicts with existing definition in function schema of `{self.tool.name}`.

What it means

Raised in ToolMetadata.get_tool_schema when merging $defs (JSON-Schema definitions from nested pydantic models) and the same $defs key exists on both sides with different definitions. Identical definitions are merged silently; divergent ones mean two different types share a definition name and the merged schema would be ambiguous.

Source

Thrown at src/agentscope/tool/_types.py:142

            for def_key, def_value in extended_schema["$defs"].items():
                def_value_copy = deepcopy(def_value)
                _remove_title_field(
                    def_value_copy,
                )  # pylint: disable=protected-access

                if def_key in merged_params["$defs"]:
                    # Check if the two definitions are from the same BaseModel
                    # by comparing their content
                    # Create copies and remove title fields for comparison

                    existing_def_copy = deepcopy(
                        merged_params["$defs"][def_key],
                    )
                    _remove_title_field(existing_def_copy)

                    if existing_def_copy != def_value_copy:
                        # The definitions are different, raise an error
                        raise ValueError(
                            f"The $defs key `{def_key}` conflicts with "
                            f"existing definition in function schema of "
                            f"`{self.tool.name}`.",
                        )
                    # The definitions are the same (from the same BaseModel),
                    # skip merging this key
                    continue

                merged_params["$defs"][def_key] = def_value_copy

        return function_schema


# The function types that can be registered as tools in AgentScope.
Function: TypeAlias = (
    # Sync function
    Callable[..., ToolChunk]
    |

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Rename one of the colliding nested model classes so their $defs keys differ
  2. Make the two models actually identical (import the same class instead of redefining it)
  3. If a nested model changed shape, update both usages to reference the single current definition

Example fix

# before
class Inner(BaseModel):
    a: int          # used by the tool function
class Inner(BaseModel):
    b: str          # redefined elsewhere, used by extended model -> conflict
# after
class InnerA(BaseModel):
    a: int
class InnerB(BaseModel):
    b: str
# no $defs key collision when merging
Defensive patterns

Strategy: validation

Validate before calling

fn_defs = set(func_schema.get('$defs', {}))
ext_defs = set(ExtendedModel.model_json_schema().get('$defs', {}))
overlap = fn_defs & ext_defs
assert not overlap or all(fn_defs[k] == ext_defs[k] for k in overlap), f'conflicting $defs: {overlap}'

Prevention

When it happens

Trigger: Extending a tool schema with an extended_model whose nested pydantic models produce a $defs entry (e.g. 'Inner') that differs from an 'Inner' definition already present in the function's schema — same class name, different fields/types.

Common situations: Two pydantic models with the same class name but different fields used across the function signature and the extended model; refactored model classes shadowing old names; vendored/duplicated model definitions.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/c3854b4a71455aa4. Report an issue: GitHub.