Function: gptel--handle-tool-use
gptel--handle-tool-use is a natively compiled function defined in
gptel-request.el.
Signature
(gptel--handle-tool-use FSM)
Documentation
Run tool calls captured in FSM, and advance the state machine with the results.
Source Code
;; Defined in /nix/store/q3r7g81pvghw7a523kjk2k2zih3pfk8z-emacs-packages-deps/share/emacs/site-lisp/elpa/gptel-20261002.545/gptel-request.el
(defun gptel--handle-tool-use (fsm)
"Run tool calls captured in FSM, and advance the state machine with the results."
(when-let* ((info (gptel-fsm-info fsm))
(backend (plist-get info :backend))
;; This function might run many times, so only act on the remaining tool calls.
(tool-use (cl-remove-if (lambda (tc) (plist-get tc :result))
(plist-get info :tool-use))))
(with-current-buffer (plist-get info :buffer)
(let ((pending-calls))
(mapc ; Construct function calls
(lambda (tool-call)
(letrec ((args (plist-get tool-call :args))
(name (plist-get tool-call :name))
(tool-spec (cl-find-if (lambda (ts) (equal (gptel-tool-name ts) name))
(plist-get info :tools)))
(process-tool-result (apply-partially #'gptel--process-tool-call
fsm tool-spec tool-call)))
(if (null tool-spec)
(if (equal name gptel--ersatz-json-tool) ;Could be a JSON response
(progn ;Handle structured JSON output supplied as tool call
(funcall (plist-get info :callback)
(gptel--json-encode (plist-get tool-call :args)) info)
(plist-put info :tool-use ;Remove this tool call from the list
(cl-remove-if (lambda (tc) (equal (plist-get tc :name)
gptel--ersatz-json-tool))
(plist-get info :tool-use)))
(when (plist-get info :stream)
(funcall (plist-get info :callback) t info)))
(message "Unknown tool called by model: %s" name)
(funcall process-tool-result
(format "Error: Tool '%s' is not available. Available tools: %s"
name (mapconcat #'gptel-tool-name
(plist-get info :tools) ", "))))
(let ((confirm)) ;Check if tool requires confirmation
(cond ;:confirm in tool-call (from hooks) takes precedence
((and-let* ((call-confirm (plist-member tool-call :confirm)))
(prog1 t (setq confirm (cadr call-confirm)))))
((and gptel-confirm-tool-calls ;global and tool-specific setting
(or (eq gptel-confirm-tool-calls t) ;always confirm, or
(and-let* ((confirm (gptel-tool-confirm tool-spec)))
(or (not (functionp confirm))
(apply confirm (gptel--map-tool-args tool-spec args))))))
(setq confirm t)))
(if confirm ;To send to callback for confirmation
(push (list tool-spec args process-tool-result) pending-calls)
(let ((arg-values (gptel--map-tool-args tool-spec args)))
(if (gptel-tool-async tool-spec) ;If not, run the tool
(apply (gptel-tool-function tool-spec)
process-tool-result arg-values)
(let ((result (condition-case errdata
(apply (gptel-tool-function tool-spec) arg-values)
(error (mapconcat #'gptel--to-string errdata " ")))))
(funcall process-tool-result result)))))))))
tool-use)
(when pending-calls
(plist-put info :tool-pending t)
(funcall (plist-get info :callback)
(cons 'tool-call pending-calls) info))))))