gigafibre-fsm/services/targo-hub/lib/agent-tools.json
louispaulb b40cf7d059 feat(assistant): capacités CLIENT 360 (solde, factures, abonnements, équipement, historique)
Le copilote STAFF peut répondre à toute question client. 5 lecteurs ajoutés
(audience:staff), réutilisant les getters du répondeur client (agent.execTool) :
- customer_overview : résumé 360 (identité + SOLDE + abonnements + tickets ouverts)
- customer_balance  : solde du compte + factures récentes
- customer_subscriptions / customer_equipment
- customer_history  : tickets passés → « un problème est-il déjà survenu ? »
Client résolu via find_customer (id C-xxxx) ; prompt mis à jour (règle QUESTIONS CLIENT).

Corrige aussi un bug LATENT : geminiChat n'avait pas reasoningEffort:'none' →
avec 35 outils le « thinking » de gemini-2.5-flash mangeait maxTokens et renvoyait
une réponse VIDE (« Aucune action détectée »). Thinking coupé + maxTokens 900→1200.

Vérifié live : « solde de C-LPB4 » → « 0 $, aucune facture impayée » ; « résume le
compte » → 360 (Louis-Paul Bourdon, solde, forfaits, 4 tickets) ; « un problème
déjà arrivé ? » → « 7 problèmes, dont 4 ouverts ». Régression OK (check_service, suspend).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 09:17:39 -04:00

39 lines
22 KiB
JSON

[
{ "type": "function", "function": { "name": "get_customer_info", "description": "Get customer account information: name, type, territory, contact details, flags", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string", "description": "Customer ID (e.g. C-LPB4)" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "get_subscriptions", "description": "Get active service subscriptions: plan names, prices, billing frequency, status", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "get_invoices", "description": "Get recent invoices: amounts, dates, payment status, outstanding balance", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" }, "limit": { "type": "number", "description": "Max invoices (default 5)" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "get_outstanding_balance", "description": "Get total outstanding (unpaid) balance across all invoices", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "get_service_locations", "description": "Get service locations (addresses) with connection type", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "get_equipment", "description": "Get equipment (routers, ONTs) installed: serial numbers, MAC, status", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "check_device_status", "description": "Quick snapshot of device status via TR-069 + SNMP. Returns online/offline, uptime, signal levels. NOTE: if the device appears offline, do NOT tell the customer it is offline — instead call start_connection_check to run a thorough background verification.", "parameters": { "type": "object", "properties": { "serial_number": { "type": "string", "description": "Device serial number" } }, "required": ["serial_number"] } } },
{ "type": "function", "function": { "name": "check_onu_status", "description": "Check ONU status from OLT SNMP: online/offline, signal levels, last offline cause (Dying Gasp, Branch Fiber Cut, LOSi), recent events history.", "parameters": { "type": "object", "properties": { "serial_number": { "type": "string", "description": "Device serial number (ONU serial)" } }, "required": ["serial_number"] } } },
{ "type": "function", "function": { "name": "start_connection_check", "description": "IMPORTANT: Use this tool instead of telling the customer their connection is offline. Launches a background verification that polls the device 3 times over ~90 seconds via both TR-069 and OLT SNMP, then automatically sends the diagnostic result to the customer. Tell the customer 'Nous vérifions votre connexion, un instant...' while the check runs. Do NOT announce the device as offline before this check completes.", "parameters": { "type": "object", "properties": { "serial_number": { "type": "string", "description": "Device serial number" }, "customer_id": { "type": "string", "description": "Customer ID" } }, "required": ["serial_number", "customer_id"] } } },
{ "type": "function", "function": { "name": "analyze_outage", "description": "Analyze a device outage by correlating with other ONUs on the same OLT port. Determines if the problem is isolated (single customer) or widespread (multiple customers affected). Returns severity, cause type (power outage, fiber cut, backbone issue), recommended action (none/simple_tech/fiber_splicer/escalate_noc). Use this after check_onu_status shows a device offline to understand the scope.", "parameters": { "type": "object", "properties": { "serial_number": { "type": "string", "description": "Device serial number (ONU serial)" } }, "required": ["serial_number"] } } },
{ "type": "function", "function": { "name": "get_open_tickets", "description": "Get open support tickets: subject, status, priority, date", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" } }, "required": ["customer_id"] } } },
{ "type": "function", "function": { "name": "create_ticket", "description": "Create a support ticket when customer reports a problem needing agent follow-up", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string" }, "subject": { "type": "string" }, "description": { "type": "string" }, "priority": { "type": "string", "enum": ["Low", "Medium", "High", "Urgent"] } }, "required": ["customer_id", "subject"] } } },
{ "type": "function", "function": { "name": "get_chat_link", "description": "Get the web chat link for this conversation so the customer can continue chatting in a browser instead of SMS", "parameters": { "type": "object", "properties": {} } } },
{ "type": "function", "function": { "name": "create_dispatch_job", "description": "Create an emergency dispatch job and auto-assign to the nearest available technician. Use when: device offline with fiber issue (Rx power < -25 dBm, Branch Fiber Cut), customer reports no internet and troubleshooting fails, or any situation requiring on-site technician.", "parameters": { "type": "object", "properties": { "customer_id": { "type": "string", "description": "Customer ID (e.g. C-LPB4)" }, "service_location": { "type": "string", "description": "Service Location name (from get_service_locations)" }, "subject": { "type": "string", "description": "Job description (e.g. 'Branch Fiber Cut - 691 rue des Hirondelles')" }, "priority": { "type": "string", "enum": ["low", "medium", "high"], "description": "Job priority (default: high for emergencies)" }, "job_type": { "type": "string", "enum": ["Installation", "Réparation", "Maintenance", "Retrait", "Dépannage", "Autre"], "description": "Type of work (default: Dépannage)" }, "notes": { "type": "string", "description": "Additional context (signal levels, error details, customer complaint)" } }, "required": ["customer_id", "subject"] } } },
{ "audience": "staff", "mode": "read", "title": "Lister les techniciens", "type": "function", "function": { "name": "list_technicians", "description": "STAFF/dispatch. Liste les techniciens (id, nom, statut, compétences). Sert à RÉSOUDRE un technicien par son nom (« Simon » → TECH-4693) avant d'assigner/planifier. Filtre optionnel par nom partiel et/ou compétence.", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "Nom partiel du technicien (optionnel)" }, "skill": { "type": "string", "description": "Compétence requise (optionnel), ex. fibre, monteur, sans-fil" } }, "required": [] } } },
{ "audience": "staff", "mode": "read", "title": "Détails du job", "type": "function", "function": { "name": "get_job", "description": "STAFF/dispatch. Détails d'un Dispatch Job (sujet, statut, technicien assigné, date/heure, client, lieu, durée). Sert à vérifier un job avant de le modifier/réassigner/reporter.", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job, ex. DJ-2026-0001 ou LEG-253958" } }, "required": ["job"] } } },
{ "audience": "staff", "mode": "read", "title": "Compétence requise (diagnostic)", "type": "function", "function": { "name": "resolve_skill", "description": "STAFF/dispatch. DIAGNOSTIC : à partir de la RAISON décrite en langage naturel (ex. « voir signal fibre », « pas d'internet », « installation », « ajout TV ») → détermine la/les COMPÉTENCE(S) terrain requise(s) + la confiance. LECTURE. À appeler AVANT de créer/assigner une intervention, pour cibler la ressource ; enchaîne ensuite find_slot (avec la compétence) pour la disponibilité. Si la raison est vague, pose UNE question avant.", "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "La raison / le problème décrit par l'utilisateur ou le client" }, "department": { "type": "string", "description": "Département/motif si déjà connu (optionnel)" } }, "required": ["text"] } } },
{ "audience": "staff", "mode": "read", "title": "Trouver un créneau", "type": "function", "function": { "name": "find_slot", "description": "STAFF/dispatch. Propose les meilleurs créneaux disponibles (technicien + date + heure) selon la durée et la compétence requise. LECTURE — ne réserve rien ; présente les options à l'utilisateur.", "parameters": { "type": "object", "properties": { "duration_h": { "type": "number", "description": "Durée en heures (défaut 1)" }, "skill": { "type": "string", "description": "Compétence requise (optionnel)" }, "after_date": { "type": "string", "description": "Chercher à partir de cette date AAAA-MM-JJ (défaut aujourd'hui)" } }, "required": [] } } },
{ "audience": "staff", "mode": "read", "title": "Ressources disponibles", "type": "function", "function": { "name": "resource_availability", "description": "STAFF/dispatch. DIAGNOSTIC : combien de techniciens QUALIFIÉS pour une compétence sont DISPONIBLES sur une période, et combien d'heures libres. LECTURE. À appeler après resolve_skill pour répondre « a-t-on la ressource ? » avant de proposer ; find_slot donnera ensuite les créneaux précis.", "parameters": { "type": "object", "properties": { "skill": { "type": "string", "description": "Compétence requise (issue de resolve_skill), ex. réparation, installation" }, "after_date": { "type": "string", "description": "Dès cette date AAAA-MM-JJ (défaut aujourd'hui)" }, "days": { "type": "number", "description": "Fenêtre en jours (défaut 7)" } }, "required": [] } } },
{ "audience": "staff", "mode": "read", "title": "État du service (modem/signal)", "type": "function", "function": { "name": "check_service", "description": "STAFF/dispatch. DIAGNOSTIC À DISTANCE : état LIVE du service d'un client — modem/ONU en ligne ou hors ligne, puissance du signal (Rx dBm), abonnement. LECTURE. À utiliser AVANT de proposer un déplacement pour un problème de connexion : si l'équipement est EN LIGNE, propose d'abord un correctif à distance (redémarrage) ; s'il est HORS LIGNE avec signal faible/nul, un déplacement (réparation) est justifié. Fournis customer (id C-xxxx) ou query (nom/adresse/téléphone/courriel).", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client (C-xxxx) si connu" }, "query": { "type": "string", "description": "Sinon : nom / adresse / téléphone / courriel du client" } }, "required": [] } } },
{ "audience": "staff", "mode": "read", "title": "Trouver un client", "type": "function", "function": { "name": "find_customer", "description": "STAFF. Recherche un client par nom / adresse / téléphone / courriel et renvoie les CANDIDATS probables. LECTURE. À appeler dès qu'un client n'est PAS déjà identifié par son id (C-xxxx) : UN seul candidat → prends son id et continue ; PLUSIEURS → NE DEVINE PAS, demande brièvement « lequel ? » — l'interface affiche la liste cliquable des candidats, ne les réénumère donc pas tous en texte. Enchaîne l'action avec l'id choisi.", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "Nom, adresse, téléphone ou courriel (même partiel)" } }, "required": ["query"] } } },
{ "audience": "staff", "mode": "read", "title": "Aperçu client (360)", "type": "function", "function": { "name": "customer_overview", "description": "STAFF. Aperçu 360 d'un client : identité, SOLDE du compte, abonnements actifs, tickets ouverts. LECTURE. Utilise pour « c'est qui ? », « résume le compte », l'état général. Fournis customer (id C-xxxx obtenu via find_customer).", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client C-xxxx (via find_customer)" } }, "required": ["customer"] } } },
{ "audience": "staff", "mode": "read", "title": "Solde et factures", "type": "function", "function": { "name": "customer_balance", "description": "STAFF. SOLDE du compte (montant total dû) + factures récentes (montants, dates, statut de paiement). LECTURE. Utilise pour « quel est le solde / le montant dû », « factures impayées ». Fournis customer (id C-xxxx).", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client C-xxxx" } }, "required": ["customer"] } } },
{ "audience": "staff", "mode": "read", "title": "Abonnements client", "type": "function", "function": { "name": "customer_subscriptions", "description": "STAFF. Abonnements / services du client : forfaits, prix, fréquence de facturation, statut. LECTURE. Fournis customer (id C-xxxx).", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client C-xxxx" } }, "required": ["customer"] } } },
{ "audience": "staff", "mode": "read", "title": "Équipement client", "type": "function", "function": { "name": "customer_equipment", "description": "STAFF. Équipement installé (ONU / modem / routeur) : n° de série, MAC, statut. LECTURE. Fournis customer (id C-xxxx). Pour l'état LIVE (en ligne / signal), utilise plutôt check_service.", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client C-xxxx" } }, "required": ["customer"] } } },
{ "audience": "staff", "mode": "read", "title": "Historique / problèmes client", "type": "function", "function": { "name": "customer_history", "description": "STAFF. Historique des tickets du client (tous statuts, récents d'abord) → répond « un problème est-il DÉJÀ survenu chez ce client ? ». LECTURE. Fournis customer (id C-xxxx).", "parameters": { "type": "object", "properties": { "customer": { "type": "string", "description": "ID client C-xxxx" } }, "required": ["customer"] } } },
{ "audience": "staff", "mode": "write", "permission": "create_jobs", "title": "Créer un job", "type": "function", "function": { "name": "create_job", "description": "STAFF/dispatch. Crée un Dispatch Job (intervention). ÉCRITURE — proposée puis confirmée par l'utilisateur avant exécution. auto_assign=true assigne au meilleur tech disponible.", "parameters": { "type": "object", "properties": { "subject": { "type": "string", "description": "Description du travail" }, "customer_id": { "type": "string", "description": "ID client (optionnel)" }, "service_location": { "type": "string", "description": "Nom du lieu de service (optionnel)" }, "address": { "type": "string", "description": "Adresse civique de l'intervention (texte libre, ex. « 2338 rue Ste-Clotilde ») — si aucun lieu de service lié" }, "priority": { "type": "string", "enum": ["low", "medium", "high"], "description": "Priorité (défaut high pour urgence, medium sinon)" }, "job_type": { "type": "string", "enum": ["Installation", "Réparation", "Maintenance", "Retrait", "Dépannage", "Autre"], "description": "Type de travail (défaut Dépannage)" }, "notes": { "type": "string", "description": "Contexte additionnel" }, "auto_assign": { "type": "boolean", "description": "Assigner automatiquement au meilleur tech dispo (défaut true)" } }, "required": ["subject"] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Assigner un technicien", "type": "function", "function": { "name": "assign_tech", "description": "STAFF/dispatch. Assigne OU réassigne un Dispatch Job à un technicien (pose aussi l'heure au premier trou libre du quart). ÉCRITURE — confirmée avant exécution. Résous d'abord le tech via list_technicians pour obtenir tech_id.", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job" }, "tech_id": { "type": "string", "description": "id du technicien (TECH-xxxx), via list_technicians" }, "date": { "type": "string", "description": "Date AAAA-MM-JJ (optionnel)" }, "start": { "type": "string", "description": "Heure HH:MM (optionnel)" } }, "required": ["job", "tech_id"] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Ajouter un assistant", "type": "function", "function": { "name": "add_assistant", "description": "STAFF/dispatch. Ajoute un technicien en renfort (assistant) sur un job — le tech assigné (lead) reste inchangé. ÉCRITURE — confirmée avant exécution.", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job" }, "tech_id": { "type": "string", "description": "id du technicien assistant (TECH-xxxx)" }, "tech_name": { "type": "string", "description": "Nom du technicien (optionnel, pour l'affichage)" } }, "required": ["job", "tech_id"] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Changer le statut", "type": "function", "function": { "name": "set_job_status", "description": "STAFF/dispatch. Change le statut d'un Dispatch Job. ÉCRITURE — confirmée avant exécution. Cancelled = annuler l'intervention (conséquent).", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job" }, "status": { "type": "string", "enum": ["open", "On Hold", "Cancelled", "assigned"], "description": "Nouveau statut" } }, "required": ["job", "status"] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Reporter le rendez-vous", "type": "function", "function": { "name": "reschedule_job", "description": "STAFF/dispatch. Reporte un Dispatch Job à une nouvelle date (et heure). Conserve le technicien assigné si possible. ÉCRITURE — confirmée avant exécution.", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job" }, "date": { "type": "string", "description": "Nouvelle date AAAA-MM-JJ" }, "start": { "type": "string", "description": "Nouvelle heure HH:MM (optionnel)" } }, "required": ["job", "date"] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Proposer un RDV au client", "type": "function", "function": { "name": "proposer_rdv_client", "description": "STAFF/dispatch. Envoie au CLIENT un lien (par texto) pour qu'il choisisse LUI-MÊME son rendez-vous : soit il prend un créneau proposé (réservé 5 min), soit il propose ses 3 disponibilités. À utiliser après un diagnostic quand une intervention est requise mais qu'on laisse le client choisir l'heure, plutôt que d'assigner soi-même un technicien. ÉCRITURE — confirmée avant exécution. Requiert un Dispatch Job OUVERT : fournis job, ou ticket (Issue source), ou customer_id pour le retrouver.", "parameters": { "type": "object", "properties": { "job": { "type": "string", "description": "Identifiant du Dispatch Job (optionnel si ticket/customer_id fourni)" }, "ticket": { "type": "string", "description": "Ticket/Issue source (optionnel) — retrouve le job ouvert lié" }, "customer_id": { "type": "string", "description": "ID client (optionnel) — retrouve son dernier job ouvert" }, "message": { "type": "string", "description": "Message texto personnalisé (optionnel)" } }, "required": [] } } },
{ "audience": "staff", "mode": "write", "permission": "assign_jobs", "title": "Créer un horaire récurrent", "type": "function", "function": { "name": "create_recurring_shift", "description": "STAFF/planification. Définit le QUART RÉCURRENT (horaire hebdomadaire) d'un technicien — matérialisé automatiquement en assignations sur l'horizon. ÉCRITURE — confirmée avant exécution. days = jours travaillés parmi mon,tue,wed,thu,fri,sat,sun. « jours de semaine » = mon,tue,wed,thu,fri ; retire les exceptions demandées (ex. « sauf le vendredi » → mon,tue,wed,thu). « fin de semaine » = sat,sun. Convertis « 8-16h » en start 08:00 / end 16:00.", "parameters": { "type": "object", "properties": { "technicien_id": { "type": "string", "description": "id du technicien (TECH-xxxx), via list_technicians" }, "days": { "type": "array", "items": { "type": "string" }, "description": "Jours travaillés: mon,tue,wed,thu,fri,sat,sun" }, "start": { "type": "string", "description": "Heure de début HH:MM, ex. 08:00" }, "end": { "type": "string", "description": "Heure de fin HH:MM, ex. 16:00" } }, "required": ["technicien_id", "days", "start", "end"] } } },
{ "audience": "staff", "mode": "write", "title": "Suivre", "type": "function", "function": { "name": "follow_doc", "description": "STAFF. (Dé)suivre un job ou un ticket pour recevoir les notifications de mise à jour (l'utilisateur connecté devient abonné). ÉCRITURE légère — confirmée avant exécution.", "parameters": { "type": "object", "properties": { "doctype": { "type": "string", "enum": ["Dispatch Job", "Issue"], "description": "Type de document à suivre" }, "name": { "type": "string", "description": "Identifiant du job ou du ticket" }, "follow": { "type": "boolean", "description": "true = suivre (défaut), false = ne plus suivre" } }, "required": ["doctype", "name"] } } },
{ "audience": "staff", "mode": "write", "permission": "reboot_provision", "title": "Action équipement (OLT)", "type": "function", "function": { "name": "device_action", "description": "STAFF/réseau (Do Stuff). Opération à distance sur l'ONU/modem d'un client via l'OLT. ÉCRITURE RÉSEAU — proposée avec un APERÇU (effet, cible, avertissements) puis CONFIRMÉE avant exécution ; idempotente ; l'acteur est journalisé. À utiliser après check_service pour un CORRECTIF À DISTANCE avant d'envoyer un technicien (ex. redémarrer un modem en ligne). Actions : reboot (redémarrer l'ONU) · speed (changer le forfait / profil de ligne, l'ONU redémarre) · suspend (couper l'internet, bascule VLAN) · unsuspend (rétablir l'internet) · activate (provisionner l'ONU) · replace (remplacer le n° de série) · remove (retirer / désactiver l'ONU). Fournis serial (n° de série ONU) OU customer_id (on résout l'ONU du client). profileid requis pour activate / speed ; new_sn requis pour replace.", "parameters": { "type": "object", "properties": { "action": { "type": "string", "enum": ["reboot", "speed", "suspend", "unsuspend", "activate", "replace", "remove"], "description": "Opération à exécuter sur l'ONU" }, "serial": { "type": "string", "description": "Numéro de série de l'ONU (ex. TPLGxxxx, RCMGxxxx)" }, "customer_id": { "type": "string", "description": "ID client (C-xxxx) — si le serial est inconnu, on résout l'ONU du client" }, "profileid": { "type": "string", "description": "N° de profil de ligne (requis pour activate et speed)" }, "new_sn": { "type": "string", "description": "Nouveau numéro de série (requis pour replace)" } }, "required": ["action"] } } }
]