Map XML tool body to schema's primary required arg

ober

4b6906e1acfb8e1bfdacbad363d79c5c72e8d501

diff --git a/src/jcode/core/agent.ss b/src/jcode/core/agent.ss
index 1995e27..71f7f5b 100644
--- a/src/jcode/core/agent.ss
+++ b/src/jcode/core/agent.ss
@@ -617,7 +617,7 @@ Be concise. Prefer edit over write for modifying existing files.
                                      acc))))
                     ((tool-exists? name)
                      (loop next
-                           (cons (make-tool-call name (xml->json-args attrs body))
+                           (cons (make-tool-call name (xml->json-args name attrs body))
                                  acc)))
                     (else (loop next acc)))))))))))))
 
@@ -857,7 +857,7 @@ Be concise. Prefer edit over write for modifying existing files.
                (put-string out new)
                (loop (+ idx olen))))))))))
 
-(def (xml->json-args attrs body)
+(def (xml->json-args name attrs body)
   (let ((ht (make-hash-table)))
     (for-each
       (lambda (p) (hash-put! ht (car p) (cdr p)))
@@ -869,7 +869,11 @@ Be concise. Prefer edit over write for modifying existing files.
           (cond
             ((hash-table? parsed)
              (hash-for-each (lambda (k v) (hash-put! ht k v)) parsed))
-            (else (hash-put! ht "_body" trimmed))))))
+            (else
+             ;; Bare body — map to the tool's primary required arg if known
+             ;; (e.g. <glob>**/*.ss</glob> → {"pattern":"**/*.ss"}).
+             (let ((key (or (tool-primary-arg name) "_body")))
+               (hash-put! ht key trimmed)))))))
     (json-object->string ht)))
 
 ;;; Anthropic/DSML invoke-tag tool call detection ;;;
diff --git a/src/jcode/tool/registry.ss b/src/jcode/tool/registry.ss
index 8a40e30..8cc7d33 100644
--- a/src/jcode/tool/registry.ss
+++ b/src/jcode/tool/registry.ss
@@ -12,7 +12,8 @@
         write-tool-name?
         register-write-tools!
         set-tool-internal!
-        tool-exists?)
+        tool-exists?
+        tool-primary-arg)
 
 (import :std/text/json
         :std/misc/string
@@ -131,6 +132,16 @@
 (def (tool-exists? name)
   (and (hash-get *tools* name) #t))
 
+(def (tool-primary-arg name)
+  ;; Return the first required arg name for a tool's schema, or #f. Used to
+  ;; recover models that emit '<tool>VALUE</tool>' instead of '<tool key="VALUE"/>'.
+  (let ((tool (hash-get *tools* name)))
+    (and tool
+         (let* ((schema (hash-ref tool "schema" #f))
+                (req (and (hash-table? schema)
+                          (hash-get schema "required"))))
+           (and (pair? req) (car req))))))
+
 (def (set-tool-internal! name internal?)
   "Toggle the 'internal' flag on a registered tool. When #t, the tool is
    hidden from get-tool-schemas (and therefore from the LLM). Used by serve