about summary refs log tree commit diff
diff options
context:
space:
mode:
authorArun Isaac2026-05-17 19:36:41 +0100
committerArun Isaac2026-05-17 23:10:17 +0100
commita47a9e899383fba7e3488ae9d494af9caf0492fa (patch)
tree7c71412828440ff0537456eec1580223a4f69eea
parent3414bec6245100e809ce6a24a5a4095e8fcd51ef (diff)
downloadkaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.tar.gz
kaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.tar.lz
kaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.zip
Check types of tool call arguments.
-rw-r--r--kaagum/tools.scm42
-rw-r--r--tests/tools.scm46
2 files changed, 87 insertions, 1 deletions
diff --git a/kaagum/tools.scm b/kaagum/tools.scm
index f561e65..97f0796 100644
--- a/kaagum/tools.scm
+++ b/kaagum/tools.scm
@@ -22,6 +22,8 @@
   #:use-module (rnrs exceptions)
   #:use-module (rnrs records syntactic)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-43)
   #:use-module (ice-9 match)
   #:use-module (gnu build linux-container)
   #:use-module (gnu system file-systems)
@@ -146,6 +148,34 @@
   tool-call-failure tool-call-failure?
   (message tool-call-failure-message))
 
+(define (check-type value type)
+  "Check type of JSON @var{value}. Return @code{#t} if it matches @var{type}, else
+return @code{#f}. @var{type} is a JSON Schema type defined in
+@url{https://json-schema.org/draft/2020-12/json-schema-validation#section-6.1.1}."
+  (match type
+    ("null"
+     (eq? value 'null))
+    ("boolean"
+     (boolean? value))
+    ("integer"
+     (integer? value))
+    ("number"
+     (number? value))
+    ("string"
+     (string? value))
+    ((? array-type? type)
+     (and (vector? value)
+          (vector-every (cut check-type <> (array-type-subtype type))
+                        value)))
+    ("object"
+     (every (match-lambda
+              ((key . _)
+               (string? key)))
+            value))
+    (#(types ...)
+     (any (cut check-type value <>)
+          types))))
+
 (define (spec->tool-call session-id session-cwd tools allowed-tools rejected-tools spec)
   "Deserialize JSON tool call @var{spec} into a @code{<tool-call>}
 object. Raise a @code{&tool-call-parse-failure} condition if deserialization
@@ -183,7 +213,17 @@ names that have been respectively allowed and rejected by the user in advance."
                              ((arg-name . parameter)
                               (cond
                                ((assoc arg-name args)
-                                => identity)
+                                => (match-lambda
+                                     ((and (_ . value)
+                                           key-value)
+                                      (let ((type (tool-parameter-type parameter)))
+                                        (unless (check-type value type)
+                                          (raise-exception
+                                           (tool-call-parse-failure
+                                            (string-append "Error: Argument "
+                                                           arg-name
+                                                           " of invalid type"))))
+                                        key-value))))
                                (else
                                 (and (tool-parameter-required? parameter)
                                      (raise-exception
diff --git a/tests/tools.scm b/tests/tools.scm
new file mode 100644
index 0000000..1ad0c62
--- /dev/null
+++ b/tests/tools.scm
@@ -0,0 +1,46 @@
+;;; kaagum --- Tiny, security-focused AI agent in Guile
+;;; Copyright © 2026 Arun Isaac <arunisaac@systemreboot.net>
+;;;
+;;; This file is part of kaagum.
+;;;
+;;; kaagum is free software: you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation, either version 3 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; kaagum is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with kaagum.  If not, see <https://www.gnu.org/licenses/>.
+
+(use-modules (srfi srfi-64)
+             (kaagum tools))
+
+(test-begin "tools")
+
+(test-equal "tool call with parameter type mismatch must error out"
+  "Error: Argument arg of invalid type"
+  (guard (c ((tool-call-parse-failure? c)
+             (tool-call-parse-failure-message c)))
+    (spec->tool-call "foo"
+                     "/foo/bar"
+                     `(("read" . ,(tool #:description "A dummy test tool"
+                                        #:parameters `(("arg" . ,(tool-parameter
+                                                                  #:description "an argument"
+                                                                  #:type "integer"
+                                                                  #:required? #t)))
+                                        #:proc identity
+                                        #:title identity
+                                        #:kind "read")))
+                     (list "read")
+                     (list)
+                     `(("id" . "foo123")
+                       ("type" . "function")
+                       ("function"
+                        ("name" . "read")
+                        ("arguments" . "{\"arg\": \"[738\"}"))))))
+
+(test-end "tools")