diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2026-03-10 16:09:13 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2026-03-10 15:36:44 +0000 |
| commit | b19feb243f1f2bdb7f04e5c6f3b693ee8cd2a8b7 (patch) | |
| tree | 44c8b4434fffffde7b2a55f21a371b4f0a390ad3 /pkg | |
| parent | 9eee85817edcc7ad7e20ffadf0e43e1ba748cb35 (diff) | |
pkg/aflow: ensure we don't register MCP tools with duplicate names
If we have duplicate names, then only one of the duplicates will be used at random.
Add a check that we don't have duplicate names.
Currently it's only "crash-reproducer" (both action and a tool).
Also ignore "set-results" tool, and all tools created in tests.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/aflow/flow/flows_test.go | 14 | ||||
| -rw-r--r-- | pkg/aflow/flow_test.go | 5 | ||||
| -rw-r--r-- | pkg/aflow/llm_agent.go | 4 | ||||
| -rw-r--r-- | pkg/aflow/mcp.go | 19 | ||||
| -rw-r--r-- | pkg/aflow/tool/syzlang/reproduce.go | 2 |
5 files changed, 40 insertions, 4 deletions
diff --git a/pkg/aflow/flow/flows_test.go b/pkg/aflow/flow/flows_test.go index 3c01596b5..a66479d14 100644 --- a/pkg/aflow/flow/flows_test.go +++ b/pkg/aflow/flow/flows_test.go @@ -3,4 +3,16 @@ package flow -// An empty test that runs registration and verification of all registered workflows via init functions. +import ( + "testing" + + "github.com/google/syzkaller/pkg/aflow" +) + +// Note: this test also runs registration and verification of all registered workflows via init functions. + +func TestMCPTools(t *testing.T) { + for tool := range aflow.MCPTools { + t.Log(tool.Name) + } +} diff --git a/pkg/aflow/flow_test.go b/pkg/aflow/flow_test.go index 734781c41..94758c549 100644 --- a/pkg/aflow/flow_test.go +++ b/pkg/aflow/flow_test.go @@ -15,6 +15,11 @@ import ( "google.golang.org/genai" ) +func init() { + // Tests register tools with duplicate names. + registerMCPTools = false +} + func TestWorkflow(t *testing.T) { type flowInputs struct { InFoo int diff --git a/pkg/aflow/llm_agent.go b/pkg/aflow/llm_agent.go index 378f044a5..3529fa5b1 100644 --- a/pkg/aflow/llm_agent.go +++ b/pkg/aflow/llm_agent.go @@ -108,7 +108,7 @@ func Tools(tools ...any) []Tool { // LLMOutputs creates a special tool that can be used by LLM to provide structured outputs. func LLMOutputs[Args any]() *llmOutputs { return &llmOutputs{ - tool: NewFuncTool("set-results", func(ctx *Context, state struct{}, args Args) (Args, error) { + tool: NewFuncTool(llmSetResultsTool, func(ctx *Context, state struct{}, args Args) (Args, error) { return args, nil }, "Use this tool to provide results of the analysis."), provideOutputs: func(ctx *verifyContext, who string, many bool) { @@ -129,6 +129,8 @@ func LLMOutputs[Args any]() *llmOutputs { } } +const llmSetResultsTool = "set-results" + const llmOutputsInstruction = ` Use set-results tool to provide results of the analysis. diff --git a/pkg/aflow/mcp.go b/pkg/aflow/mcp.go index f94376113..5e0944e08 100644 --- a/pkg/aflow/mcp.go +++ b/pkg/aflow/mcp.go @@ -6,6 +6,7 @@ package aflow import ( "context" "errors" + "fmt" "time" "github.com/google/syzkaller/pkg/aflow/trajectory" @@ -51,7 +52,7 @@ func registerMCPTool[State, Args, Results any](t *funcTool[State, Args, Results] } return reply, nil } - MCPTools[tool] = handler + registerMCP(tool, handler) } func registerMCPAction[Args, Results any](a *funcAction[Args, Results]) { @@ -68,5 +69,21 @@ func registerMCPAction[Args, Results any](a *funcAction[Args, Results]) { } return reply, err } + registerMCP(tool, handler) +} + +var ( + registerMCPTools = true + mcpToolNames = map[string]bool{} +) + +func registerMCP(tool *mcp.Tool, handler MCPToolFunc) { + if !registerMCPTools || tool.Name == llmSetResultsTool { + return + } + if mcpToolNames[tool.Name] { + panic(fmt.Sprintf("MCP tool %q is already registered", tool.Name)) + } + mcpToolNames[tool.Name] = true MCPTools[tool] = handler } diff --git a/pkg/aflow/tool/syzlang/reproduce.go b/pkg/aflow/tool/syzlang/reproduce.go index 3faa11563..2c22bddd9 100644 --- a/pkg/aflow/tool/syzlang/reproduce.go +++ b/pkg/aflow/tool/syzlang/reproduce.go @@ -9,7 +9,7 @@ import ( _ "github.com/google/syzkaller/sys" ) -var Reproduce = aflow.NewFuncTool("crash-reproducer", reproduce, ` +var Reproduce = aflow.NewFuncTool("reproduce-crash", reproduce, ` Tool evaluates whether the given syz repro program crashes the kernel. It will compile the program and execute it in a VM. `) |
