microsoft/autogen · error · ValueError

Handoff name must be a string: {values['name']}

Error message

Handoff name must be a string: {values['name']}

What it means

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.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/base/_handoff.py:40

    name: str = Field(default="")
    """The name of this handoff configuration. If not provided, it is generated from the target agent's name."""

    message: str = Field(default="")
    """The message to the target agent.
    By default, it will be the result for the handoff tool.
    If not provided, it is generated from the target agent's name."""

    @model_validator(mode="before")
    @classmethod
    def set_defaults(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        if not values.get("description"):
            values["description"] = f"Handoff to {values['target']}."
        if not values.get("name"):
            values["name"] = f"transfer_to_{values['target']}".lower()
        else:
            name = values["name"]
            if not isinstance(name, str):
                raise ValueError(f"Handoff name must be a string: {values['name']}")
            # Check if name is a valid identifier.
            if not name.isidentifier():
                raise ValueError(f"Handoff name must be a valid identifier: {values['name']}")
        if not values.get("message"):
            values["message"] = (
                f"Transferred to {values['target']}, adopting the role of {values['target']} immediately."
            )
        return values

    @property
    def handoff_tool(self) -> BaseTool[BaseModel, BaseModel]:
        """Create a handoff tool from this handoff configuration."""

        def _handoff_tool() -> str:
            return self.message

        return FunctionTool(_handoff_tool, name=self.name, description=self.description, strict=True)

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Pass name as a plain string or omit it entirely to get the auto-generated transfer_to_<target> name
  2. Sanitize config-sourced values: str(name) or name = name if isinstance(name, str) else None before constructing Handoff
  3. Validate the handoff config schema at load time (pydantic model or jsonschema) before creating agents

Example fix

# before
handoff = Handoff(target="writer", name=agent_id)  # agent_id: int

# after
handoff = Handoff(target="writer", name=str(agent_id) if agent_id else None)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_valid_handoff_name(name) -> bool:
    return name is None or isinstance(name, str)

Type guard

def is_handoff_name(value) -> bool:
    """True when `name` is acceptable for Handoff (str or omittable)."""
    return value is None or (isinstance(value, str) and len(value) > 0)

Try / catch

from autogen_agentchat.base import Handoff
try:
    handoff = Handoff(target="writer", name=raw_name)
except ValueError as e:
    if "must be a string" in str(e):
        handoff = Handoff(target="writer")  # fall back to auto-generated name
    else:
        raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/6b68c8a70e9152ed. Report an issue: GitHub.