run-llama/llama_index · error · ValueError

Handoff output prompt must contain {to_agent} and {reason}

Error message

Handoff output prompt must contain {to_agent} and {reason}

What it means

handoff_output_prompt defines the exact string format the LLM must emit to perform a handoff (containing {to_agent} and {reason}). When passed as a string, AgentWorkflow validates both placeholders exist before wrapping it in a PromptTemplate, because _initialize_agent handoff parsing depends on this exact output shape.

Source

Thrown at llama-index-core/llama_index/core/agent/workflow/multi_agent_workflow.py:169

        self.root_agent = root_agent
        self.initial_state = initial_state or {}

        handoff_prompt = handoff_prompt or DEFAULT_HANDOFF_PROMPT
        if isinstance(handoff_prompt, str):
            handoff_prompt = PromptTemplate(handoff_prompt)
            if "{agent_info}" not in handoff_prompt.get_template():
                raise ValueError("Handoff prompt must contain {agent_info}")
        self.handoff_prompt = handoff_prompt

        handoff_output_prompt = handoff_output_prompt or DEFAULT_HANDOFF_OUTPUT_PROMPT
        if isinstance(handoff_output_prompt, str):
            handoff_output_prompt = PromptTemplate(handoff_output_prompt)
            if (
                "{to_agent}" not in handoff_output_prompt.get_template()
                or "{reason}" not in handoff_output_prompt.get_template()
            ):
                raise ValueError(
                    "Handoff output prompt must contain {to_agent} and {reason}"
                )
        self.handoff_output_prompt = handoff_output_prompt

        state_prompt = state_prompt or DEFAULT_STATE_PROMPT
        if isinstance(state_prompt, str):
            state_prompt = PromptTemplate(state_prompt)
            if (
                "{state}" not in state_prompt.get_template()
                or "{msg}" not in state_prompt.get_template()
            ):
                raise ValueError("State prompt must contain {state} and {msg}")
        self.state_prompt = state_prompt

        self.output_cls = output_cls
        self.structured_output_fn = structured_output_fn
        if output_cls is not None and structured_output_fn is not None:
            self.structured_output_fn = None

View on GitHub (pinned to afd0fef371)

Solutions

  1. Include both tokens verbatim, e.g. handoff_output_prompt='Handoff to <{to_agent}> because {reason}'.
  2. Or leave handoff_output_prompt unset to use DEFAULT_HANDOFF_OUTPUT_PROMPT.
  3. If you need a different format, keep the placeholders and only change surrounding text.

Example fix

# before
wf = AgentWorkflow(
    agents=[...], root_agent="researcher",
    handoff_output_prompt="Transfer to {target} since {reason}",  # ValueError
)

# after
wf = AgentWorkflow(
    agents=[...], root_agent="researcher",
    handoff_output_prompt="Transfer to {to_agent} because {reason}",
)
Defensive patterns

Strategy: validation

Validate before calling

def check_handoff_output_prompt(tpl: str):
    for token in ("{to_agent}", "{reason}"):
        if token not in tpl:
            raise ValueError(f"handoff_output_prompt must contain {token}")
    return tpl

Prevention

When it happens

Trigger: AgentWorkflow(..., handoff_output_prompt=...) with a string template lacking either '{to_agent}' or '{reason}'. Both must be present; missing either one triggers the error.

Common situations: Reformatting the handoff output template (e.g. renaming {to_agent} to {target}) which breaks the parser; translating/localizing the prompt and losing a placeholder; copying examples from incompatible versions.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/94fab9154768607d. Report an issue: GitHub.