datawhalechina/hello-agents · warning · Exception

工具未定义: {tool_name}.

Error message

工具未定义: {tool_name}.

What it means

A generic Exception raised in the GPSAgent agent loop (src/gps/agent_loop.py) when the LLM's tool call names a tool outside the dispatch table. The loop explicitly matches tool_name against 'find_fact', 'find_goal', 'check', 'summarize', and 'finish'; anything else hits the else branch. Importantly, the loop immediately catches this exception and converts it to the string '调用工具时发生错误:...' added to conversation memory, so the agent usually self-corrects on the next turn rather than crashing.

Source

Thrown at Co-creation-projects/BitSecret-GPSAgent/src/gps/agent_loop.py:189

                try:  # tool calls
                    tool_name, args = parse_response(response)
                    if tool_name == 'apply':
                        tool_call = '工具执行结果:\n' + solver.apply(args)
                    elif tool_name == 'decompose':
                        tool_call = '工具执行结果:\n' + solver.decompose(args)
                    elif tool_name == 'find_fact':
                        tool_call = '工具执行结果:\n' + solver.find_fact(args)
                    elif tool_name == 'find_goal':
                        tool_call = '工具执行结果:\n' + solver.find_goal(args)
                    elif tool_name == 'check':
                        tool_call = '工具执行结果:\n' + solver.check()
                    elif tool_name == 'summarize':
                        agent.summarize(solver.state(), args)
                        continue
                    elif tool_name == 'finish':
                        break
                    else:
                        raise Exception(f'工具未定义: {tool_name}.')
                except Exception as e:
                    tool_call = f"调用工具时发生错误:{repr(e)}"

                agent.add_memory(role='user', content=tool_call)

                if solver.status_of_goal[0] == 1:
                    agent.add_memory(role='user', content='检测到问题已求解,自动结束。')
                    break

                if agent.context_length > max_context:
                    agent.add_memory(role='user', content=get_summarize_prompt())

        except KeyboardInterrupt:
            agent.add_memory(role='user', content="用户主动介入中断(KeyboardInterrupt)。")

        if solver.status_of_goal[0] == 1:
            result = 'solved'
            agent.add_memory(role='user', content="求解结束:成功✅")

View on GitHub (pinned to 606a07d341)

Solutions

  1. Make the system prompt enumerate the exact allowed tool names ('find_fact', 'find_goal', 'check', 'summarize', 'finish') and state that other names are invalid
  2. Normalize tool_name before dispatch: strip whitespace and parentheses (tool_name.strip())
  3. Lower temperature or use a model with reliable function-calling to reduce hallucinated names
  4. Log unknown tool names with the raw model output to identify prompt gaps
  5. If a new tool is intended, add an elif branch for it in the dispatch chain

Example fix

# before
else:
    raise Exception(f'工具未定义: {tool_name}.')

# after
tool_name = tool_name.strip()
if tool_name not in {'find_fact', 'find_goal', 'check', 'summarize', 'finish'}:
    agent.add_memory(role='user', content=f'未知工具 {tool_name},可用工具: find_fact, find_goal, check, summarize, finish')
    continue
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_TOOLS = {'find_fact', 'find_goal', 'check', 'summarize', 'finish'}
tool_name = raw_tool_name.strip().strip('()')
if tool_name not in ALLOWED_TOOLS:
    # do not dispatch; feed corrective feedback to the model instead
    feedback = f'未知工具 {tool_name}。可用工具: {sorted(ALLOWED_TOOLS)}'

Type guard

def is_known_tool(name: str) -> bool:
    return isinstance(name, str) and name.strip() in {
        'find_fact', 'find_goal', 'check', 'summarize', 'finish'
    }

Try / catch

try:
    dispatch(tool_name, args)
except Exception as e:
    # the loop already converts this to a memory message; keep that pattern:
    agent.add_memory(role='user', content=f'调用工具时发生错误:{repr(e)},请仅使用: {ALLOWED_TOOLS}')
    continue

Prevention

When it happens

Trigger: The model outputs a function/tool name such as 'search', 'find_fact(' with a typo, or a hallucinated tool like 'solve' in its tool-call response. Causes: system prompt not listing the exact tool names, model not adhering to the schema, or the temperature/prompt causing creative tool invention. The error is swallowed into memory, so it manifests as a corrective user-role message in the transcript.

Common situations: Switching to a weaker model that invents tool names; renaming a tool in the solver without updating the prompt's tool list; few-shot examples referencing removed tools; locale/tokenization quirks producing tool names with trailing whitespace or parentheses.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/377c3a720eac5510. Report an issue: GitHub.