From d80a0fa7e4e7121ef9a5e0f9e4ca2e32adadedf6 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Fri, 13 Mar 2026 19:57:18 +0100 Subject: [PATCH] Reject null input in agent tool parameter validation JSON null unmarshals into an empty string, so the presence-only key check let {"input":null} through, running the nested agent with a blank user message. Signed-off-by: Bryan Frimin --- pkg/agent/agent_tool.go | 3 ++- pkg/agent/agent_tool_test.go | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pkg/agent/agent_tool.go b/pkg/agent/agent_tool.go index 16ccad145..51345abab 100644 --- a/pkg/agent/agent_tool.go +++ b/pkg/agent/agent_tool.go @@ -83,7 +83,8 @@ func (t *agentTool) Execute(ctx context.Context, arguments string) (ToolResult, }, nil } - if _, ok := fields["input"]; !ok { + raw, ok := fields["input"] + if !ok || string(raw) == "null" { return ToolResult{ Content: "Missing required parameters: input", IsError: true, diff --git a/pkg/agent/agent_tool_test.go b/pkg/agent/agent_tool_test.go index 09440df1e..fe89a8574 100644 --- a/pkg/agent/agent_tool_test.go +++ b/pkg/agent/agent_tool_test.go @@ -215,6 +215,27 @@ func TestAgentTool_Execute(t *testing.T) { }, ) + t.Run( + "null input returns tool error for missing input", + func(t *testing.T) { + t.Parallel() + + ag := agent.New( + "sub", + newTestClient(&mockProvider{}), + agent.WithModel("test-model"), + ) + + tool := ag.AsTool("sub_tool", "A sub-agent tool.") + result, err := tool.Execute(context.Background(), `{"input":null}`) + + require.NoError(t, err) + assert.True(t, result.IsError) + assert.Contains(t, result.Content, "Missing required parameters") + assert.Contains(t, result.Content, "input") + }, + ) + t.Run( "sub-agent error propagates as Go error", func(t *testing.T) {