Documentation
¶
Overview ¶
Package toolbundle builds one program from a set of tools: a binary whose commands are the tools, run through cli.Runner, and which writes the Agent Skill that teaches a model to call it. It is the way out for a host that allows no MCP server but gives the model a shell, a permission layer over shell commands and skills.
func main() {
os.Exit(toolbundle.Main(context.Background(), toolbundle.Bundle{
Name: "file-tools",
Description: "Read, search and edit files in the working tree. Use when …",
Tools: []toolbundle.Tool{
toolbundle.Use(ReadFile, toolbundle.PreApproved(),
toolbundle.Example("read_file --path go.mod", "Read a file")),
toolbundle.Use(WriteFile),
},
}, os.Args))
}
The tools need nothing to be bundled. What a tool needs to say about the bundle, whether its command is pre-approved, its examples, that it keeps state, is said where the bundle is built, with Use, and never on the tool.
One call is one process, so a tool that keeps state across calls, a persistent shell or a container session, loses it at exit. Such a tool is better left out of the bundle; export-skill warns about one that looks like it, unless Stateful says the author knows.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Main ¶
Main runs the program the bundle describes with args, the command line with the program's name first as in os.Args, and returns the exit status for os.Exit:
<name> export-skill [--force] <dir> <name> version <name> [--ask] <cli.Runner's command line>
export-skill writes the skill to <dir>/<name>/SKILL.md, and version prints the version. Anything else is one call of one tool, run by cli.Runner with the exit statuses it documents. --ask, given first, asks a person at the terminal any question a tool asks, through cli.Prompt; without it a question takes cli's protocol for a model: the call ends with cli.ExitNeedsAnswer and the question on stdout. A terminal does not say who is at it, so the default is the one that is safe for a model.
Before anything runs, Main refuses a bundle that could not export a valid skill, a tool named as one of the program's commands, and an example that does not parse, with cli.ExitUsage. It stops the call on an interrupt, and closes the tools when it is done with agenttool.Set.Close, whatever ran; a failed close is reported on stderr and leaves the exit status as it was, since the call has already happened.
Types ¶
type Bundle ¶
type Bundle struct {
// Name is the program's name, the name the binary is installed
// under, and the skill's name. It must be a valid skill name:
// lowercase letters, digits and hyphens, at most 64 characters,
// with no leading, trailing or doubled hyphen.
Name string
// Description is the skill's description: what the tools do and
// when to use them, which is what a model reads to choose the
// skill.
Description string
// Version is the program's version, printed by the version command
// and recorded in the skill's metadata. Empty, it is the main
// module's version from the build information.
Version string
// Tools are the program's commands, in the order the skill lists
// them.
Tools []Tool
}
Bundle is a set of tools as one program, and the skill that teaches a model to call it.
type Option ¶
type Option func(*Tool)
An Option says something about a tool in a bundle.
func Example ¶
Example adds a worked command line to the tool's section of the skill. args is what follows the program's name, the command first: "read_file --path go.mod". The program parses it against the command at startup and refuses to run if it does not parse, so an example cannot teach a flag that does not exist. An example gives its JSON argument inline, and quotes any word holding a character other than a letter, a digit or one of -_./:=,@+%.
func Hidden ¶
func Hidden() Option
Hidden leaves the tool out of the skill and out of help, for a maintenance command a model should not reach for. It stays runnable by name.
func PreApproved ¶
func PreApproved() Option
PreApproved lists the tool's command in the skill's allowed-tools, so a host that honours the field runs it without asking. It is the author's choice, made per tool, and never inferred from the tool's read-only hint: a hint may make a policy stricter and may not alone allow a call. export-skill prints every command it pre-approved.