#+TITLE: SKILL: Shell Actuator (org-skill-shell-actuator.org) #+AUTHOR: Agent #+FILETAGS: :skill:actuator:shell: #+PROPERTY: header-args:lisp :tangle ../lisp/system-actuator-shell.lisp * Overview: The Physical Actuator The Shell Actuator is the agent's hand in the physical world. Given a shell command, it executes it via ~bash -c~ and returns the output. This is how the agent installs packages, reads files, runs scripts, and interacts with any Unix tool. Because shell execution is the highest-risk operation in the system, the Shell Actuator is protected by multiple safety layers: 1. The Bouncer's shell safety gate blocks destructive commands (~rm -rf /~, ~dd~, ~mkfs~) 2. The Bouncer's injection gate blocks backtick and ~$()~ patterns 3. The Bouncer's network exfil gate blocks connections to unwhitelisted hosts 4. The actuator enforces a timeout (default 30s) so hanging commands don't freeze the agent 5. The actuator caps output (default 100KB) so infinite output doesn't exhaust memory * Implementation ** Shell Execution (actuator-shell-execute) #+begin_src lisp (defun actuator-shell-execute (action context) "Executes a bash command with timeout (via timeout(1)) and output limit." (declare (ignore context)) (let* ((payload (getf action :payload)) (cmd (getf payload :cmd)) (timeout-sym (find-symbol "*BOUNCER-SHELL-TIMEOUT*" :passepartout)) (timeout (or (getf payload :timeout) (if timeout-sym (symbol-value timeout-sym) 30))) (max-sym (find-symbol "*BOUNCER-SHELL-MAX-OUTPUT*" :passepartout)) (max-output (or (getf payload :max-output) (if max-sym (symbol-value max-sym) 100000))) (wrapped-cmd (format nil "timeout ~a bash -c ~s" timeout cmd))) (log-message "ACT [Shell]: ~a (timeout: ~as)" cmd timeout) (multiple-value-bind (out err code) (uiop:run-program (list "bash" "-c" wrapped-cmd) :output :string :error-output :string :ignore-error-status t) (cond ((= code 124) (format nil "ERROR: Command timed out after ~a seconds" timeout)) ((> (length out) max-output) (format nil "~a~%... (output truncated to ~a chars)" (subseq out 0 max-output) max-output)) ((= code 0) out) (t (format nil "ERROR [~a]: ~a" code err)))))) #+end_src ** Skill Registration #+begin_src lisp (register-actuator :shell #'actuator-shell-execute) (defskill :passepartout-system-actuator-shell :priority 50 :trigger (lambda (ctx) (declare (ignore ctx)) nil)) #+end_src