llm_tool_generator 0.8.0
llm_tool_generator: ^0.8.0 copied to clipboard
Code generator for llm_tool. Turns @LlmTool-annotated Dart functions into LLM tools for OpenAI, Gemini, Claude and MCP, with JSON schemas and validation.
llm_tool_generator #
The code generator for llm_tool:
turn any Dart function into an LLM tool with one annotation. No hand-written JSON schemas.
For every @LlmTool() function it generates a ToolDefinition with the JSON
Schema for the LLM, argument validation and type-safe dispatch.
The full documentation, including supported types, limits, validation and
errors, and how to send tools to OpenAI, Claude, Gemini or MCP, is in the
llm_tool README.
Quick start #
1. Install
dart pub add llm_tool dev:llm_tool_generator dev:build_runner
2. Write a tool
import 'package:llm_tool/llm_tool.dart';
part 'tools.g.dart';
/// Gets the current weather for a city.
@LlmTool()
String getWeather(
@Param('City name, e.g. Kanpur') String city, {
@Param('Use Celsius instead of Fahrenheit') bool celsius = true,
}) => 'Sunny, ${celsius ? '31°C' : '88°F'} in $city';
3. Generate
dart run build_runner build
4. Use the generated getWeatherTool
print(getWeatherTool.parametersSchema); // send to your LLM
print(await getWeatherTool({'city': 'Kanpur'})); // Sunny, 31°C in Kanpur
What gets generated #
final getWeatherTool = ToolDefinition(
name: "getWeather",
description: "Gets the current weather for a city.",
parametersSchema: {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. Kanpur"},
"celsius": {
"type": "boolean",
"description": "Use Celsius instead of Fahrenheit",
},
},
"required": ["city"],
"additionalProperties": false,
},
requiresConfirmation: false,
execute: (args) => getWeather(
args["city"] as String,
celsius: args["celsius"] as bool? ?? true,
),
);
/// Every tool in this file, e.g. to send to an LLM or look up by name.
/// Typed by the tools' common return type, so calling one needs no cast.
final allTools = [getWeatherTool];
The list is named after the file: tools.dart gives allTools,
weather_tools.dart gives weatherTools.
For a class marked @LlmToolset(), its @LlmTool methods are generated
into an extension, bound to the instance they're called on:
@LlmToolset()
class WeatherTools {
WeatherTools(this._api);
final WeatherApi _api;
/// Gets the current weather for a city.
@LlmTool()
Future<String> getWeather(@Param('City name') String city) =>
_api.current(city);
}
// Generated:
extension WeatherToolsLlmTools on WeatherTools {
List<ToolDefinition<String>> get llmTools => [
ToolDefinition(
name: "getWeather",
// ...
execute: (args) => getWeather(args["city"] as String),
),
];
}
// Use it:
final tools = WeatherTools(api).llmTools;
Supported #
- Top-level functions, and instance or static methods of
@LlmToolset()classes (generated as anllmToolsgetter): sync, async (Future<T>) andvoid. String,int,double,num,bool, enum, class andListparameters (lists of any of these, including nested lists): positional or named, nullable or not, with or without defaults.- Descriptions from
@LlmTool(description: ...)or the doc comment. - Custom JSON names with
@Param('...', name: 'game_id'), so your Dart code keeps camelCase while the LLM sees snake case. - Limits with
@Param('...', min: 0, max: 130),minLength,maxLength,pattern,minItemsandmaxItems. See Limits. - Class parameters become nested object schemas, built through the class's unnamed constructor. freezed classes work too. See Class parameters.
Anything else is a build-time error with a message explaining the fix:
unsupported types, missing descriptions, tool names that LLM providers would
reject, generic functions, limits that don't fit the type, and @LlmTool on
methods of a class without @LlmToolset().
Troubleshooting #
Undefined name 'getWeatherTool': add part 'your_file.g.dart'; and run
dart run build_runner build. A @LlmTool method needs @LlmToolset() on its
class; without it, in a file with no other top-level annotation, the method is
skipped without a message.
The name 'ToolDefinition' is defined in the libraries ...: another
package (e.g. flutter_ai_core) also has a ToolDefinition. Import
llm_tool with a prefix (as ltc) and use @ltc.LlmTool(); the
generated code follows your prefix.
Conflicting outputs were detected: run
dart run build_runner build --delete-conflicting-outputs.
More in the full troubleshooting guide.
Author #
Built and maintained by Amit Gupta. Bug reports, ideas and pull requests are welcome on GitHub. If this package saves you time, a like on pub.dev or a star on GitHub helps others find it.