FrameworksAgents.com Logo

Les agents OpenClaw : guide complet

Guidecalendar_todayPublié le 7 mars 2026schedule10 min de lecturecréer agent openclawtypes agents openclaw

Comprendre les agents OpenClaw : composants, types, cycle de vie, création et orchestration. Guide technique avec code Python et exemples concrets.

Les agents OpenClaw : guide complet

Un agent OpenClaw est une unité autonome capable d'accomplir un objectif défini en enchaînant des skills, en prenant des décisions conditionnelles et en gérant ses propres erreurs. Comprendre ce que sont les agents OpenClaw, comment ils sont structurés et comment les créer est le point de départ de tout déploiement. Ce guide couvre l'architecture interne, les types d'agents disponibles, le cycle de vie et la création d'un premier agent fonctionnel, avec des exemples de code Python commentés.

Qu'est-ce qu'un agent OpenClaw ?

Un agent OpenClaw est un programme Python qui orchestre des skills dans un ordre logique pour accomplir une tâche de bout en bout. Il ne s'agit pas d'un simple script séquentiel : l'agent peut interrompre son exécution si une condition n'est pas remplie, réessayer une étape en cas d'échec, ou adapter son comportement en fonction des données reçues à chaque étape.

La différence avec un script classique est dans la gestion de l'état. Un agent maintient une mémoire de contexte partagée entre tous ses skills. Quand le skill A produit un résultat, le skill B peut l'utiliser directement sans qu'il soit nécessaire de le passer manuellement entre les fonctions. Cette mémoire persistante rend les workflows multi-étapes fiables et inspectables.

Un agent OpenClaw est défini par :

  • un nom et une configuration (modèle LLM, nombre de retries, backend mémoire) ;
  • une liste de skills enregistrés dans un ordre d'exécution logique ;
  • une mémoire de contexte initialisée à l'entrée et enrichie à chaque étape ;
  • des règles de sortie : continuer, arrêter, ou réessayer.

Pour aller plus loin sur la philosophie du framework, consultez le guide complet OpenClaw.

Les composants d'un agent

AgentConfig

AgentConfig définit le comportement global de l'agent : quel LLM utiliser, combien de fois réessayer en cas d'échec, quel backend utiliser pour stocker la mémoire.

from openclaw import AgentConfig

config = AgentConfig(
    name="mon-agent",
    model="gpt-4o",          # LLM utilisé par les skills qui en ont besoin
    max_retries=3,           # Nombre de tentatives avant abandon
    memory_backend="local",  # "local", "redis", "sqlite"
    log_level="INFO",        # Niveau de verbosité des logs
    timeout=120,             # Timeout global en secondes
)

Skill

Un skill est une classe Python qui hérite de Skill. Elle implémente une méthode run(context: dict) -> SkillResult. Chaque skill reçoit le contexte courant, effectue une action, et retourne un résultat qui enrichit ce contexte.

from openclaw import Skill, SkillResult

class MonSkill(Skill):
    name = "mon_skill"

    def run(self, context: dict) -> SkillResult:
        # Lire des données du contexte
        input_data = context.get("input_data")

        # Effectuer une action
        result = process(input_data)

        # Retourner succès ou arrêt
        if result:
            return SkillResult.success({**context, "output": result})
        else:
            return SkillResult.stop(reason="Traitement impossible")

AgentMemory

La mémoire est le contexte partagé entre tous les skills. Elle est initialisée avec les données d'entrée et enrichie à chaque étape. Chaque skill peut lire tout ce qui a été produit par les skills précédents.

# Initialisation de la mémoire à l'entrée
initial_context = {
    "keyword": "agent ia python",
    "lang": "fr",
    "user_id": "42",
}
result = agent.run(initial_context)

SkillResult

SkillResult communique à l'agent ce qu'il doit faire après l'exécution d'un skill :

SkillResult.success(data)     # Continuer avec les données enrichies
SkillResult.stop(reason)      # Arrêter le pipeline (log + exit propre)
SkillResult.retry(reason)     # Réessayer ce skill (jusqu'à max_retries)
SkillResult.error(exception)  # Erreur inattendue (log + exit avec code erreur)

Les types d'agents

OpenClaw supporte plusieurs patterns d'agents selon la complexité du workflow :

Agent séquentiel

Le type le plus simple. Chaque skill s'exécute dans l'ordre, l'un après l'autre.

agent = Agent(config)
agent.register_skill(SkillA())
agent.register_skill(SkillB())
agent.register_skill(SkillC())
agent.run(context)
# Exécution : A → B → C

Adapté pour : pipelines de traitement de données, génération de contenu, rapports automatiques.

Agent conditionnel

Les skills s'exécutent selon des conditions évaluées sur le contexte courant.

from openclaw import ConditionalSkill

agent.register_skill(ConditionalSkill(
    condition=lambda ctx: ctx.get("volume", 0) > 500,
    skill=WriterSkill(),
    fallback=LogSkill(message="Volume insuffisant"),
))

Adapté pour : workflows avec critères de qualité, filtrages métier, traitement sélectif.

Agent boucle

Répète un ensemble de skills sur une liste d'entrées.

from openclaw import LoopAgent

agent = LoopAgent(config, items_key="keywords")
agent.register_skill(SerpSkill())
agent.register_skill(WriterSkill())
agent.run({"keywords": ["kw1", "kw2", "kw3"]})
# Exécute le pipeline complet pour chaque mot-clé

Adapté pour : traitement par lot (mots-clés, URLs, leads, produits).

Agent orchestré (multi-agents)

Un agent principal délègue des sous-tâches à des agents spécialisés. Chaque sous-agent est autonome et retourne un résultat à l'orchestrateur.

from openclaw import OrchestratorAgent

orchestrator = OrchestratorAgent(config)
orchestrator.register_sub_agent("seo", seo_agent)
orchestrator.register_sub_agent("social", social_agent)
orchestrator.register_sub_agent("email", email_agent)
orchestrator.run({"article_id": "123"})
# L'orchestrateur délègue en parallèle ou en séquence selon config

Adapté pour : workflows complexes impliquant des domaines différents, pipelines avec parallélisation.

Cycle de vie d'un agent

┌─────────────────────────────────────────────────────────┐
│                   CYCLE DE VIE AGENT                    │
│                                                         │
│  ┌──────────┐                                           │
│  │  INIT    │ ← AgentConfig + Skills enregistrés        │
│  └────┬─────┘                                           │
│       │                                                 │
│       ▼                                                 │
│  ┌──────────┐                                           │
│  │  START   │ ← context = données d'entrée              │
│  └────┬─────┘                                           │
│       │                                                 │
│       ▼                                                 │
│  ┌──────────┐   SkillResult.retry   ┌──────────┐        │
│  │  SKILL   │──────────────────────▶│  RETRY   │        │
│  │  RUN     │◀──────────────────────└──────────┘        │
│  └────┬─────┘  (max_retries atteint → STOP)             │
│       │                                                 │
│       ├── SkillResult.stop ──▶ ┌──────────┐            │
│       │                        │   STOP   │ → log       │
│       │                        └──────────┘            │
│       │                                                 │
│       ├── SkillResult.error ─▶ ┌──────────┐            │
│       │                        │  ERROR   │ → log+exit  │
│       │                        └──────────┘            │
│       │                                                 │
│       ▼ SkillResult.success                             │
│  ┌──────────┐                                           │
│  │  NEXT    │ ← context enrichi avec output du skill    │
│  │  SKILL   │                                           │
│  └────┬─────┘                                           │
│       │ (dernier skill atteint)                         │
│       ▼                                                 │
│  ┌──────────┐                                           │
│  │  DONE    │ → retourne AgentResult final              │
│  └──────────┘                                           │
└─────────────────────────────────────────────────────────┘

Chaque transition est loggée. Le résultat final (AgentResult) contient le contexte final, le statut global, la liste des skills exécutés et les éventuelles erreurs rencontrées.

Créer son premier agent

Voici un agent minimal fonctionnel qui récupère le contenu d'une URL et en extrait les titres H2.

Installation

pip install openclaw beautifulsoup4 httpx

Code complet

# first_agent.py
from openclaw import Agent, AgentConfig, Skill, SkillResult
from bs4 import BeautifulSoup
import httpx

# --- Skill 1 : fetch ---
class FetchSkill(Skill):
    name = "fetch_url"

    def run(self, context: dict) -> SkillResult:
        url = context.get("url")
        if not url:
            return SkillResult.stop(reason="Aucune URL fournie")

        try:
            response = httpx.get(url, timeout=10, follow_redirects=True)
            response.raise_for_status()
            return SkillResult.success({**context, "html": response.text})
        except httpx.HTTPError as e:
            return SkillResult.retry(reason=f"Erreur HTTP : {e}")

# --- Skill 2 : parse ---
class ParseH2Skill(Skill):
    name = "parse_h2"

    def run(self, context: dict) -> SkillResult:
        html = context.get("html", "")
        soup = BeautifulSoup(html, "html.parser")
        h2s = [h.get_text(strip=True) for h in soup.find_all("h2")]

        if not h2s:
            return SkillResult.stop(reason="Aucun H2 trouvé sur la page")

        return SkillResult.success({**context, "h2_titles": h2s})

# --- Configuration ---
config = AgentConfig(
    name="h2-extractor",
    model="gpt-4o",
    max_retries=2,
    memory_backend="local",
    log_level="INFO",
)

# --- Création et exécution ---
agent = Agent(config)
agent.register_skill(FetchSkill())
agent.register_skill(ParseH2Skill())

result = agent.run({"url": "https://example.com/article"})

if result.success:
    print("H2 trouvés :", result.data["h2_titles"])
else:
    print("Arrêt :", result.reason)

Cet agent de 40 lignes est autonome : il gère les erreurs HTTP, réessaie automatiquement, et s'arrête proprement si la page ne contient pas de H2.

Pour explorer les skills disponibles dans la bibliothèque standard OpenClaw, voir le guide des skills OpenClaw.

Agents simples vs agents orchestrés

CritèreAgent simpleAgent orchestré
Nombre de skills2–6Illimité (via sous-agents)
ParallélisationNonOui (sous-agents en parallèle)
Complexité codeFaibleÉlevée
DébogageFacilePlus complexe
Cas d'usagePipeline linéaireWorkflow multi-domaines
ExempleAudit SERP + rédactionSEO + social + email

Recommandation : commencez toujours par un agent simple. Ajoutez un orchestrateur uniquement quand un pipeline linéaire atteint ses limites (trop de skills, besoin de parallélisation, domaines métier trop différents).

Un agent simple bien conçu couvre 80 % des cas d'usage courants. La complexité supplémentaire d'un orchestrateur n'est justifiée que si elle apporte un gain mesurable (temps d'exécution, capacité de traitement).

Exemple concret : agent de veille

Objectif : surveiller les 5 principaux concurrents sur un mot-clé et envoyer un rapport email hebdomadaire si un concurrent publie un nouvel article.

# veille_agent.py
from openclaw import Agent, AgentConfig, Skill, SkillResult, LoopAgent
import httpx
import smtplib
from email.mime.text import MIMEText
from bs4 import BeautifulSoup
from datetime import datetime, timedelta

class CheckNewArticlesSkill(Skill):
    name = "check_new_articles"

    def run(self, context: dict) -> SkillResult:
        competitor_url = context.get("competitor_url")
        response = httpx.get(competitor_url, timeout=10, follow_redirects=True)
        soup = BeautifulSoup(response.text, "html.parser")

        # Chercher des articles publiés dans les 7 derniers jours
        # (logique simplifiée — adapter aux balises du site concurrent)
        articles = soup.find_all("article")
        new_articles = []

        for article in articles:
            date_tag = article.find("time")
            if date_tag and date_tag.get("datetime"):
                pub_date = datetime.fromisoformat(date_tag["datetime"][:10])
                if pub_date >= datetime.now() - timedelta(days=7):
                    title = article.find("h2") or article.find("h3")
                    link = article.find("a")
                    if title and link:
                        new_articles.append({
                            "title": title.get_text(strip=True),
                            "url": link.get("href"),
                            "date": str(pub_date.date()),
                        })

        if not new_articles:
            return SkillResult.stop(reason="Aucun nouvel article cette semaine")

        existing = context.get("new_articles", [])
        return SkillResult.success({
            **context,
            "new_articles": existing + [
                {"source": competitor_url, **a} for a in new_articles
            ],
        })


class EmailReportSkill(Skill):
    name = "email_report"

    def __init__(self, smtp_config: dict, recipient: str):
        self.smtp_config = smtp_config
        self.recipient = recipient

    def run(self, context: dict) -> SkillResult:
        articles = context.get("new_articles", [])
        if not articles:
            return SkillResult.stop(reason="Rien à envoyer")

        body = "Nouveaux articles concurrents cette semaine :\n\n"
        for a in articles:
            body += f"- [{a['title']}]({a['url']}) — {a['source']} ({a['date']})\n"

        msg = MIMEText(body)
        msg["Subject"] = f"Veille concurrentielle — {datetime.now().strftime('%d/%m/%Y')}"
        msg["From"] = self.smtp_config["from"]
        msg["To"] = self.recipient

        with smtplib.SMTP(self.smtp_config["host"], self.smtp_config["port"]) as server:
            server.starttls()
            server.login(self.smtp_config["user"], self.smtp_config["password"])
            server.send_message(msg)

        return SkillResult.success({**context, "email_sent": True})


# --- Configuration et exécution ---
config = AgentConfig(name="veille-agent", model="gpt-4o", max_retries=2, memory_backend="local")

smtp_cfg = {"host": "smtp.gmail.com", "port": 587, "from": "vous@email.com",
            "user": "vous@email.com", "password": "APP_PASSWORD"}

competitors = [
    "https://concurrent1.fr/blog/",
    "https://concurrent2.fr/articles/",
    "https://concurrent3.fr/ressources/",
]

# Agent boucle : exécute CheckNewArticlesSkill pour chaque concurrent
loop_agent = LoopAgent(config, items_key="competitor_urls")
loop_agent.register_skill(CheckNewArticlesSkill())

# Exécuter la veille
result = loop_agent.run({"competitor_urls": competitors})

# Envoyer le rapport si des articles ont été trouvés
if result.success and result.data.get("new_articles"):
    report_agent = Agent(config)
    report_agent.register_skill(EmailReportSkill(smtp_cfg, "destinataire@email.com"))
    report_agent.run(result.data)

Cet agent de veille tourne en cron hebdomadaire (via Vercel Cron ou un scheduler Linux). Il envoie un rapport uniquement quand des nouveaux articles sont détectés — pas de bruit inutile dans la boîte mail.

Pour voir un agent plus complexe en production, consultez le guide Créer un agent SEO avec OpenClaw.

Bonnes pratiques

Nommer les skills de façon descriptive. L'attribut name du skill apparaît dans les logs. fetch_url est utile au débogage ; skill_1 ne l'est pas.

Toujours retourner un SkillResult explicite. Ne jamais laisser une méthode run retourner None ou lever une exception non gérée. L'agent doit savoir quoi faire à chaque sortie possible.

Garder les skills petits et focalisés. Un skill fait une chose. Si un skill dépasse 50 lignes, il fait probablement deux choses différentes — découpez-le. Cela facilite les tests unitaires et la réutilisation.

Tester chaque skill isolément avant de l'intégrer dans un agent. Passez-lui un contexte minimal et vérifiez que SkillResult.success, SkillResult.stop et SkillResult.retry se déclenchent dans les bons cas.

Logger les métriques importantes dans le contexte. Durée d'exécution, coût API, nombre d'items traités — ajoutez ces données dans le contexte à chaque skill. Le AgentResult final contiendra alors un historique complet inspectable.

Définir une stratégie de retry différenciée. Certaines erreurs méritent un retry (timeout réseau), d'autres non (volume insuffisant, contenu inexistant). Utilisez SkillResult.retry uniquement pour les erreurs transitoires.

Conclusion

Un agent OpenClaw est la combinaison d'une configuration, de skills modulaires et d'une mémoire partagée. Sa puissance réside dans la clarté de cette architecture : chaque composant est indépendant, testable et remplaçable. La progression naturelle est de démarrer par un agent séquentiel simple, de valider son comportement sur des cas réels, puis d'augmenter la complexité uniquement si le besoin le justifie. La maîtrise des agents OpenClaw commence par cette discipline de conception — simple d'abord, complexe seulement si nécessaire.

Restez informé sur les agents IA

Nouveaux tutoriels, comparatifs et guides pratiques directement dans votre boîte mail.

homeAccueilcodeFrameworkssmart_toyAgentsmenu_bookTutorielsTwitter