From 44f3ece2f786f3e68932792da5d71c97a55367c4 Mon Sep 17 00:00:00 2001 From: BaSui Date: Tue, 12 May 2026 04:43:23 +0800 Subject: [PATCH] fix(a2a): reject ambiguous default agent selection (#79) - only auto-select the lone registered agent when DefaultAgentID is unset - return an explicit error when multiple agents are registered without a configured default instead of relying on random map iteration - add regression coverage for getDefaultAgent and discovery fallback behavior Co-authored-by: Codex --- .../protocol/a2a/a2a_coverage_test.go | 15 +++++++++++++++ agent/execution/protocol/a2a/server_agent.go | 17 ++++++++++++++--- agent/execution/protocol/a2a/server_test.go | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/agent/execution/protocol/a2a/a2a_coverage_test.go b/agent/execution/protocol/a2a/a2a_coverage_test.go index 259ebb87..b3a86269 100644 --- a/agent/execution/protocol/a2a/a2a_coverage_test.go +++ b/agent/execution/protocol/a2a/a2a_coverage_test.go @@ -568,6 +568,21 @@ func TestHTTPServer_GetDefaultAgent_WithDefaultID(t *testing.T) { assert.Equal(t, "default-agent", defaultAg.ID()) } +func TestHTTPServer_GetDefaultAgent_MultipleAgentsWithoutDefaultReturnsError(t *testing.T) { + server := NewHTTPServer(&ServerConfig{ + BaseURL: "http://localhost:8080", + Logger: zap.NewNop(), + }) + + _ = server.RegisterAgent(newMockAgent("agent-a", "Agent A")) + _ = server.RegisterAgent(newMockAgent("agent-b", "Agent B")) + + ag, err := server.getDefaultAgent() + require.Error(t, err) + assert.Nil(t, ag) + assert.Contains(t, err.Error(), "multiple agents registered") +} + // --- AgentCard discovery with agent_id query param --- func TestHTTPServer_HandleAgentCardDiscovery_WithAgentID(t *testing.T) { diff --git a/agent/execution/protocol/a2a/server_agent.go b/agent/execution/protocol/a2a/server_agent.go index a93eb2cf..3d4b5ed0 100644 --- a/agent/execution/protocol/a2a/server_agent.go +++ b/agent/execution/protocol/a2a/server_agent.go @@ -2,6 +2,7 @@ package a2a import ( "fmt" + "sort" "go.uber.org/zap" ) @@ -133,9 +134,19 @@ func (s *HTTPServer) getDefaultAgent() (Agent, error) { } } - // 返回第一个可用的代理 - for _, ag := range s.agents { - return ag, nil + if len(s.agents) == 1 { + for _, ag := range s.agents { + return ag, nil + } + } + + if len(s.agents) > 1 { + agentIDs := make([]string, 0, len(s.agents)) + for id := range s.agents { + agentIDs = append(agentIDs, id) + } + sort.Strings(agentIDs) + return nil, fmt.Errorf("multiple agents registered (%d) but no default agent configured; set DefaultAgentID (available: %v)", len(agentIDs), agentIDs) } return nil, ErrAgentNotFound diff --git a/agent/execution/protocol/a2a/server_test.go b/agent/execution/protocol/a2a/server_test.go index 9e9af63b..944e24de 100644 --- a/agent/execution/protocol/a2a/server_test.go +++ b/agent/execution/protocol/a2a/server_test.go @@ -123,6 +123,24 @@ func TestHTTPServer_HandleAgentCardDiscovery(t *testing.T) { assert.Equal(t, "Test Agent", card.Name) } +func TestHTTPServer_HandleAgentCardDiscovery_MultipleAgentsWithoutDefaultReturnsNotFound(t *testing.T) { + server := NewHTTPServer(&ServerConfig{ + BaseURL: "http://localhost:8080", + Logger: zap.NewNop(), + }) + + _ = server.RegisterAgent(newMockAgent("agent-a", "Agent A")) + _ = server.RegisterAgent(newMockAgent("agent-b", "Agent B")) + + req := httptest.NewRequest(http.MethodGet, "/.well-known/agent.json", nil) + w := httptest.NewRecorder() + + server.ServeHTTP(w, req) + + assert.Equal(t, http.StatusNotFound, w.Code) + assert.Contains(t, w.Body.String(), "multiple agents registered") +} + func TestHTTPServer_HandleSyncMessage(t *testing.T) { server := NewHTTPServer(&ServerConfig{ BaseURL: "http://localhost:8080",