Any Go function can become a tool the FrostAgent engine hands to the LLM. At each reasoning iteration, the engine passes all registered tool definitions to the model, which decides autonomously whether and when to invoke one. The result is fed back into the conversation and the loop continues until the model produces a final text response or the iteration limit is reached.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/GuaiZai233/FrostAgent/llms.txt
Use this file to discover all available pages before exploring further.
Tool anatomy
Every tool is a value of thetools.Tool struct defined in internal/tools/tools.go:
| Field | Purpose |
|---|---|
name | Unique identifier the LLM uses when requesting a call |
description | Natural-language explanation of what the tool does — the LLM reads this to decide when to call it |
parameter | A map[string]any encoding a JSON Schema object that describes the expected arguments |
execute | The Go function that runs when the LLM calls the tool; receives JSON-encoded arguments, returns a plain-text result |
Name(), Description(), Parameters(), and Execute() — which satisfy the llm.ToolExecutor interface used by the engine’s run loop.
Step-by-step: building a custom tool
Define the execute function
Write a function that accepts a JSON string of arguments and returns a string result. Parse the JSON into a typed struct and validate the inputs before doing any work.The built-in weather tool (
internal/tools/weather.go) follows exactly this pattern:Return a Tool from a constructor function
Wrap the execute closure inside a
Tool struct and return it from a constructor. This is the pattern used across all built-in tools (GetWeatherTool, GetGameVersionTool, SendMsgTool).Write the JSON Schema parameters
The The top-level object is always
parameter field must be a map[string]any that follows JSON Schema conventions. The LLM reads this schema to understand what arguments to pass. A minimal single-string parameter looks like:type: object. Individual properties each have their own type and description. List every mandatory field in required.Register the tool in main.go
Open Because
cmd/app/main.go and add your constructor call alongside the existing tool registrations inside the init() function. The engine uses two maps: registry stores the full Tool metadata (for listing to the LLM), and executorMap stores the same values cast to the llm.ToolExecutor interface (for execution).tools.Tool implements every method required by llm.ToolExecutor (Name(), Description(), Parameters(), Execute()), no adapter code is needed.Test the tool
Start FrostAgent and send a message that should trigger your tool. The engine logs each tool invocation and its result — look for log lines prefixed with
【智能体调用工具】 and 【工具执行结果】 to confirm the LLM called your tool with the expected arguments and that the execute function returned the right output.The LLM decides when to call a tool based on the conversation context, the tool description, and the parameter schema. If the tool is not being invoked, revisit the description to make the trigger conditions clearer.Complete example: get_current_time
Below is the full file ready to drop into internal/tools/time.go:
main.go:
JSON Schema tips
Theparameter map is serialised and forwarded to the LLM exactly as written. Use standard JSON Schema conventions:
String parameter
type to "object", wrap all parameters under properties, and list every required argument in the required array.
Error handling
Execute returns (string, error). When the execute function returns a non-nil error, the engine formats it as "工具执行失败: <err>" and sends that string back to the LLM as the tool result. The LLM can then decide to retry with different arguments, call a different tool, or report the failure to the user.
Good practice:
- Validate all required fields immediately after unmarshalling and return a descriptive
errorif any are missing or invalid. - Wrap external errors with
fmt.Errorf("...: %w", err)so context is preserved in logs. - Return structured text on success — for example, JSON or a short sentence — so the LLM can parse or relay it accurately.