From d1127d597396b2c36c89778352396d0407e87940 Mon Sep 17 00:00:00 2001 From: Hz_ Date: Fri, 31 Jul 2026 18:00:34 +0800 Subject: [PATCH] fix(go-agent): fix Tavily tool array schemas (#17640) ## Summary - Add string item schemas for Tavily Search domain filters. - Add the same schema fix for Tavily Extract URLs. - Add regression coverage for generated tool schemas. ## Testing - `CGO_ENABLED=0 go test -count=1 ./internal/agent/tool ./internal/agent/component` image --- internal/agent/tool/tavily.go | 3 ++ internal/agent/tool/tavily_test.go | 48 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/internal/agent/tool/tavily.go b/internal/agent/tool/tavily.go index f85e825828..4eaed95443 100644 --- a/internal/agent/tool/tavily.go +++ b/internal/agent/tool/tavily.go @@ -234,11 +234,13 @@ func (t *TavilyTool) Info(_ context.Context) (*schema.ToolInfo, error) { }, "include_domains": { Type: schema.Array, + ElemInfo: &schema.ParameterInfo{Type: schema.String}, Desc: "Domains that search results must include.", Required: false, }, "exclude_domains": { Type: schema.Array, + ElemInfo: &schema.ParameterInfo{Type: schema.String}, Desc: "Domains that search results must exclude.", Required: false, }, @@ -254,6 +256,7 @@ func (t *TavilyExtractTool) Info(_ context.Context) (*schema.ToolInfo, error) { ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{ "urls": { Type: schema.Array, + ElemInfo: &schema.ParameterInfo{Type: schema.String}, Desc: "The URLs to extract content from.", Required: true, }, diff --git a/internal/agent/tool/tavily_test.go b/internal/agent/tool/tavily_test.go index 7f3f96c6f1..72b082a339 100644 --- a/internal/agent/tool/tavily_test.go +++ b/internal/agent/tool/tavily_test.go @@ -23,6 +23,8 @@ import ( "net/http/httptest" "strings" "testing" + + "github.com/cloudwego/eino/schema" ) func TestTavily_BuildRequest(t *testing.T) { @@ -183,6 +185,52 @@ func TestTavily_Info(t *testing.T) { } } +func TestTavily_InfoArraySchemasIncludeStringItems(t *testing.T) { + t.Parallel() + + info, err := NewTavilyTool().Info(context.Background()) + if err != nil { + t.Fatalf("Tavily Info: %v", err) + } + assertToolArrayItemType(t, info, "include_domains") + assertToolArrayItemType(t, info, "exclude_domains") + + extractInfo, err := NewTavilyExtractTool().Info(context.Background()) + if err != nil { + t.Fatalf("Tavily Extract Info: %v", err) + } + assertToolArrayItemType(t, extractInfo, "urls") +} + +func assertToolArrayItemType(t *testing.T, info *schema.ToolInfo, fieldName string) { + t.Helper() + + params, err := info.ParamsOneOf.ToJSONSchema() + if err != nil { + t.Fatalf("convert %s schema: %v", info.Name, err) + } + rawSchema, err := json.Marshal(params) + if err != nil { + t.Fatalf("marshal %s schema: %v", info.Name, err) + } + var schemaMap map[string]any + if err := json.Unmarshal(rawSchema, &schemaMap); err != nil { + t.Fatalf("decode %s schema: %v", info.Name, err) + } + properties, ok := schemaMap["properties"].(map[string]any) + if !ok { + t.Fatalf("%s schema properties = %#v", info.Name, schemaMap["properties"]) + } + field, ok := properties[fieldName].(map[string]any) + if !ok { + t.Fatalf("%s schema field %q = %#v", info.Name, fieldName, properties[fieldName]) + } + items, ok := field["items"].(map[string]any) + if !ok || items["type"] != "string" { + t.Fatalf("%s schema field %q items = %#v, want {type: string}", info.Name, fieldName, field["items"]) + } +} + func TestTavily_EmptyQueryReturnsEmptyResults(t *testing.T) { t.Parallel()