Protocole de connecteur Ajo (v1)
Le connecteur permet à l'agent d'agir dans votre système (site, back-office, ERP) sans que vous ayez à changer votre code métier : vous exposez deux routes, l'agent découvre vos outils et les appelle quand la conversation l'exige.
1. Les deux routes à exposer
GET {baseUrl}/manifest
POST {baseUrl}/tools/{toolName}GET /manifest
{
"protocol": "ajo.connector/v1",
"name": "Doubovo",
"tools": [
{
"name": "get_offer",
"description": "Formules d'abonnement en vente, prix unitaire du repas, frais de livraison.",
"input_schema": { "type": "object", "properties": {}, "additionalProperties": false },
"effect": "read"
},
{
"name": "start_subscription_checkout",
"description": "Crée l'abonnement en attente de paiement et renvoie le lien de paiement.",
"input_schema": {
"type": "object",
"properties": {
"planId": { "type": "string" },
"startOn": { "type": "string", "description": "Date AAAA-MM-JJ" }
},
"required": ["planId", "startOn"],
"additionalProperties": false
},
"effect": "write"
}
]
}descriptionest lue par l'agent : écrivez-la comme vous l'expliqueriez à un vendeur.input_schema: JSON Schema (sous-ensemble :object,string,number,integer,boolean,array,enum,required,description).effect:readouwrite. Un outilwriten'est jamais rejoué automatiquement.
POST /tools/{toolName}
Requête :
{
"input": { "planId": "pl_123", "startOn": "2026-11-16" },
"context": {
"organizationId": "org_…",
"conversationId": "cv_…",
"contact": { "phone": "+2290197000000", "name": "Awa", "externalId": null },
"locale": "fr",
"idempotencyKey": "tc_…"
}
}Réponse :
{ "ok": true, "data": { "paymentUrl": "https://…", "reference": "DBV-…", "amount": 16500 } }ou
{ "ok": false, "error": { "code": "OUT_OF_ZONE", "message": "Adresse hors zone de livraison" } }dataest transmis tel quel à l'agent : renvoyez des champs lisibles, sans secret.- Une erreur métier se renvoie en HTTP 200 avec
ok: false; l'agent l'explique au client. contact.phoneest le numéro prouvé : le message vient de ce numéro WhatsApp.idempotencyKeyest unique par appel d'outil : utilisez-la pour ne pas créer deux fois la même commande si un appel est rejoué après une coupure réseau.
2. Signature (dans les deux sens)
Chaque requête porte :
X-Ajo-Timestamp: 1763000000
X-Ajo-Signature: v1=<hex(HMAC_SHA256(secret, timestamp + "." + corpsBrut))>Rejetez une requête dont l'horodatage a plus de 5 minutes ou dont la signature ne correspond pas (comparaison à temps constant). Le secret est affiché une seule fois dans le tableau de bord (Réglages → Connecteur).
3. Vos événements vers Ajo
POST https://api.ajo.africa/v1/events
Authorization: Bearer ajo_live_…{
"type": "order.out_for_delivery",
"idempotencyKey": "evt_order_0192_ofd",
"contact": { "phone": "+2290197000000" },
"data": { "orderId": "0192…", "deliveryCode": "4821", "trackingUrl": "https://…" }
}Chaque type d'événement est relié, dans le tableau de bord, à une automatisation (template WhatsApp, note de contexte pour l'agent, tour d'agent immédiat ou non). Les types connus d'Ajo ont une automatisation par défaut ; les autres sont libres.
4. Bonnes pratiques
- Répondez en moins de 5 s (au-delà, l'agent annonce une vérification et réessaie une fois pour un outil
read). - Gardez peu d'outils, bien nommés, avec des descriptions précises : l'agent choisit mieux parmi 10 outils clairs que parmi 40 ambigus.
- Ne renvoyez jamais de données d'un autre client : le contexte vous donne le numéro prouvé, servez-vous-en pour filtrer.