Files
memex/system/skills/org-skill-router.org

6.8 KiB

SKILL: Router Agent (Meta-Cognitive Intent Classifier)

Overview

The Router Agent acts as the system's "Pre-Frontal Cortex." It is the first cognitive layer to handle unstructured user input, responsible for classifying intent and orchestrating the delegation of tasks to specialized sub-agents. It ensures that complex requests are decomposed into a logical sequence of atomic operations.

The Routing Mandate

  1. Perception: The Router must monitor for both explicit commands and implicit requests (e.g., `@agent` tags in headlines).
  2. Decomposition: Complex natural language must be broken down into a sequence of specific, actionable intents (e.g., memory retrieval followed by a shell command).
  3. Efficiency: The Router should utilize faster, lower-latency models for intent classification to minimize system response time.
  4. Dynamic Identity: The Router must adapt its triggers based on the agent's current identity (name).

Symbolic Implementation (The Logic)

The implementation focuses on the efficient detection of requests and the execution of the delegation loop.

Architectural Intent: Request Perception

This function performs a recursive search of the Org-mode AST to find headlines addressed to the agent. It dynamically resolves the agent's name from the Identity skill, ensuring the perception layer is always aligned with the agent's "self."

(defun find-agent-request (ast agent-name)
  "Recursively search the AST for a headline addressed to @agent or @name."
  (when (listp ast)
    (let* ((type (getf ast :type))
           (props (getf ast :properties))
           (title (or (getf props :TITLE) "")))
      (if (and (eq type :HEADLINE)
               (or (search "@agent" title :test #'string-equal)
                   (search (format nil "@~a" agent-name) title :test #'string-equal)))
          ;; Found it! Extract the instruction (everything after the @ tag)
          (let* ((pos (or (search "@agent" title :test #'string-equal)
                          (search (format nil "@~a" agent-name) title :test #'string-equal)))
                 ;; Skip the '@name' part
                 (instruction (subseq title (+ pos (if (search "@agent" title :test #'string-equal) 6 (1+ (length agent-name)))))))
            (string-trim '(#\Space #\Tab) instruction))
          ;; Not here, recurse into children
          (cl:some (lambda (c) (find-agent-request c agent-name)) (getf ast :contents))))))

(defun trigger-skill-router (context)
  "Engage if a user command exists OR if an @agent/@name request is found in the AST."
  (let* ((payload (getf context :payload))
         (sensor (getf payload :sensor))
         ;; DYNAMIC NAME RESOLUTION:
         ;; We look for the get-agent-name function in the identity skill's package.
         ;; If the skill hasn't loaded yet, we fall back to "Agent".
         (identity-pkg (find-package :org-agent.skills.skill-agent-identity))
         (name-fn (when identity-pkg (find-symbol "GET-AGENT-NAME" identity-pkg)))
         (agent-name (if (and name-fn (fboundp name-fn))
                         (funcall name-fn)
                         "Agent")))
    (cond
     ((eq sensor :user-command) t)
     ((eq sensor :buffer-update)
      ;; Proactive scanning of the AST using the dynamic name
      (let ((request (find-agent-request (getf payload :ast) agent-name)))
        (when request
          ;; Store the extracted instruction in the context for System 1
          (setf (getf (getf context :payload) :text) request)
          (kernel-log "KERNEL [Router] Detected request for @~a: ~a" agent-name request)
          t)))
     (t nil))))

Architectural Intent: Neuro-Cognitive Intent Decomposition

The neural layer is tasked with the high-level classification of the user's intent. It uses the `:fast` model tier to provide rapid delegation, mapping unstructured text to a list of internal skill targets.

(defun neuro-skill-router (context)
  (let ((text (getf (getf context :payload) :text))
        (config-pkg (find-package :org-agent.skills.skill-environment-config)))
    (let* ((get-tiered-fn (when config-pkg (find-symbol "GET-TIERED-MODEL" config-pkg)))
           ;; Router uses the :FAST tier for routing efficiency
           (model (if (and get-tiered-fn (fboundp get-tiered-fn))
                      (funcall get-tiered-fn :fast "openrouter/auto")
                      "openrouter/auto")))
      (format nil "
        You are the Master Router for an autonomous Lisp agent.
        The user said - '~a'
        
        Using model: ~a
        
        Decompose this request into a SEQUENCE of atomic intents.
        Available targets -
        - :atomic-notes (historical memory/note retrieval)
        - :shell (system commands like git status)
        - :gtd (tasks, deadlines, schedules)
        - :web (internet research, fetching URLs, searching the web)
        - :foundry (scaffolding new projects, creating directories)
        - :skill-creator (new capabilities, create a skill)
        
        Return a Lisp plist containing a list of intents - 
        (:type :MULTI-DELEGATION :intents ((:target-skill :atomic-notes :query \"...\") (:target-skill :shell :cmd \"...\")))
      " text model))))

Architectural Intent: Symbolic Delegation Loop

This stage executes the delegation by injecting new stimuli back into the kernel's event bus. It handles both single and multi-intent requests, effectively "re-triggering" the cognitive loop for the specific target skills.

(defun verify-skill-router (proposed-action context)
  (let ((type (getf proposed-action :type)))
    (cond
     ((eq type :MULTI-DELEGATION)
      (let ((intents (getf proposed-action :intents)))
        (kernel-log "KERNEL [Router] Processing ~a intents.~%" (length intents))
        (dolist (intent intents)
          (let* ((target (getf intent :target-skill))
                 (query (getf intent :query))
                 (cmd (getf intent :cmd))
                 (delegation-event `(:type :EVENT :payload (:sensor :delegation :target-skill ,target :query ,query :cmd ,cmd))))
            (kernel-log "KERNEL [Router] Delegating to ~a~%" target)
            (org-agent:inject-stimulus delegation-event)))
        nil))
     ((eq type :DELEGATION)
      (let* ((target (getf proposed-action :target-skill))
             (query (getf proposed-action :query))
             (delegation-event `(:type :EVENT :payload (:sensor :delegation :target-skill ,target :query ,query))))
        (kernel-log "KERNEL [Router] Delegating to ~a~%" target)
        (org-agent:inject-stimulus delegation-event)
        nil))
     (t '(:type :LOG :payload (:text "Router failed to classify."))))))

Registration

(defskill :skill-router
  :priority 90
  :trigger #'trigger-skill-router
  :neuro #'neuro-skill-router
  :symbolic #'verify-skill-router)