Repository: google/adk-go
File: tool.go (Go)

Code before:
	// The event actions of the current tool call.
	EventActions []*EventAction
}

type ToolArgs[TArgs any] struct {
	Args        TArgs        `json:"arguments,omitempty"`
	ToolContext *ToolContext `json:"-"`
}

type ToolResults[TResults any] struct {
	Results TResults `json:"results,omitempty"`
}

// TODO: Implement an MCP client as a tool to validate whether
// a concrete type is sufficient for tool use.

// TODO: Validate the Tool representation for long running tools.
// Introduce LongRunningTool as an additional type if needed.

type Tool struct {
	Name        string
	Description string
	InputSchema *jsonschema.Schema
}

type Handler[TArgs, TResults any] func(context.Context, *ToolArgs[TArgs]) (*ToolResults[TResults], error)

func NewTool[TArgs, TResults any](name string, desc string, handler Handler[TArgs, TResults]) *Tool {
	panic("not implemented")
}


Review comment (suggestion):
Maybe I'm just used to how we do it in MCP, but there the "params," which includes some context like the progress token, are separate from access to the client (the `ServerSession`). I assume ToolContext contains both of those. (In MCP tools should have access to the client, so they can talk to the client-side LLM as part of their work.)
Maybe the best signature is
```
func(context.Context, tctx *ToolContext, args TArgs) ...
```
assuming ToolContext lets the tool talk to the client.

Code after:

	"github.com/google/adk-go/internal/jsonschema"
)

// ToolContext is the tool invocation context.
type ToolContext struct {
	// The invocation context of the tool call.
	InvocationContext *InvocationContext

	// The function call id of the current tool call.
	// This id was returned in the function call event from LLM to identify
	// a function call. If LLM didn't return an id, ADK will assign one t it.
	// This id is used to map function call response to the original function call.
	FunctionCallID string

	// The event actions of the current tool call.
	EventActions *EventActions
}

// TODO: Implement an MCP client as a tool to validate whether
// a concrete type is sufficient for tool use.

// Tool is an ADK tool.
type Tool struct {
	Name        string
	Description string
	InputSchema *jsonschema.Schema
	// TODO: OutputSchema

	rawHandler rawToolHandler
}

// Run executes the tool with the provided context and yields events.
func (t *Tool) Run(ctx context.Context, tc *ToolContext, args map[string]any) (map[string]any, error) {
	return t.rawHandler(ctx, tc, args)
}

// ToolHandler is the execution handler of a tool.
type ToolHandler[In, Out any] func(ctx context.Context, input In) (output Out, err error)

type rawToolHandler func(ctx context.Context, tc *ToolContext, args map[string]any) (map[string]any, error)

// NewTool creates a new tool with a name, description, and the provided handler.
// Input schema is automatically inferred from the input and output types.
func NewTool[In, Out any](name string, description string, handler ToolHandler[In, Out]) *Tool {
	// TODO(jbd): Add ToolOption as variadic arguments to NewTool.
	ischema, err := jsonschema.For[In]()
	if err != nil {
		panic(fmt.Errorf("NewTool(%q): %w", name, err))
	}
	rawHandler := func(ctx context.Context, tc *ToolContext, args map[string]any) (map[string]any, error) {