Outils de classe Apex
Qu’est-ce qu’un outil de classe Apex ?
Classe Apex est le troisième type du générateur d’outils REDA AI, avec Modèle SOQL et Mappage de fichiers. Choisissez-le lorsque :
- Le traitement exige une logique conditionnelle, plusieurs étapes ou des écritures dans plusieurs objets.
- L’outil doit appeler un système externe.
- Vous devez rapprocher les données d’enregistrements existants, dédupliquer ou appliquer des règles métier avant l’écriture.
- La structure des données extraites d’un fichier dépasse les possibilités d’une correspondance déclarative.
La plateforme gère le contrat avec l’agent : schéma JSON, validation des entrées, traitement des erreurs, confirmation des actions, journalisation et formatage des résultats. Votre classe réalise le traitement métier et reste responsable de ses contrôles d’accès.
L’interface d’exécution
Chaque outil Apex implémente une même interface globale :
global interface REDAAI_Executable {
Object execute(String toolName, Map<String, Object> input);
}
Deux paramètres et une valeur de retour :
toolName: nom développeur de la définition d’outil à l’origine de l’appel. Utilisez-le si une classe implémente plusieurs outils et doit choisir le traitement correspondant.input: paramètres fournis par l’agent et validés selon votre Schéma d'entrée (JSON), avec la clé_channeldécrite ci-dessous.- Valeur de retour : dépend de la catégorie ; consultez Contrat de retour.
Connaître le canal d’exécution
Un même outil peut être appelé depuis une conversation interne dans Salesforce, un widget public ou un agent API autonome exécuté la nuit. Il est souvent utile d’adapter le résultat au canal. REDA AI ajoute donc des clés fournies par le serveur dans input avant l’appel, à commencer par le canal :
global class OrderLookupTool implements REDAAI_Executable {
global Object execute(String toolName, Map<String, Object> input) {
String channel = (String) input.get('_channel'); // 'Internal' | 'External_Widget' | 'Community' | 'API'
if (REDAAIConstants.CHANNEL_EXTERNAL_WIDGET.equals(channel)) {
return summaryForPublicVisitor(input); // no internal notes, no margins
}
return fullInternalDetail(input);
}
}
Les valeurs possibles sont Internal, External_Widget, Community et API, comme dans le champ Canal. Utilisez les constantes REDAAIConstants.CHANNEL_* plutôt que de recopier les valeurs. La plateforme fournit cette valeur, pas l’agent. Si le modèle tente de définir _channel, REDA AI l’écrase ; si le canal ne peut pas être résolu, la clé est supprimée. Une clé _channel présente est donc fiable ; son absence signifie « inconnu », jamais « Interne ».
_channel indique où l’outil s’exécute, pas ce qu’il est autorisé à faire. Ce contexte sert à adapter la réponse et son niveau de détail ; il ne constitue pas une autorisation. Ne considérez jamais _channel == 'API' comme un motif pour omettre un contrôle. Les accès aux objets et champs dépendent du contexte et de l’utilisateur, comme expliqué dans Accès aux données et autorisations. Un outil qui s’accorde lui-même des privilèges selon cette clé crée un modèle de sécurité incorrect.Deux autres clés sont transmises de la même manière, avec la même garantie d’écrasement ou de suppression. La plateforme les fournit et ignore toute valeur proposée par le modèle :
| Clé | Contenu | Utilisation |
|---|---|---|
_conversation_id |
Identifiant de la conversation dans laquelle l’outil s’exécute. | Rattacher une piste d’audit à la conversation ou résoudre sa configuration, notamment l’identité visuelle des e-mails. |
_agent_definition_id |
Identifiant de l’agent qui a appelé l’outil. | Adapter le comportement à l’agent ou consigner l’agent à l’origine d’une écriture. |
En l’absence de conversation ou d’agent dans le contexte, les clés sont supprimées plutôt que de conserver une valeur périmée. Comme pour _channel, une valeur présente est fiable et son absence signifie « inconnu ».
Les outils existants n’ont pas besoin d’être modifiés. Un outil qui ne lit pas _channel ignore simplement cette entrée supplémentaire et conserve son comportement.
Champs de la définition de l’outil
| Champ | Obligatoire | Objectif |
|---|---|---|
| Type d'outil | Oui | Définir sur Apex_Class. |
| Classe d'exécuteur testamentaire | Oui | Nom complet de la classe Apex d’exécution qui implémente REDAAI_Executable. Le libellé affiché « Classe d'exécuteur testamentaire » désigne ici cette classe technique. Les espaces de noms sont pris en charge, par exemple MyNs.OrderCreator. |
| Catégorie | Oui | Tool pour la lecture seule ; Action pour toute écriture ou autre effet. Choisissez selon le comportement réel de votre classe. |
| Description | Oui | Description en langage naturel transmise à l’agent pour l’aider à choisir l’outil. Précisez l’objectif, les entrées, les effets et les contraintes. |
| Schéma d'entrée (JSON) | Oui | Schéma JSON de type objet décrivant la Map input attendue. Il sert à valider l’appel avant d’invoquer la classe. |
| Le traitement des fichiers | Facultatif | Définir sur true si l’outil traite des données extraites d’un fichier chargé. Active le contexte d’extraction décrit ci-dessous. |
| Nécessite une confirmation | Facultatif | Pour les outils Action, contrôle la carte de confirmation avant exécution sur le canal interne. Activé par défaut pour les actions ; les autres canaux suivent leurs règles propres. |
| Niveau d'outil (obsolète), Chaînes, Nom de l'agent, Objets de contexte | Facultatif | Paramètres habituels : canaux, restriction à un agent et objets de contexte. Le niveau d’outil est obsolète et ignoré lors de l’exécution. |
Créer la classe Apex
Exemple minimal d’un exécuteur de catégorie Action créant un enregistrement :
global with sharing class MyToolExecutor implements redaai.REDAAI_Executable {
global Object execute(String toolName, Map<String, Object> input) {
try {
String name = (String) input.get('account_name');
Account a = new Account(Name = name);
insert as user a;
return new Map<String, Object>{
'success' => true,
'message' => 'Account created.',
'recordId' => a.Id
};
} catch (Exception e) {
return new Map<String, Object>{
'success' => false,
'message' => e.getMessage()
};
}
}
}
Points à relever :
- La classe est global. Public ne suffit pas : la plateforme l’instancie via une interface globale pour que les utilisateurs du package puissent fournir des implémentations dans leur propre espace de noms.
- La classe déclare
with sharing. La plateforme n’impose pas le partage à l’intérieur de votre code ; l’exécuteur est responsable de son modèle d’accès aux données. - La clause
insert as userexécute le DML en mode utilisateur et applique la sécurité au niveau des champs. C’est le choix recommandé par défaut, sauf motif explicite d’élévation. - Les erreurs sont interceptées et renvoyées de manière structurée. Les exceptions non interceptées sont journalisées, mais une réponse explicite donne à l’agent une information utile à transmettre.
Contrat de retour
La structure de retour dépend de Catégorie :
| Catégorie | Type de retour | Structure attendue |
|---|---|---|
Tool, lecture seule |
Chaîne JSON | Les données à montrer à l’agent : généralement un objet contenant un tableau records, un totalSize ou un résultat unique. Les erreurs utilisent { "error": "…" }. |
Action, écriture |
Map<String, Object> |
Au minimum, un booléen success et une chaîne message. Ajoutez recordId après une création ou modification pour permettre à l’agent de proposer un lien. |
Outils Apex pilotés par des fichiers
Activer Le traitement des fichiers avec true permet à l’agent de fournir les données extraites du fichier selon votre schéma. Le modèle extrait d’abord une structure, puis celle-ci est transmise à votre exécuteur dans la Map input.
Ce fonctionnement convient aux fichiers non tabulaires — PDF, images et documents mixtes — pour lesquels la correspondance simple entre colonnes et champs ne suffit pas.
Concevoir le schéma d’extraction
Le schéma décrit la structure des données extraites, pas le fichier brut. Pour un document de plusieurs lignes, l’agent peut produire :
{
"rows": [
{ "external_id": "INV-1001", "amount": 250.00, "due_date": "2026-05-01" },
{ "external_id": "INV-1002", "amount": 980.50, "due_date": "2026-05-15" }
]
}
Votre exécuteur parcourt ensuite rows, recherche les enregistrements correspondants, applique les règles métier nécessaires et écrit dans Salesforce.
Lorsque Le traitement des fichiers est activé dans le générateur d’outils, le générateur IA peut produire un exemple de structure extraite à partir d’un fichier représentatif. Utilisez cet exemple comme contrat pour écrire votre classe.
Nommage, package et résolution
- Visibilité de la classe : la classe et sa méthode
executedoivent toutes deux êtreglobal, paspublic. - Implémentation : la classe doit implémenter
redaai.REDAAI_Executable. - Longueur du nom : jusqu’à 255 caractères dans le champ Classe d'exécuteur testamentaire.
- Une classe pour plusieurs outils : un exécuteur peut servir plusieurs définitions et adapter son comportement selon
toolName.
public class et public Object execute(...) par global, puis à redéployer.Sécurité et gouvernance
- Vous êtes responsable de la sécurité du code. La plateforme n’impose pas la FLS ou le partage à l’intérieur de votre classe. Utilisez
with sharinget les approchesUSER_MODE/as user, sauf raison explicite d’élévation. - Reconnaissance de responsabilité à l’enregistrement. Lors du premier enregistrement d’un outil personnalisé — Apex, modèle SOQL ou correspondance de fichiers — vous acceptez une reconnaissance de responsabilité partagée pour sa sécurité, ses autorisations CRUD/FLS, son périmètre de données, la validation des entrées et sa conformité. REDA AI peut en effet l’appeler de façon autonome, y compris sur les canaux communauté et externe sans confirmation humaine. Votre acceptation, avec nom et horodatage, est enregistrée sur l’outil et complète le contrat-cadre de service REDA AI. Les outils intégrés du package ISV sont exemptés ; l’acceptation est conservée après modification et n’est requise qu’une fois par outil.
- Les entrées sont validées. La plateforme contrôle
inputselon le schéma avant l’appel de la classe. Effectuez néanmoins des conversions de type défensives et vérifiez les contraintes métier dans votre code. - La confirmation reste applicable. Pour la catégorie
Action, les paramètres de confirmation et d’exécution automatique déterminent la carte sur le canal interne. Les canaux externes et API suivent leurs règles propres. - Les erreurs sont journalisées. Les exceptions non interceptées créent des incidents REDA AI avec la conversation, l’outil et le contexte technique. Une réponse d’erreur claire reste préférable pour l’utilisateur ; le journal sert de filet de sécurité.
- Exécution synchrone. Les outils Apex s’exécutent directement pendant le tour de l’agent. Pour un traitement long, votre exécuteur doit lancer une tâche Queueable, Schedulable ou par lot, puis annoncer immédiatement que le travail a commencé.
Quand choisir Apex
| Besoin | Type d’outil adapté |
|---|---|
| Lire des enregistrements avec une requête paramétrée | Outil de modèle SOQL |
| Charger un CSV dans un objet avec une correspondance stable | Outil de correspondance de fichiers |
| Écriture dans plusieurs objets, conditions, déduplication, appels externes ou orchestration | Outil de classe Apex, décrit ici |
| Extraire des données structurées de PDF, images ou documents mixtes et agir sur ces données | Outil de classe Apex avec Le traitement des fichiers activé |
Bonnes pratiques
Rédigez une description précise. L’agent choisit l’outil principalement à partir de sa description. Expliquez ce qu’il fait, ce qu’il ne fait pas et ses conditions préalables.
Délimitez les schémas. Utilisez required, enum, maxLength et des types explicites. Un schéma précis réduit les entrées inattendues dans votre code.
Renvoyez toujours un message utile. Même en cas d’échec, renvoyez success: false et un message compréhensible. L’agent le transmet à l’utilisateur ; une erreur opaque rend la conversation confuse.
Terminez rapidement ou mettez en attente et annoncez-le. Évitez de bloquer le tour avec un appel externe lent. Effectuez le travail rapidement ou lancez un traitement asynchrone en indiquant qu’il est en cours.
Testez avec l’aperçu du générateur. Le panneau d’impact montre le schéma, la carte d’action et le contrat d’exécution. Repérez les écarts avant la première conversation réelle.
Questions fréquentes
Non. Elle peut appartenir à votre espace de noms, à votre package géré ou au code non géré d’une organisation cliente. Si elle implémente redaai.REDAAI_Executable et que le champ Classe d'exécuteur testamentaire permet de la résoudre, la plateforme peut l’appeler.
Oui. Le premier paramètre de execute() est le nom développeur de l’outil. Utilisez-le pour choisir la méthode appropriée et regrouper des opérations liées dans un même exécuteur.
Non. Elle applique les contrôles de ses outils intégrés, mais votre code est responsable de son propre accès aux données. Déclarez with sharing et utilisez as user / AccessLevel.USER_MODE pour les requêtes et le DML, sauf motif explicite d’élévation.
La plateforme l’intercepte, consigne un incident avec le contexte de conversation et renvoie une erreur générique à l’agent. L’utilisateur reçoit une explication plutôt qu’une trace technique. Intercepter l’erreur et renvoyer une réponse structurée permet de mieux maîtriser le message transmis.
L’appel execute() est synchrone pendant le tour. Pour un traitement long, l’exécuteur doit lancer une tâche Queueable ou planifiée et répondre immédiatement que le travail a commencé.
Activez-le lorsque l’outil agit sur des données extraites d’un fichier chargé. Le modèle traite d’abord le fichier et produit la structure décrite par votre schéma, qui est transmise à l’exécuteur. Vous n’avez donc pas à analyser vous-même le fichier brut.
Jusqu’à 10 000 caractères. Cela suffit à la plupart des outils. Si vous atteignez cette limite, envisagez de répartir les responsabilités entre plusieurs outils.
Prochaines étapes
Consultez Outils de modèle SOQL pour une simple requête paramétrée, ou Traitement des documents pour comprendre le parcours des fichiers dans REDA AI.