Production
Mise en production
Gardez votre agent en ligne en permanence — reconnexion automatique, supervision du processus, secrets protégés et travail rejouable sans risque.
Un agent qui fonctionne dans votre terminal n'est qu'à une étape d'un agent fiable depuis votre téléphone. Cette page couvre cette étape.
Se reconnecter automatiquement
Le SDK ouvre une connexion. Les réseaux coupent, les portables se mettent en veille, les serveurs redémarrent : enveloppez le client dans une petite boucle qui recrée un client à partir de l'état enregistré et réessaie avec un délai croissant.
import {
createNodeAgentGatewayClient,
createNodeSignalSnapshotStore,
} from "@pacerelle/sdk/node";
const agentId = process.env.PACERELLE_AGENT_ID;
const token = process.env.PACERELLE_AGENT_TOKEN;
const delays = [1, 2, 5, 10, 30]; // secondes
let attempt = 0;
let generation = 0;
async function start() {
const current = ++generation;
const state = createNodeSignalSnapshotStore(agentId); // recharge le dernier état enregistré
const client = createNodeAgentGatewayClient({
agentId,
token,
e2ee: true,
signalSnapshot: state.signalSnapshot,
onSignalSnapshot: state.onSignalSnapshot,
onOpen: () => {
attempt = 0;
console.log("Connecté");
},
onClose: () => {
if (current === generation) retry(client);
},
onError: (error) => console.error("Erreur Pacerelle :", error),
});
client.onMessage(handleMessage);
try {
await client.connect();
} catch {
if (current === generation) retry(client);
}
}
function retry(client) {
generation++; // ignore les événements tardifs de l'ancien client
client.close();
const delay = delays[Math.min(attempt++, delays.length - 1)];
console.log(`Déconnecté. Nouvelle tentative dans ${delay} s…`);
setTimeout(start, delay * 1000);
}
await start();Les messages envoyés pendant que l'agent était hors ligne lui sont livrés à la reconnexion.
Avec Agent Connect, les jetons d'exécution durent 15 minutes :
demandez-en un nouveau dans start() avant de créer chaque client.
Conserver le fichier d'état
Le SDK enregistre sur disque les clés privées de l'agent et son journal de livraison :
| SDK | Emplacement par défaut | Pour le changer |
|---|---|---|
| JavaScript | ~/.pacerelle/agents/<agent-id>.signal.b64 | PACERELLE_AGENT_SIGNAL_STATE_FILE ou PACERELLE_AGENT_SIGNAL_STATE_DIR |
| Python | ~/.myagents/<agent-id>/signal.db | argument store_root= |
| Serveur MCP | ~/.pacerelle/mcp | PACERELLE_STORE_ROOT |
- Placez-le sur un stockage persistant — un volume Docker, pas le système de fichiers du conteneur.
- Limitez l'accès au compte qui exécute l'agent, et sauvegardez-le de façon sécurisée.
- Un processus par fichier d'état. Deux processus qui le partagent corrompent les sessions de l'agent.
Superviser le processus
Faites tourner l'agent comme un service qui démarre au boot et redémarre en cas d'échec.
[Unit]
Description=Mon agent Pacerelle
After=network-online.target
Wants=network-online.target
[Service]
User=agent
WorkingDirectory=/opt/mon-agent
EnvironmentFile=/opt/mon-agent/.env
ExecStart=/usr/bin/node agent.mjs
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetProtéger les secrets
- Gardez
PACERELLE_AGENT_TOKENdans un fichier d'environnement lisible uniquement par le compte de service, ou dans le gestionnaire de secrets de votre plateforme. - Ajoutez
.envà.gitignore. N'intégrez jamais de jeton dans une image. - Utilisez des agents distincts pour le développement, la préproduction et la production.
Rendre le travail idempotent
Un message peut être relivré si votre fonction échoue ou si le processus plante avant la fin.
Utilisez message.id comme clé d'idempotence pour tout ce qui a des effets :
client.onMessage(async (message, agent) => {
if (await jobs.exists(message.id)) return; // déjà traité
await jobs.create(message.id, message.text); // enregistrer avant de rendre la main
await agent.reply(message, { text: "C'est lancé, je reviens vers vous ici." });
});Un envoi confirme que le message a été remis à la connexion, pas qu'il a été affiché. Si un envoi échoue, vérifiez la conversation avant de répéter une action importante.
Journaliser sans risque
Journalisez les événements de connexion, les erreurs et les durées. Ne journalisez pas en production le texte des messages, le contenu des fichiers, les réponses aux widgets ni les jetons — c'est précisément ce que protège le chiffrement de bout en bout.
Faire tourner un jeton
- Remplacez le jeton dans l'application — l'ancien cesse aussitôt de fonctionner.
- Mettez à jour le secret là où tourne l'agent.
- Redémarrez le service et vérifiez que l'agent est de nouveau connecté.
Essayez-le une fois avant d'en avoir besoin en urgence.
Liste de contrôle
- L'agent se reconnecte seul après une coupure réseau.
- Il redémarre après un plantage et après un reboot.
- Le fichier d'état est sur un stockage persistant, privé et sauvegardé.
- Le jeton est dans un coffre à secrets, pas dans le code ni dans une image.
- Les effets de bord sont idempotents sur
message.id. - Les actions destructives ou externes passent par des widgets ou des autorisations.
- Les logs ne contiennent ni contenu de message ni secret.
- Développement et production utilisent des agents différents.