Protocole de Collaboration entre Agents (ACP)
Utilisez un dossier partagé comme bus de coordination portable pour les agents qui ne peuvent pas se transmettre de messages directement. ACP est un protocole strict : c'est une machine à états avec des événements structurés et des portes de préparation, et non une conversation libre en Markdown.
Tout agent compatible doit être capable de lire du Markdown et du JSON, d'écrire du Markdown, d'ajouter des événements JSONL et d'exécuter ou de reproduire exactement le comportement du script fourni. Ne pas s'appuyer sur les API de threads Codex, les hooks spécifiques à Claude, l'état propre à OpenCode, les métadonnées propres à Kiro, ou la mémoire de conversation cachée pour la correction.
Entrées Requises
Avant de commencer, exiger :
collaboration_folder: chemin absolu ou relatif au dépôt du dossier partagé.objective: ce que la collaboration doit décider ou produire.completion_gates: portes concrètes pour terminer la collaboration.participants: tous les identifiants des participants, tels queserver,reader,reviewer, ouagent-a.participant_id: l'identité de l'agent actuel.
Si une entrée requise est manquante, demandez-la avant de créer des fichiers ou d'écrire des événements. N'inventez pas de portes de complétion.
Fichiers
Les dossiers ACP utilisent ces fichiers :
protocol.json: objectif, participants, portes de complétion, phase actuelle, propriétaire de la proposition, participants en attente, et horodatages.events.jsonl: journal d'événements en ajout seulement. Chaque ligne est un objet JSON compact.proposal.md: proposition actuelle uniquement.review.md: avis structurés des participants.decisions.md: décisions acceptées uniquement.readiness.md: classification des questions ouvertes, blocages, éléments différés non bloquants, et préparation à l'implémentation.conclusion.md: conclusion finale de la discussion. Elle indique si l'on doit procéder, ne pas procéder, différer ou bloquer ; pourquoi ; comment implémenter ou pourquoi ne pas le faire ; et la prochaine action.
Ne créez ni n'utilisez state.log, discussion.md ou opinions.md. Ce ne sont pas des fichiers de protocole et ils ne doivent pas apparaître dans les portes de complétion ou les instructions.
Initialisation
Préférez le script fourni :
python3 <skill>/scripts/init_collaboration.py \
--folder <collaboration_folder> \
--participant <participant_id> \
--participant <autre_participant_id> \
--objective "<objectif>" \
--completion "<porte de complétion>" \
--completion "<autre porte>"
L'initialiseur échoue si protocol.json existe déjà, sauf si --resume est fourni. Une initialisation répétée n'est pas une opération d'ajout.
Événements
Utilisez scripts/append_event.py ou reproduisez exactement son comportement. N'écrivez pas d'événements à la main sauf si l'environnement d'exécution ne peut pas exécuter de scripts.
Champs requis pour les événements :
seq: entier continu dansevents.jsonl.from: identifiant du participant listé dansprotocol.json.event: nom d'événement autorisé.at: horodatage UTC ISO-8601.summary: une phrase courte.
Champs recommandés :
doc: chemin relatif au dossier de collaboration.reply_to:seqd'un événement antérieur.
Événements autorisés :
initializedproposal_submittedreview_submittedproposal_revisedquestion_classifieddecision_proposeddecision_acceptedreadiness_passedcompletedblocked
Toutes les réponses doivent utiliser reply_to lorsqu'elles répondent à un événement antérieur. reply_to doit pointer vers un événement existant antérieur. Les horodatages des événements ne doivent pas reculer à mesure que seq augmente. Si une erreur est découverte, ajoutez blocked ou un nouvel événement correctif ; ne réécrivez pas les événements antérieurs.
Phases
Les agents doivent agir selon protocol.json.currentPhase et protocol.json.waitingFor :
drafting: le propriétaire de la proposition met à jourproposal.md, puis ajouteproposal_submitted.reviewing: seuls les participants listés danswaitingForajoutent des avis structurés àreview.md, puis ajoutentreview_submitted.revising: le propriétaire de la proposition traite les changements requis et ajouteproposal_revised.decision_review: le propriétaire de la proposition classe d'abord chaque question ouverte dansreadiness.mdet ajoutequestion_classified; seulement alors les participants listés danswaitingForacceptent les décisions explicites dansdecisions.mden ajoutantdecision_accepted.readiness_check: les participants classent chaque question, lèvent les blocages et valident la préparation, puis le propriétaire de la proposition écritconclusion.md.completed: arrêtez-vous sauf si l'utilisateur démarre explicitement un nouveau cycle.blocked: arrêtez-vous jusqu'à ce que le blocage soit résolu.
completed n'est valide qu'après un événement readiness_passed antérieur. completed doit référencer conclusion.md. Ne terminez pas avec seulement decisions.md ; les décisions sont des entrées, tandis que conclusion.md est la réponse finale à l'objectif de collaboration.
Le propriétaire de la proposition doit attendre après proposal_submitted. Pendant que la phase est reviewing, le propriétaire peut interroger la prochaine action ou ajouter blocked pour un délai d'attente/blocage réel, mais ne doit pas modifier proposal.md, decisions.md, readiness.md ou protocol.json, et ne doit pas ajouter d'événements de progression jusqu'à ce que l'avis requis soit soumis.
Format de l'Avis
Chaque événement review_submitted doit avoir un en-tête correspondant dans review.md dont le seq est égal au seq de cet événement :
## <UTC ISO-8601> - <participant_id> - seq <seq de l'événement review_submitted>
Contexte :
- Lu `proposal.md` après l'événement seq `<seq>`.
Position :
- ...
Préoccupations :
- ...
Modifications Requises :
- ...
Questions :
- ...
N'utilisez pas le seq de l'événement auquel vous répondez dans l'en-tête de l'avis. Mettez le contexte de la réponse dans Contexte et reply_to.
Porte de Préparation
Avant readiness_passed ou completed :
- Chaque question ouverte doit être classée comme
[résolue],[différée_non_bloquante]ou[bloquante]. - Chaque élément
[différé_non_bloquant]doit inclureRaison : .... - Aucun élément
[bloquant]ou[non_résolu]ne doit subsister. - La liste de contrôle de conception finale doit inclure et cocher
Prêt à implémenter. validate_collaboration.pydoit réussir.
Les éléments de préparation bloquants empêchent également decision_accepted. Les questions non résolues et les éléments différés sans Raison : ... empêchent également decision_accepted.
Les documents de conception finale doivent séparer :
- Décisions Acceptées
- Hypothèses
- Suivis Différés
- Blocages d'Implémentation
- Prêt à Implémenter
Conclusion Finale
Avant completed, écrivez conclusion.md comme un document de conclusion, pas un journal. Il doit inclure :
- Résultat de la Décision : exactement un parmi
[procéder],[ne_pas_procéder]ou[différer]. - Justification.
- Décisions Acceptées.
- Approche d'Implémentation.
- Hypothèses.
- Suivis Différés.
- Blocages d'Implémentation.
- Prochaine Action.
Utilisez [procéder] lorsque l'implémentation doit commencer maintenant, [ne_pas_procéder] lorsque la fonctionnalité ou le plan ne doit pas être réalisé, et [différer] lorsqu'un travail de suivi doit avoir lieu avant l'implémentation. Un résultat [bloqué] peut exister tant que la collaboration est bloquée, mais il n'est pas finalisable.
Interrogation et Surveillants
Les participants doivent rester actifs pour la boucle de collaboration jusqu'à ce que la phase soit completed, blocked, ou qu'un délai explicite de l'utilisateur/coordinateur soit atteint. Ne vous arrêtez pas simplement parce que vous avez ajouté un événement valide. Après chaque action, relisez protocol.json et soit effectuez la prochaine action autorisée, soit attendez le prochain événement.
Si l'environnement d'exécution dispose d'un surveillant, il peut notifier le participant lorsque events.jsonl ou protocol.json change. Le surveillant doit rester passif : il ne fait que remarquer les changements et n'écrit jamais d'analyse ou de décisions.
S'il n'y a pas de surveillant, utilisez :
python3 <skill>/scripts/next_action.py \
--folder <collaboration_folder> \
--participant <participant_id>
Pour les participants autonomes, préférez l'assistant bloquant :
python3 <skill>/scripts/wait_for_turn.py \
--folder <collaboration_folder> \
--participant <participant_id>
wait_for_turn.py se termine lorsque le participant est listé dans waitingFor, ou lorsque la collaboration devient completed ou blocked. Il utilise un délai d'attente par défaut de 30 minutes pour éviter que les processus participants ne restent bloqués indéfiniment ; utilisez --timeout 0 uniquement lorsqu'un superviseur externe gère l'annulation. Au retour, inspectez next_action.py, agissez si c'est votre tour, ajoutez l'événement requis, et répétez la boucle d'attente/action. Les invites manuelles de l'utilisateur comme "vérifiez le nouvel avis" sont uniquement une solution de repli, pas la boucle de collaboration prévue.
Les invites du coordinateur qui lancent les participants doivent demander à chaque participant d'exécuter cette boucle au lieu de faire une phase et de sortir. Un participant qui n'est pas listé dans waitingFor peut bloquer dans wait_for_turn.py, mais ne doit pas modifier l'état partagé en attendant.
Validation
Exécutez :
python3 <skill>/scripts/validate_collaboration.py --folder <collaboration_folder>
Le validateur vérifie les fichiers requis, l'absence de fichiers obsolètes, la forme des événements, la continuité des seq, la monotonie des horodatages, les transitions de phase, la propriété waitingFor, reply_to, les séquences d'en-tête des avis, la classification de préparation, l'exhaustivité de la conclusion et l'ordre de complétion.
Codes de sortie :
0: valide.1: valide avec avertissements.2: invalide.