function_test.go
Overview
The function_test.go file contains unit and example tests for the Function Tool functionality within the system. It verifies the ability of the functiontool package to wrap native Go functions as tools that can be invoked by an AI agent or large language model (LLM). The tests cover creation, execution, JSON schema customization, input/output handling, error cases, and integration with Gemini-based LLM models.
This file ensures that function tools correctly:
Infer JSON schemas from Go function signatures.
Process LLM requests by embedding function declarations.
Deserialize LLM function call arguments.
Execute wrapped Go functions and return typed results.
Handle primitive and complex return types.
Consolidate multiple function declarations into a single GenAI tool.
Support custom input JSON schemas with validation and enums.
Interact with the Gemini LLM model for generating content and function calls.
The tests simulate real-world usage scenarios of function tools in the context of an LLM-driven agent workflow, validating their behavior end-to-end.
Detailed Explanations
ExampleNew()
A concise usage example demonstrating how to create a simple sum function tool.
func ExampleNew()
Purpose: Showcases how to define a function tool wrapping a Go function that sums two integers.
Details:
Defines argument (
SumArgs) and result (SumResult) structs with JSON tags.Implements a handler function adding
AandB.Calls
functiontool.New()with the handler and config (name, description).Panics if an error occurs during tool creation.
Usage: Illustrates minimal code for creating a
functiontool.Toolwith automatic schema inference.
TestFunctionTool_Simple()
func TestFunctionTool_Simple(t *testing.T)
Purpose: Tests a function tool for retrieving weather reports by city name, integrated with a Gemini LLM model.
Details:
Defines input (
Args) and output (Result) types.Creates an in-memory result set mapping cities to weather reports.
Implements a handler that returns the corresponding report or an error if city data is unavailable.
Creates a function tool with
functiontool.New().Initializes a Gemini model client with HTTP replay for deterministic testing.
For each test case (london, paris, new york), sends prompts to the LLM.
Extracts and verifies the function call generated by the LLM.
Runs the function tool with the parsed arguments.
Compares actual results against expected using
cmp.Diff.
Key Points:
Verifies JSON schema inference, argument unmarshaling, and function execution.
Validates error handling for unknown city input.
Demonstrates integration with LLM request processing and response consumption.
Usage Example:
This test mimics an agent workflow calling a function tool via LLM function call.
TestFunctionTool_DifferentFunctionDeclarations_ConsolidatedInOneGenAiTool()
func TestFunctionTool_DifferentFunctionDeclarations_ConsolidatedInOneGenAiTool(t *testing.T)
Purpose: Ensures multiple function tools with different signatures are consolidated into a single GenAI tool in the LLM request configuration.
Details:
Defines two separate function tools: one for identity on
int, another onstring.Processes both tools to modify the same LLM request (
model.LLMRequest).Checks that the resulting request contains exactly one tool entry.
Validates that the tool has two function declarations (one for each wrapped function).
Key Points:
Confirms that the system merges multiple function declarations under one tool in LLM config.
Prevents duplicate tool entries and supports multiple function signatures.
Usage: Useful when different functions are exposed as variants of a single tool in the agent.
TestFunctionTool_ReturnsBasicType()
func TestFunctionTool_ReturnsBasicType(t *testing.T)
Purpose: Tests function tools returning primitive types (string) instead of structs.
Details:
Inputs: city name in a struct.
Outputs: plain string (weather report) instead of structured result.
The handler returns a string or a message for unknown city.
Creates the function tool with name and description.
For each test case, processes the request and calls the tool's
Runmethod.Converts the raw output map to a typed map and verifies the
"result"key matches expected string.
Key Points:
Verifies function tool correctly wraps primitive results by mapping to
{"result": value}.Confirms seamless support for simple return types.
Usage: Supports lightweight tools where a full result struct is unnecessary.
TestFunctionTool_CustomSchema()
func TestFunctionTool_CustomSchema(t *testing.T)
Purpose: Validates support for custom input JSON schemas with descriptions and enumerations.
Details:
Defines input struct
Argswith aFruitfield.Generates a JSON schema for
Argsviajsonschema.For.Modifies schema to add description and restrict enum values (
mandarin,kiwi).Creates a function tool with the custom input schema.
The handler verifies that the fruit argument is one of the enumerated values.
Runs subtests for:
Valid fruit input.
Invalid fruit string input.
Wrong type input.
Nil input.
For each, calls the tool’s
Runand verifies error presence or absence.Also tests that the tool correctly injects the function declaration into LLM request, matching the custom schema.
Key Points:
Shows how to override default inferred schemas to add validation constraints.
Ensures input validation enforces enum restrictions.
Usage: Enables tighter control over function tool inputs, improving robustness.
Helper Functions
newGeminiTestClientConfig()
func newGeminiTestClientConfig(t *testing.T, rrfile string) *genai.ClientConfig
Returns a Gemini client config using HTTP record/replay transport for test determinism.
Sets a fake API key during replay to avoid real network calls.
Used in tests that require Gemini model interaction.
readFirstResponseT any
func readFirstResponse[T any](s iter.Seq2[*model.LLMResponse, error]) (T, error)
Generic function to extract the first relevant response of type
Tfrom a sequence of LLM responses.Supports types: string, *genai.FunctionCall, *genai.FunctionResponse.
Returns error if no suitable content is found.
Used to parse LLM generation output in tests.
toolDeclaration()
func toolDeclaration(cfg *genai.GenerateContentConfig) *genai.FunctionDeclaration
Helper to extract the first function declaration from the first tool in the LLM request config.
Returns nil if no declarations exist.
stringify()
func stringify(v any) string
JSON marshals and indents a value to a string.
Used for comparing JSON schema objects in tests.
Important Implementation Details
The function tools are created via
functiontool.New()by supplying:A config (name, description, optional custom schemas).
A Go function handler of signature:
func(tool.Context, TArgs) (TResults, error).
The system automatically infers input and output JSON schemas using the
jsonschemapackage.Function tools implement interfaces such as
toolinternal.RequestProcessorandtoolinternal.FunctionToolto integrate with LLM request lifecycle and function calling.The tests simulate the full cycle of:
Processing an LLM request to embed function declarations.
Receiving a function call from the LLM.
Running the wrapped Go function with deserialized arguments.
Returning results serialized back as JSON maps.
Tests use HTTP record/replay (
httprr) to simulate Gemini API responses for deterministic testing.The system supports consolidating multiple function declarations into a single GenAI tool (important for LLM tooling compatibility).
Custom schemas allow adding validation constraints like enums and descriptions.
Primitive return types are wrapped as
{"result": value}in the JSON output to satisfy function call response requirements.Tests verify error handling, including unknown inputs and type mismatches.
File Interaction with Other Components
Imports
functiontoolpackage to create and test function tools.Uses
geminipackage to instantiate Gemini LLM model clients for integration tests.Interacts with
model.LLMRequestandgenai.GenerateContentConfigfor configuring LLM requests.Uses internal packages such as
toolinternalfor interfaces (RequestProcessor,FunctionTool).Uses
typeutil.ConvertToWithJSONSchemafor converting arbitrary JSON map outputs into typed Go structs.Employs
httprrandtestutilto implement HTTP record and replay for Gemini API calls.Utilizes
cmppackage to compare expected and actual test results.The test file validates how function tools interact with agents and LLMs as part of the broader Tooling System and Function Tools.
Visual Diagram
flowchart TD
A[Create Function Tool] --> B[Infer JSON Schemas]
B --> C[ProcessRequest embeds function declaration in LLMRequest]
C --> D[Send LLMRequest to Gemini Model]
D --> E[LLM generates content with FunctionCall]
E --> F[Extract FunctionCall from LLM response]
F --> G[FunctionTool.Run deserializes arguments]
G --> H[Invoke wrapped Go function handler]
H --> I[Return result or error]
I --> J[Serialize output to JSON map]
J --> K[Return result to agent and LLM]
K --> L[Agent appends results and continues]
subgraph Test Scenarios
M[TestFunctionTool_Simple]
N[TestFunctionTool_DifferentFunctionDeclarations]
O[TestFunctionTool_ReturnsBasicType]
P[TestFunctionTool_CustomSchema]
end
M -.-> A
N -.-> A
O -.-> A
P -.-> A
This flowchart illustrates the lifecycle of a function tool within the test scenarios, highlighting creation, schema inference, request processing, LLM interaction, function invocation, and result serialization.
Usage Summary
Developers define Go functions with typed inputs and outputs.
Wrap those functions into tools using
functiontool.New().The system automatically generates JSON schemas and exposes these via the LLM request config.
During runtime, the LLM generates function calls, which the agent routes to the corresponding function tool.
The tool deserializes input, runs the Go function, and serializes the output.
Test coverage verifies this entire workflow with various function signatures, return types, error conditions, and schema customizations.
This file is essential for validating the robustness and correctness of function tool integration within the AI agent tooling framework. It ensures that native Go logic can be safely and effectively exposed as callable tools for LLM-driven agents.
Relevant Topics
Function Tools — for detailed concepts on wrapping Go functions as tools.
Tooling System — for understanding the overall modular tool framework.
LLM Integration and Agents — for how tools interact with LLM requests and agent workflows.
Instruction Template Processing — related to how function tool declarations are injected into prompts and LLM requests.