function.go
Overview
The function.go file, part of the functiontool package, implements a generic Function Tool that wraps arbitrary Go functions as callable tools within an AI agent framework. It provides a mechanism to expose Go functions with typed inputs and outputs as tools that can be invoked by large language models (LLMs) or agents. The file emphasizes automatic JSON schema inference for function arguments and results, seamless serialization and deserialization, and integration with the tool lifecycle and LLM function calling mechanisms.
This file enables developers to easily create tools by wrapping Go functions without manual schema definition, facilitating robust, type-safe, and schema-validated function calls from agents or LLMs.
Key Components
Config struct
type Config struct {
Name string
Description string
InputSchema *jsonschema.Schema
OutputSchema *jsonschema.Schema
IsLongRunning bool
}
Purpose: Configuration input to create a new function tool.
Fields:
Name: Identifier for the tool.Description: Human-readable description of the tool.InputSchema: Optional override for the JSON schema of input arguments. Ifnil, inferred automatically.OutputSchema: Optional override for the JSON schema of output results. Ifnil, inferred automatically.IsLongRunning: Indicates if the tool represents a long-running operation.
Func Type
type Func[TArgs, TResults any] func(tool.Context, TArgs) (TResults, error)
Purpose: Defines the signature for Go functions wrapped by the tool.
Parameters:
tool.Context: Provides runtime context for the tool invocation.TArgs: Generic type representing the input argument structure.
Returns:
TResults: Generic type representing the output result structure.error: Execution error, if any.
New Function
func New[TArgs, TResults any](cfg Config, handler Func[TArgs, TResults]) (tool.Tool, error)
Purpose: Constructs a new function tool instance by wrapping a Go function handler.
Parameters:
cfg: Configuration struct with tool metadata and optional schemas.handler: The Go function to wrap, matching theFuncsignature.
Return:
Returns a
tool.Toolinterface implementation wrapping the provided function.Returns an error if schema inference or resolution fails.
Behavior:
Infers JSON schemas for input and output types if not supplied.
Creates a
functionToolinstance holding config, schemas, and handler.
Usage Example:
sumTool, err := functiontool.New(functiontool.Config{ Name: "sum", Description: "Sums two integers", }, func(ctx tool.Context, args SumArgs) (SumResult, error) { return SumResult{Sum: args.A + args.B}, nil })
functionTool Struct
type functionTool[TArgs, TResults any] struct {
cfg Config
inputSchema *jsonschema.Resolved
outputSchema *jsonschema.Resolved
handler Func[TArgs, TResults]
}
Purpose: Internal implementation of the
tool.Toolinterface that wraps the Go function.Fields:
cfg: Configuration data.inputSchema: Resolved JSON schema for input arguments.outputSchema: Resolved JSON schema for output results.handler: The wrapped Go function.
Methods Implementing tool.Tool Interface
Name() string
Returns the tool's name from config.Description() string
Returns the tool's description from config.IsLongRunning() bool
Returns whether the tool is marked as long-running.ProcessRequest(ctx tool.Context, req *model.LLMRequest) error
Packs the function tool’s declaration into the LLM request viatoolutils.PackTool.Declaration() *genai.FunctionDeclaration
Constructs aFunctionDeclarationobject for LLM integration that includes:Name and description
Input parameters JSON schema
Output response JSON schema
A note appended in the description if the tool is long-running
Run Method
func (f *functionTool[TArgs, TResults]) Run(ctx tool.Context, args any) (map[string]any, error)
Purpose: Executes the wrapped Go function with deserialized input and returns serialized output.
Parameters:
ctx: Invocation context.args: Raw input arguments, expected asmap[string]any.
Returns:
map[string]any: Serialized output suitable for LLM consumption.error: If input deserialization, function execution, or output serialization fails.
Implementation Details:
Validates that
argsis amap[string]any.Converts raw map input to typed
TArgsusing JSON schema (typeutil.ConvertToWithJSONSchema).Calls the wrapped function handler.
Converts the output
TResultsback tomap[string]anyfor LLM.If output schema validation fails or output is a primitive (non-map), wraps it in
{"result": output}to comply with LLM function call response expectations.
Example Behavior:
If the function returns a simple string or number, the result is wrapped as
{"result": <value>}.If the output schema exists, output is validated against it before returning.
Error Handling:
Returns descriptive errors for unexpected input types or conversion failures.
Propagates errors from the wrapped function.
resolvedSchema Helper Function
func resolvedSchema[T any](override *jsonschema.Schema) (*jsonschema.Resolved, error)
Purpose: Resolves or infers a JSON schema for a given generic type
T.Parameters:
override: Optional JSON schema override.
Returns:
A resolved JSON schema object.
Error if schema inference or resolution fails.
Implementation Detail:
If an override is provided, resolves that schema.
Otherwise, uses
jsonschema.ForTto infer schema from Go typeT.
Note: There is a TODO to check compatibility between override schema and generic type
T.
Important Implementation Details
The tool leverages Go generics to strongly type function inputs and outputs.
Automatic JSON schema inference simplifies developer experience by avoiding manual schema specification.
Input and output are serialized/deserialized using JSON schemas, ensuring type safety and validation.
The tool supports marking operations as "long-running," which modifies the function declaration's description for LLM awareness.
Output normalization wraps primitive types in an object with a
"result"key to satisfy function call response protocols.The tool integrates with the LLM request lifecycle by embedding function declarations that define callable functions for the LLM.
Error handling ensures that invalid input types or schema mismatches are surfaced clearly.
The design intentionally diverges from MCP (Model Context Protocol) tooling to provide a simpler, function-centric interface without exposing session internals.
Interaction with Other System Components
Implements the
tool.Toolinterface defined in the broader Tooling System, enabling consistent tool behavior alongside artifact loaders, search tools, and others.Uses
tool.Contextas the execution context, which provides agent invocation data and environment.Integrates with LLM request generation by packing the function declaration schema into the request via
ProcessRequest.Upon LLM function call invocation, the agent calls
Run()with the function arguments, executing the underlying Go function and returning results.Utilizes
jsonschema-gofor JSON schema generation and validation.Uses utility functions in
typeutilandtoolutilsfor schema-aware conversion and request packing.Supports both synchronous and long-running function invocations, informing LLMs and agents accordingly.
Enables dynamic extension of agents’ capabilities by exposing arbitrary Go functions as tools callable by LLMs or agents.
Usage Example
type AddArgs struct {
X int `json:"x"`
Y int `json:"y"`
}
type AddResult struct {
Sum int `json:"sum"`
}
addHandler := func(ctx tool.Context, args AddArgs) (AddResult, error) {
return AddResult{Sum: args.X + args.Y}, nil
}
addTool, err := functiontool.New(functiontool.Config{
Name: "add",
Description: "Adds two integers",
}, addHandler)
if err != nil {
// handle error
}
This example creates a tool named "add" that sums two integers. The input and output JSON schemas are automatically generated from the AddArgs and AddResult types.
Visual Diagram
classDiagram
class functionTool {
+Name()
+Description()
+IsLongRunning()
+ProcessRequest()
+Declaration()
+Run()
}
functionTool --> Config
functionTool --> Func
functionTool --> jsonschema.Resolved
Config : +Name
Config : +Description
Config : +InputSchema
Config : +OutputSchema
Config : +IsLongRunning
Func : +func(tool.Context, TArgs) (TResults, error)
Workflow Summary
sequenceDiagram
participant Agent
participant LLM
participant FunctionTool
participant GoFunction
Agent->>LLM: Embed FunctionDeclaration with schemas
LLM->>Agent: Generate content (may include FunctionCall)
Agent->>FunctionTool: Run(args as map)
FunctionTool->>GoFunction: Deserialize args and execute
GoFunction-->>FunctionTool: Return result or error
FunctionTool-->>Agent: Serialize result map
Agent->>LLM: Provide function call result
This sequence shows how the function tool integrates with the agent and LLM:
The agent embeds the function's declaration into the LLM request.
The LLM may issue a function call with arguments.
The function tool deserializes arguments, runs the Go function, and returns the serialized result.
The agent forwards the function call result back to the LLM.
References to Related Topics
For details on the overall modular tool framework and how tools integrate into agents and LLMs, see Tooling System.
For the broader context of LLM integration and function calling workflows, refer to LLM Integration and Agents.
For the generic types and context interfaces used here, see Agent Invocation Context.
For JSON schema inference and validation mechanisms, see the jsonschema-go package.
For utility functions handling schema-based conversions and request packing, see toolutils and typeutil.
For comparison and design rationale, MCP tool integration is discussed in MCP Toolset Integration.
This documentation covers the purpose, structure, and usage of the function.go file that implements the generic Function Tool within the functiontool package, providing an extensible and type-safe bridge between Go functions and AI agent tooling.