Skip to content

[Bug] llmagent is only compatible with functiontool where input is a struct #330

@yarolegovich

Description

@yarolegovich

Problem

functiontool can be used in contexts other than llmagent so any Type parameter constraints make sense:

type Func[TArgs, TResults any] func(tool.Context, TArgs) (TResults, error)

But llmagent is incompatible with functiontools where input is a non-struct type, because genai.FunctionCall.Args is a map:

Args map[string]any `json:"args,omitempty"`

The result is that an agent can never succeed in calling such tool.

Desired behavior

One of:

  1. Validate tools in llmagent.New and report tool incompatibility as an error.
  2. Make llmagent wrap such tools in a special decorator which will be handling unboxing of llm-provided arguments of form like map[string]any{"input": arg}. It will need to override input schema as well.

Reproduction

The agent will never succeed in running the super_tool:

func main() {
	ctx := context.Background()

	model, err := gemini.NewModel(ctx, "gemini-2.5-flash", &genai.ClientConfig{
		APIKey: os.Getenv("GOOGLE_API_KEY"),
	})
	if err != nil {
		log.Fatalf("Failed to create model: %v", err)
	}

	superTool, err := functiontool.New(functiontool.Config{Name: "super_tool"}, functiontool.Func[string, string](
		func(ctx tool.Context, input string) (string, error) {
			return "Hello", nil
		},
	))
	if err != nil {
		log.Fatalf("Failed to create a tool: %v", err)
	}

	a, err := llmagent.New(llmagent.Config{
		Name:        "super_tool_caller",
		Model:       model,
		Description: "Agent to invoke the super_tool",
		Instruction: "Your SOLE purpose is to invoke the super_tool and pass the result to me.",
		Tools:       []tool.Tool{superTool},
	})
	if err != nil {
		log.Fatalf("Failed to create agent: %v", err)
	}

	l := full.NewLauncher()
	if err = l.Execute(ctx, &launcher.Config{AgentLoader: agent.NewSingleLoader(a)}, os.Args[1:]); err != nil {
		log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax())
	}
}

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