Skip to content

[RFC] Structured tool result format for LLM-friendly error handling #1010

@aorangehc

Description

@aorangehc

问题描述

当前 InvokableTool 接口返回 (string, error),对字符串结果没有任何结构约束。
这意味着 Tool 的错误信息是非结构化的自由文本,LLM 无法据此做出可靠的决策。

社区中已有真实案例(见 #432):当 Tool 返回 Go error 时,react Agent 直接停止,报错如下:

[NodeRunError] failed to invoke tool[name:get_weather]: not implemented

LLM 完全看不到这个错误——它在框架层就被终止了。
即便错误以字符串形式传回给 LLM,LLM 也无法判断:

  • 是否应该重试?
  • 是否需要修改入参?
  • 是否应该换一个 Tool?
  • 应该给用户回复什么?

问题根因

这个问题分两层:

  1. 框架层InvokableRun 返回 Go error 导致 Agent 直接中止(相关:Is it possible to make react Agent to go on calling other tools or end with a summary when tool calling returns an error? #432
  2. 内容层:即使错误传到了 LLM,也是非结构化、无法被 LLM 利用的字符串

本提案解决第二层——提供一个标准结构化返回格式,
让 Tool 开发者能够写出对 LLM 友好的错误信息。

提案

eino-ext 中新增 toolutil 包,提供标准结构体和 helper 函数。
不修改任何现有接口,纯粹向后兼容的新增。

结构定义

type Result struct {
    Success bool       `json:"success"`
    Data    any        `json:"data,omitempty"`
    Error   *ToolError `json:"error,omitempty"`
}

type ToolError struct {
    Code       string `json:"code"`               // 机器可读的错误码
    Message    string `json:"message"`             // LLM 可读的描述
    Retryable  bool   `json:"retryable"`           // LLM 是否应该重试
    Suggestion string `json:"suggestion,omitempty"` // 建议 LLM 的下一步行动
}

Helper 函数

// 成功
toolutil.OK(data)

// 失败
toolutil.Fail("ORDER_NOT_FOUND", "订单不存在", false,
    "请让用户确认订单号,或调用 list_orders 查询")

Tool 使用示例

func (t *MyTool) InvokableRun(ctx context.Context, args string) (string, error) {
    order, err := t.db.GetOrder(ctx, id)
    if err != nil {
        return toolutil.Fail("ORDER_NOT_FOUND", "order does not exist", false,
            "Confirm the order ID with the user or call list_orders")
    }
    return toolutil.OK(order)
}

LLM 收到的是可直接用于决策的结构化内容:

{
  "success": false,
  "error": {
    "code": "ORDER_NOT_FOUND",
    "message": "order ORD-999 does not exist",
    "retryable": false,
    "suggestion": "Confirm the order ID with the user or call list_orders"
  }
}

动机

Tool 的错误信息应该是为 LLM 设计的,而不是为开发者设计的。
retryablesuggestion 字段让 Agent 拥有足够的上下文做出正确决策,
而不是凭空猜测恢复路径。

实现范围

  • 新增包:eino-ext/components/tool/util
  • 不修改任何现有接口,完全向后兼容
  • 包含单元测试和使用示例

如果 maintainer 认可这个方向,我可以负责实现。

相关 Issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions