From c688ce130414b10af92c1cfd7372216896c3c45a Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Wed, 4 Nov 2026 22:56:54 +0000 Subject: Allow custom tools. --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ bin/kaagum | 7 +++++++ 2 files changed, 55 insertions(+) diff --git a/README.md b/README.md index 045598c..67a3ad2 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,54 @@ Install the `kaagum` and `emacs-agent-shell-kaagum` packages from Guix. Then, pu ``` Change to the directory you want to work in. kaagum will only have access to that directory and its contents. Run `M-x agent-shell` and select `kaagum` from the menu. +# Using custom tools with kaagum + +kaagum empowers you to equip your agents with custom tools specific to your needs. To do this, you write a scheme file (let's call it `custom-tools.scm`) that defines your custom tools. Then, you pass that file on to kaagum using the `--more-tools=custom-tools.scm` parameter. + +What should your custom tools file look like? Here's an example: +```scheme +(use-modules (kaagum tools)) + +(define %string-length + (tool #:description "Compute the length of a string." + #:parameters `(("str" . ,(tool-parameter + #:type "string" + #:description "String whose length to compute" + #:required? #t))) + #:proc (lambda* (#:key str) + (format #t "~a~%" (string-length str))) + #:title (lambda* (#:key str) + (format #f "string-length ~s" str)) + #:kind "other")) + +`(("string-length" . ,%string-length)) +``` +The file must return an association list mapping tool names to definitions (`` objects) as its final expression. + +`` objects are defined using `tool` from `(kaagum tools)`. `tool` takes the following keyword arguments: +- **description:** string that describes the tool; this is read by the LLM to decide whether and how to use the tool—make it a detailed documentation of the tool and the parameters that it takes. +- **parameters:** association list mapping tool parameter names to `` objects. +- **proc:** the actual function run if the tool is executed; parameters are passed to it as keyword arguments, and output must be written to standard output +- **title:** human-readable string describing what the tool is doing; this is used by the ACP client in its UI +- **kind:** category of tool—one of `"read"`, `"edit"`, `"delete"`, `"move"`, `"search"`, `"execute"`, `"think"`, `"fetch"`, `"switch_mode"`, or `"other"`; this is also used by the ACP client in its UI +- **container-mappings:** list of Guix `` objects representing file system paths to mount into the container of the tool call process +- **container-namespaces:** list of namespaces to create for the container—should be like `%namespaces` from Guix's `(gnu build linux-container)` + +`` objects are defined using `tool-parameter` from `(kaagum tools)`. tool-parameter takes the following keyword arguments: +- **type:** parameter type—`"string"`, `"boolean"`, etc. +- **description:** string describing the tool parameter +- **required?:** `#t` if this parameter is required (that is, mandatory), else `#f`; if the parameter is not required, the default argument must be specified in the `lambda*` function in `#:proc` and `#:title`. + +See definitions of built-in tools under `kaagum/tools/*.scm` for examples. + +If your custom tools require other Guile packages or modules, you may provide access by setting the `GUILE_LOAD_PATH` and `GUILE_LOAD_COMPILED_PATH` environment variables. If you're using Emacs agent shell, you can do this by setting the `agent-shell-kaagum-environment` variable. +```elisp +(setq agent-shell-kaagum-environment + (agent-shell-make-environment-variables + "GUILE_LOAD_PATH" "/some/path/" + "GUILE_LOAD_COMPILED_PATH" "/some/path/")) +``` + # Contributing Please report issues or send patches to the public inbox at [kaagum@systemreboot.net](https://lists.systemreboot.net/kaagum/). diff --git a/bin/kaagum b/bin/kaagum index 75e837f..2c8c9ee 100755 --- a/bin/kaagum +++ b/bin/kaagum @@ -50,6 +50,9 @@ exec guile --no-auto-compile -e main -s "$0" "$@" (option (list #\k "api-key-command") #t #f (lambda (opt name arg result) (acons 'api-key-command arg result))) + (option (list #\t "more-tools") #t #f + (lambda (opt name arg result) + (acons 'more-tools arg result))) (option (list "kagi-api-key-command") #t #f (lambda (opt name arg result) (acons 'kagi-api-key-command arg result))) @@ -75,6 +78,7 @@ Run kaagum AI agent. -k, --api-key-command=COMMAND command to run to get API key -m, --model=MODEL LLM model name to start new sessions with (default: \"anthropic/claude-opus-4.8\") + -t, --more-tools=FILE scheme file providing more tools to the agent --kagi-api-key-command=COMMAND command to run to get Kagi API key @@ -128,6 +132,9 @@ Run kaagum AI agent. %forge-tools (if kagi-api-key-command %kagi-tools + '()) + (if (assq-ref args 'more-tools) + (load (assq-ref args 'more-tools)) '()))))) (parameterize ((%kagi-api-key (and kagi-api-key-command (get-api-key kagi-api-key-command)))) -- cgit 1.4.1