From 034acda23cabda0268125d88bdbdec0ba592798c Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Mon, 26 May 2025 22:00:24 -0700 Subject: [PATCH] Toolbox configuration docs, closes #1057 --- docs/tools.md | 2 ++ docs/usage.md | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/docs/tools.md b/docs/tools.md index 0258121..f9910e5 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -68,6 +68,8 @@ In LLM every tool is a defined as a Python function. The function can take any n Tool functions should include a docstring that describes what the function does. This docstring will become the description that is passed to the model. +Tools can also be defined as {ref}`toolbox classes `, a subclass of `llm.Toolbox` that allows multiple related tools to be bundled together. Toolbox classes can be be configured when they are instantiated, and can also maintain state in between multiple tool calls. + The Python API can accept functions directly. The command-line interface has two ways for tools to be defined: via plugins that implement the {ref}`register_tools() plugin hook `, or directly on the command-line using the `--functions` argument to specify a block of Python code defining one or more functions - or a path to a Python file containing the same. You can use tools {ref}`with the LLM command-line tool ` or {ref}`with the Python API `. diff --git a/docs/usage.md b/docs/usage.md index dc03321..2af3372 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -193,6 +193,20 @@ Tool call: simple_eval({'expression': '914394150 / 123'}) 7434098.780487805 914,394,150 divided by 123 is approximately 7,434,098.78. ``` +Some tools are bundled in a configurable collection of tools called a **toolbox**. This means a single `--tool` option can load multiple related tools. + +[llm-tools-datasette](https://github.com/simonw/llm-tools-datasette) is one example. Using a toolbox looks like this: + +```bash +llm install llm-tools-datasette +llm -T 'Datasette("https://datasette.io/content")' "Show tables" --td +``` +Toolboxes always start with a capital letter. They can be configured by passing a tool specification, which should fit the following patterns: + +- Empty: `ToolboxName` or `ToolboxName()` - has no configuration arguments +- JSON object: `ToolboxName({"key": "value", "other": 42})` +- Single JSON value: `ToolboxName("hello")` or `ToolboxName([1,2,3])` +- Key-value pairs: `ToolboxName(name="test", count=5, items=[1,2])` - treated the same as `{"name": "test", "count": 5, "items": [1, 2]}`, all values must be valid JSON (usage-extract-fenced-code)= ### Extracting fenced code blocks