Agent2_Ansible : spécialiste Ansible pour l'automatisation du réseau local

- agent2_ansible.py : script principal (XMPP + MQTT)
- config/system_prompt.txt : prompt spécialisé Ansible
- skills/ansible_exec.py : ANSIBLE: (ad-hoc) + PLAYBOOK: (playbooks)
- skills/memory.py, prompt_memory.py : chemins corrigés pour agent2_ansible
- ansible/ansible.cfg + inventory/hosts : configuration de base

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 16:22:34 +00:00
parent 6efb9afe0b
commit 47e93c2afa
7 changed files with 177 additions and 26 deletions
+3 -3
View File
@@ -10,11 +10,11 @@ from pathlib import Path
from slixmpp import ClientXMPP
import paho.mqtt.client as mqtt
sys.path.insert(0, "/opt/agent2_debian13")
sys.path.insert(0, "/opt/agent2_ansible")
from skills.loader import load_skills, run_skills
# ── CONFIG ───────────────────────────────────────────────────────────────
CONFIG_DIR = Path("/opt/agent2_debian13/config")
CONFIG_DIR = Path("/opt/agent2_ansible/config")
CONFIG_FILE = CONFIG_DIR / "config.json"
PROMPT_FILE = CONFIG_DIR / "system_prompt.txt"
@@ -125,7 +125,7 @@ class AgentBot(ClientXMPP):
self.send_presence()
await self.get_roster()
self.send_message(mto=ADMIN_JID,
mbody="Agent2_Debian13 en ligne !",
mbody="Agent2_Ansible en ligne !",
mtype='chat')
async def message(self, msg):
+11
View File
@@ -0,0 +1,11 @@
[defaults]
inventory = /opt/agent2_ansible/ansible/inventory
roles_path = /opt/agent2_ansible/ansible/roles
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml
timeout = 60
[privilege_escalation]
become = False
become_method = sudo
+15
View File
@@ -0,0 +1,15 @@
# Inventaire Ansible - Réseau local
# Ajouter les hôtes selon l'infrastructure réelle
[local]
localhost ansible_connection=local
[servers]
# exemple : srv1 ansible_host=192.168.7.10 ansible_user=root
# exemple : srv2 ansible_host=192.168.7.11 ansible_user=debian
[workstations]
# exemple : pc1 ansible_host=192.168.7.50 ansible_user=sylvain
[all:vars]
ansible_python_interpreter=/usr/bin/python3
+39 -21
View File
@@ -1,35 +1,52 @@
Tu es agent2_debian13, un agent autonome spécialisé dans l'administration de systèmes Debian.
Tu es agent2_ansible, un agent autonome spécialisé dans l'automatisation et l'orchestration d'infrastructure via Ansible.
Tu travailles sous les ordres d'agent1 qui te délègue des tâches via MQTT.
Tu as acs au système réel et peux exécuter des commandes shell.
Tu gères les machines du réseau local via Ansible (playbooks, modules ad-hoc, inventaire).
Tes domaines de compétence :
- Gestion des paquets : apt, dpkg, snap
- Services systemd : start, stop, enable, status, journalctl
- Conteneurs : LXC, LXD, Docker sur Debian
- Machines virtuelles : KVM/QEMU, libvirt
- Réseau Debian : interfaces, /etc/network, NetworkManager
- Sécurité : ufw, fail2ban, SSH, sudoers
- Fichiers de config système : fstab, crontab, hosts
- Surveillance : top, htop, df, du, netstat, ss
- Exécution de playbooks Ansible sur les hôtes du réseau local
- Commandes ad-hoc Ansible (ping, shell, copy, apt, service, etc.)
- Gestion de l'inventaire Ansible
- Déploiement de configurations sur plusieurs machines simultanément
- Installation et gestion de paquets à distance
- Gestion de services systemd à distance
- Copie et gestion de fichiers sur les hôtes distants
- Collecte de facts (informations système) sur les hôtes
Formats de commandes disponibles :
EXEC: <commande shell>
→ Exécuter une commande sur le système et récupérer le résultat
ANSIBLE: <arguments>
→ Exécute une commande ansible (ad-hoc) sur les hôtes
→ Exemples :
EXEC: systemctl status nginx
EXEC: apt install -y curl
EXEC: docker ps -a
EXEC: journalctl -u ssh --no-pager -n 20
ANSIBLE: all -m ping
ANSIBLE: all -m shell -a "uptime"
ANSIBLE: webservers -m apt -a "name=nginx state=present" --become
ANSIBLE: all -m gather_facts --tree /tmp/facts
ANSIBLE: all -m service -a "name=nginx state=restarted" --become
PLAYBOOK: <playbook.yml> [options]
→ Exécute un playbook Ansible
→ Les playbooks sont dans /opt/agent2_ansible/ansible/playbooks/
→ Exemples :
PLAYBOOK: site.yml
PLAYBOOK: deploy.yml --limit webservers
PLAYBOOK: update.yml --tags packages
PLAYBOOK: hardening.yml --check
EXEC: <commande shell>
→ Exécuter une commande locale (utile pour inspecter l'inventaire, les logs, etc.)
→ Exemples :
EXEC: ansible-inventory --list
EXEC: cat /opt/agent2_ansible/ansible/inventory/hosts
EXEC: ls /opt/agent2_ansible/ansible/playbooks/
SEARCH: <requête>
→ Recherche web si besoin de documentation
→ Recherche web si besoin de documentation Ansible
READ: <url>
→ Lire une page de documentation
REMEMBER: <clé> | <valeur>
→ Mémoriser une information
→ Mémoriser une information (ex: IP d'un hôte, configuration)
RECALL: <clé>
→ Récupérer une information mémorisée
@@ -37,9 +54,10 @@ RECALL: <clé>
⚠ RÈGLES :
- Tu reçois des tâches d'agent1 via MQTT et tu lui réponds via MQTT
- Tu peux aussi recevoir des instructions directement de sylvain via XMPP
- Pour toute tâche système : utilise EXEC: pour l'exécuter réellement, pas juste expliquer
- Enchaîne plusieurs EXEC: si nécessaire pour accomplir une tâche complexe
- Pour toute tâche Ansible : utilise ANSIBLE: ou PLAYBOOK: pour l'exécuter réellement
- Enchaîne plusieurs commandes si nécessaire pour accomplir une tâche complexe
- Vérifie toujours le résultat d'une commande avant de passer à la suivante
- Si une commande échoue, analyse l'erreur et adapte-toi
- Signale à agent1 si une tâche est hors de ton domaine Debian
- Signale à agent1 si une tâche est hors de ton domaine Ansible
- Réponds toujours en français avec un résumé clair de ce qui a été fait
- Pour les opérations risquées (suppression, modification critique), utilise --check d'abord
+107
View File
@@ -0,0 +1,107 @@
"""
Skill : ANSIBLE / PLAYBOOK
Exécute des commandes Ansible (ad-hoc ou playbooks) sur les hôtes du réseau local.
Commandes :
ANSIBLE: <arguments>
→ Exécute ansible avec les arguments fournis
→ Exemples :
ANSIBLE: all -m ping
ANSIBLE: all -m shell -a "uptime"
ANSIBLE: webservers -m apt -a "name=nginx state=present" --become
PLAYBOOK: <playbook.yml> [options]
→ Exécute ansible-playbook depuis le dossier playbooks/
→ Exemples :
PLAYBOOK: site.yml
PLAYBOOK: deploy.yml --limit webservers --tags packages
"""
import subprocess
from pathlib import Path
SKILL_NAME = "ansible_exec"
TRIGGER = None
TRIGGERS = {
"ANSIBLE:": "ansible_adhoc",
"PLAYBOOK:": "ansible_playbook",
}
ANSIBLE_DIR = Path("/opt/agent2_ansible/ansible")
PLAYBOOKS_DIR = ANSIBLE_DIR / "playbooks"
ANSIBLE_CFG = ANSIBLE_DIR / "ansible.cfg"
TIMEOUT = 120 # secondes (les commandes réseau peuvent être longues)
MAX_CHARS = 5000
# Variables d'environnement pour ansible
import os
ANSIBLE_ENV = {
**os.environ,
"ANSIBLE_CONFIG": str(ANSIBLE_CFG),
"ANSIBLE_FORCE_COLOR": "0",
"ANSIBLE_NOCOLOR": "1",
}
def _run(cmd: list) -> str:
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=TIMEOUT,
env=ANSIBLE_ENV,
cwd=str(ANSIBLE_DIR),
)
stdout = result.stdout.strip()
stderr = result.stderr.strip()
output = ""
if stdout:
output += stdout
if stderr:
output += ("\n[stderr] " + stderr) if output else "[stderr] " + stderr
if not output:
output = "(aucune sortie)"
if len(output) > MAX_CHARS:
output = output[:MAX_CHARS] + "\n...[tronqué]"
status = "OK" if result.returncode == 0 else "Erreur (code {})".format(result.returncode)
return "[{}] $ {}\n{}".format(status, " ".join(cmd), output)
except subprocess.TimeoutExpired:
return "Timeout : la commande a dépassé {}s.".format(TIMEOUT)
except FileNotFoundError:
return "Erreur : ansible n'est pas installé ou introuvable dans le PATH."
except Exception as e:
return "Erreur d'exécution : {}".format(e)
def ansible_adhoc(args: str) -> str:
args = args.strip()
if not args:
return "Erreur : arguments vides. Exemple : ANSIBLE: all -m ping"
cmd = ["ansible"] + args.split()
return _run(cmd)
def ansible_playbook(args: str) -> str:
args = args.strip()
if not args:
return "Erreur : playbook non spécifié. Exemple : PLAYBOOK: site.yml"
parts = args.split()
playbook = parts[0]
options = parts[1:]
# Chemin absolu si non fourni
playbook_path = Path(playbook)
if not playbook_path.is_absolute():
playbook_path = PLAYBOOKS_DIR / playbook
if not playbook_path.exists():
return "Erreur : playbook introuvable : {}".format(playbook_path)
cmd = ["ansible-playbook", str(playbook_path)] + options
return _run(cmd)
+1 -1
View File
@@ -9,7 +9,7 @@ SKILL_NAME = "memory"
TRIGGER = None
TRIGGERS = {"REMEMBER:": "remember", "RECALL:": "recall"}
DB_PATH = Path("/opt/agent2_debian13/memory.db")
DB_PATH = Path("/opt/agent2_ansible/memory.db")
def _get_conn():
conn = sqlite3.connect(DB_PATH)
+1 -1
View File
@@ -23,7 +23,7 @@ TRIGGERS = {
"PROMPT_DEL:": "prompt_del",
}
DB_PATH = Path("/opt/agent2_debian13/chroma_db")
DB_PATH = Path("/opt/agent2_ansible/chroma_db")
# Phase 1 : embedding factice (hash MD5 → vecteur 16 dims)
# Phase 2 : remplacer par un vrai modèle (ex: sentence-transformers)