branch: externals/ellama
commit 4a8eced4cfa6826d3d4f138755ff82618092df4c
Author: Sergey Kostyaev <[email protected]>
Commit: Sergey Kostyaev <[email protected]>
Add asynchronous task delegation to sub-agents
Add ellama-tool-task function that delegates descriptions to sub-agents
asynchronously. The function supports custom roles and max-steps limits with
safe fallbacks. It creates ephemeral worker sessions, resolves role-specific
tools, and uses a callback mechanism to report results.
---
ellama-tools.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/ellama-tools.el b/ellama-tools.el
index 8c6414211c..e8ac006026 100644
--- a/ellama-tools.el
+++ b/ellama-tools.el
@@ -699,5 +699,77 @@ CALLBACK will be used to report result asyncronously."
:session session
:on-done #'ellama--subagent-loop-handler)))))
+(defun ellama-tool-task (callback description &optional role)
+ "Delegate DESCRIPTION to a sub-agent asynchronously.
+
+CALLBACK – function called once with the result string.
+ROLE – role key from `ellama-subagent-roles'."
+ (let* ((parent-id ellama--current-session-id)
+ (provider ellama-provider)
+
+ ;; ---- role resolution (safe fallback) ----
+ (role-key (if (assoc role ellama-subagent-roles)
+ role
+ "general"))
+
+ (role-cfg (cdr (assoc role-key ellama-subagent-roles)))
+ (system-msg (plist-get role-cfg :system))
+
+ (steps-limit ellama-subagent-default-max-steps)
+
+ ;; ---- create ephemeral worker session ----
+ (worker (ellama-new-session provider description t))
+
+ ;; ---- resolve tools for role ----
+ (role-tools (ellama--tools-for-role role-key))
+
+ ;; ---- dynamic report_result tool ----
+ (report-tool
+ (apply #'llm-make-tool
+ (ellama-tools-wrap-with-confirm
+ (ellama-tools--make-report-result-tool callback worker))))
+
+ ;; IMPORTANT: report tool must be first (termination tool priority)
+ (all-tools (cons report-tool role-tools)))
+
+ ;; ============================================================
+ ;; Initialize session state (single source of truth)
+ ;; ============================================================
+
+ (setf (ellama-session-extra worker)
+ (list
+ :parent-session parent-id
+ :role role-key
+ :tools all-tools
+ :result-callback callback
+ :task-completed nil
+ :step-count 0
+ :max-steps steps-limit))
+
+ ;; ============================================================
+ ;; Start the agent loop
+ ;; ============================================================
+
+ (ellama-stream
+ description
+ :session worker
+ :on-done #'ellama--subagent-loop-handler
+ :tools all-tools
+ :system
+ (format
+ "%s\n\nINSTRUCTIONS:\n\
+Work step-by-step. Use tools when needed.\n\
+When the task is COMPLETE you MUST call `report_result` exactly once."
+ system-msg))
+
+ ;; ============================================================
+ ;; Immediate response to parent LLM (async contract)
+ ;; ============================================================
+
+ (message "Subtask started (session %s, role %s). Waiting for result via
callback."
+ (ellama-session-id worker)
+ role-key)
+ nil))
+
(provide 'ellama-tools)
;;; ellama-tools.el ends here