{"record":{"id":"6b68c8a70e9152ed","repo":"microsoft/autogen","slug":"handoff-name-must-be-a-string-values-name","errorCode":null,"errorMessage":"Handoff name must be a string: {values['name']}","messagePattern":"Handoff name must be a string: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/base/_handoff.py","lineNumber":40,"sourceCode":"    name: str = Field(default=\"\")\n    \"\"\"The name of this handoff configuration. If not provided, it is generated from the target agent's name.\"\"\"\n\n    message: str = Field(default=\"\")\n    \"\"\"The message to the target agent.\n    By default, it will be the result for the handoff tool.\n    If not provided, it is generated from the target agent's name.\"\"\"\n\n    @model_validator(mode=\"before\")\n    @classmethod\n    def set_defaults(cls, values: Dict[str, Any]) -> Dict[str, Any]:\n        if not values.get(\"description\"):\n            values[\"description\"] = f\"Handoff to {values['target']}.\"\n        if not values.get(\"name\"):\n            values[\"name\"] = f\"transfer_to_{values['target']}\".lower()\n        else:\n            name = values[\"name\"]\n            if not isinstance(name, str):\n                raise ValueError(f\"Handoff name must be a string: {values['name']}\")\n            # Check if name is a valid identifier.\n            if not name.isidentifier():\n                raise ValueError(f\"Handoff name must be a valid identifier: {values['name']}\")\n        if not values.get(\"message\"):\n            values[\"message\"] = (\n                f\"Transferred to {values['target']}, adopting the role of {values['target']} immediately.\"\n            )\n        return values\n\n    @property\n    def handoff_tool(self) -> BaseTool[BaseModel, BaseModel]:\n        \"\"\"Create a handoff tool from this handoff configuration.\"\"\"\n\n        def _handoff_tool() -> str:\n            return self.message\n\n        return FunctionTool(_handoff_tool, name=self.name, description=self.description, strict=True)\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/base/_handoff.py#L22-L58","documentation":"Handoff's pydantic model_validator (mode='before') validates the optional name field. If a name is supplied and it is not a str instance, ValueError is raised during model construction, before field validation even runs. The validator also auto-generates description, name (transfer_to_<target>), and message defaults when they are absent.","triggerScenarios":"Constructing Handoff(target='writer', name=123), name=None together with an explicit truthy check path (name='' or name=[] bypass via falsy values auto-generate), or passing a dict/config payload where 'name' holds a non-string JSON value (int, list, bool).","commonSituations":"Loading handoff definitions from YAML/JSON config where name is unquoted (parsed as int/bool); programmatic generation of handoffs from agent names that are not strings; LLM-generated tool schemas injecting non-string names.","solutions":["Pass name as a plain string or omit it entirely to get the auto-generated transfer_to_<target> name","Sanitize config-sourced values: str(name) or name = name if isinstance(name, str) else None before constructing Handoff","Validate the handoff config schema at load time (pydantic model or jsonschema) before creating agents"],"exampleFix":"# before\nhandoff = Handoff(target=\"writer\", name=agent_id)  # agent_id: int\n\n# after\nhandoff = Handoff(target=\"writer\", name=str(agent_id) if agent_id else None)","handlingStrategy":"type-guard","validationCode":"def is_valid_handoff_name(name) -> bool:\n    return name is None or isinstance(name, str)","typeGuard":"def is_handoff_name(value) -> bool:\n    \"\"\"True when `name` is acceptable for Handoff (str or omittable).\"\"\"\n    return value is None or (isinstance(value, str) and len(value) > 0)","tryCatchPattern":"from autogen_agentchat.base import Handoff\ntry:\n    handoff = Handoff(target=\"writer\", name=raw_name)\nexcept ValueError as e:\n    if \"must be a string\" in str(e):\n        handoff = Handoff(target=\"writer\")  # fall back to auto-generated name\n    else:\n        raise","preventionTips":["Quote handoff names in YAML/JSON config so they parse as strings","Coerce config-sourced names with str() before constructing Handoff","Omit name when unsure — the auto-generated transfer_to_<target> is always valid"],"tags":["handoff","pydantic","validation","agentchat"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}