Outils dynamiques (outils dérivés par connexion)
Déclarez un outil de découverte pour que la plateforme provisionne à l'exécution des outils propres à une connexion — objets personnalisés, champs personnalisés, types d'enregistrement personnalisés — sans reconstruire ni republier l'artefact de code de l'extension.
Vue d'ensemble
Certaines plateformes (systèmes CRM, outils de ticketing, moteurs de workflow) ont des schémas qui dépendent de la configuration de chaque client. Un outil de découverte permet à la plateforme de demander à l'instance connectée « quels outils sont disponibles en ce moment ? » et de provisionner pour l'agent un catalogue d'outils dérivés propre à la connexion.
Ce qui ne change pas :
- L'artefact de code de l'extension n'est jamais reconstruit ni réenvoyé pour chaque client.
- Chaque outil dérivé s'exécute dans la même microVM Kata
extension_codeque l'outil statique qu'il encapsule. - Aucun nouveau code exécutable n'est introduit. Un outil dérivé est une vue typée plus étroite d'un exécuteur livré statiquement.
Fonctionnement
- Vous déclarez une capacité
dynamicToolsdans votre manifeste avec une référencediscoveryToolId— le slug d'un outil statique existant du même toolkit. - La plateforme accorde chaque identifiant d'exécuteur exact que vous avez déclaré, y compris les exécuteurs de suppression : automatiquement pour une extension installée explicitement, et lorsqu'un administrateur autorise la découverte pour une extension intégrée. L'octroi est toujours votre déclaration, jamais une liste envoyée avec la requête, et une extension qui ne déclare aucun outil dynamique ne peut en recevoir aucun.
- La plateforme exécute votre outil de découverte pour une connexion, via le chemin d'exécution gouverné existant.
- La plateforme applique un pipeline d'admission à six contrôles à chaque descripteur renvoyé par votre outil de découverte.
- Les descripteurs admis deviennent des outils propres à la connexion dans le catalogue de l'agent. Ils sont stockés dans Postgres et actualisés après les changements de configuration pertinents, lorsqu'une sous-fiche Tools périmée est ouverte depuis Provides, ou sur déclenchement manuel par un administrateur.
Déclarer des outils dynamiques dans votre manifeste
// sdk-authoring: defineToolkit(...)
defineToolkit({
id: "my-crm",
name: "My CRM",
// ... other toolkit fields ...
dynamicTools: {
discoveryToolId: "list-record-types", // slug of a static tool in this toolkit
executors: [
{ toolId: "create-record", effect: "write" },
{ toolId: "update-record", effect: "write" },
{ toolId: "get-record", effect: "read" },
],
refresh: { ttlSeconds: 3600 }, // optional staleness threshold
maxTools: 50, // optional; server cap is always enforced
},
});discoveryToolId
Doit être le slug d'un outil déjà déclaré dans le même toolkit. Il ne doit accepter
aucun paramètre obligatoire (ou uniquement des paramètres que la plateforme peut
fournir depuis le profileConfig de la connexion active). C'est le seul outil que la
plateforme appelle pour la découverte ; les descripteurs renvoyés ne sont jamais
sélectionnables par l'agent.
executors
Un tableau d'objets { toolId, effect } — la liste blanche des cibles de dispatch. Un
outil dérivé dont le dispatch.tool ne figure pas dans ce tableau est withheld
(retenu) à l'admission. Pour une extension installée, chaque exécuteur déclaré est
automatiquement inclus dans l'octroi par identifiant exact de la connexion, y compris
les exécuteurs étiquetés delete. C'est la confiance déléguée lorsqu'un administrateur
installe une extension signée ou accepte explicitement l'avertissement d'une extension
non signée.
effect classe l'action pour la présentation et les diagnostics de politique. Il ne
confère pas d'autorité : l'admission vérifie l'identifiant d'outil scopé exact de
l'exécuteur, et non l'effet déclaré ; minimiser un effet ne rapporte donc rien. Gardez
une déclaration exacte et n'incluez que les exécuteurs dont votre extension a
réellement besoin.
Le code de l'extension continue d'utiliser le slug de création à la fois dans
executors[].toolId et dans dispatch.tool. À l'installation, la plateforme résout ce
slug en une identité d'exécuteur scopée unique et non ambiguë avant d'appliquer le
contrôle d'admission par identifiant exact. Un descripteur qui fournit un identifiant
scopé différent n'est jamais réécrit et est rejeté.
Écrire l'outil de découverte
Votre outil de découverte renvoie un tableau d'objets DynamicToolDescriptor.
import type { DynamicToolDescriptor } from "@scrydon/sdk-authoring/extensions";
// Example: return one derived tool per custom object type
export async function listRecordTypes(ctx: ToolContext): Promise<DynamicToolDescriptor[]> {
const objectTypes = await ctx.http.get("/api/v2/object_types");
return objectTypes.map((obj) => ({
key: obj.id, // stable unique key for this descriptor
name: obj.label, // shown in the agent catalog (character-allowlisted)
description: obj.description ?? `Create a ${obj.label} record`,
input: {
type: "object",
properties: {
values: { type: "object" },
},
required: ["values"],
},
dispatch: {
tool: "create-record", // must be in the executors array above
bind: {
objectType: obj.id, // bound parameter value (not a credential or header)
},
},
}));
}Règles applicables aux champs du descripteur
| Champ | Obligatoire | Remarques |
|---|---|---|
key | Oui | Chaîne unique et stable. Utilisée pour une troncature de capacité déterministe. |
name | Oui | Filtré par liste blanche de caractères à l'admission. À garder court et lisible. |
description | Oui | Longueur plafonnée et caractères de contrôle supprimés à l'admission. |
input | Oui | Objet JSON Schema décrivant les paramètres qui restent visibles après la liaison. |
dispatch.tool | Oui | Slug exact d'un outil statique du même toolkit. Doit correspondre à un identifiant d'outil exécuteur figurant dans l'enveloppe d'octroi de l'administrateur. |
dispatch.bind | Oui | Valeurs de paramètres liées ; utilisez {} si aucune n'est nécessaire. Ne doit pas contenir de références à des identifiants, d'en-têtes HTTP, de surcharges d'URL ni de sélecteurs de connexion. |
Contrôles d'admission et rejet
La plateforme fait passer chaque descripteur par six contrôles avant de l'admettre :
- Validation structurelle — les descripteurs malformés sont rejetés.
- Liste blanche d'exécuteurs —
dispatch.tooldoit figurer dans l'octroi par identifiant exact de la connexion. Les descripteurs hors de cet ensemble sont retenus. Les octrois des extensions installées sont réconciliés à partir de l'artefact de code épinglé résolu par le serveur, jamais à partir d'une liste d'exécuteurs fournie par le navigateur. - Refus de liaison d'autorité — tout chemin
bindqui référence un identifiant, un en-tête HTTP, une URL ou un sélecteur de connexion est rejeté et ne peut pas être contourné par un administrateur. - Neutralisation du descripteur — les noms et descriptions sont nettoyés structurellement.
- Capacité — le nombre total d'outils admis est plafonné à
min(grant.maxTools, MAX_DERIVED_TOOLS_PER_CONNECTION). - Identité — un condensat portant sur le hash de l'artefact de code, l'identifiant de l'outil exécuteur, le contenu du descripteur et l'identifiant d'octroi est calculé puis stocké.
Les descripteurs withheld sont visibles par l'administrateur, qui peut élargir
l'enveloppe. Les descripteurs rejected ne peuvent être approuvés par aucun
administrateur.
Ce que voit l'agent
Les outils dérivés admis apparaissent dans le catalogue de l'agent avec :
id: l'identifiant scopé exact de l'outil exécuteur (par exempleorg:acme:my-crm:create-record)name: votredescriptor.nameneutralisédescription: votredescriptor.descriptionneutralisée- Schéma : dérivé de l'outil exécuteur, avec les valeurs
bindpré-remplies
L'agent ne peut voir ni les valeurs bind brutes ni l'identifiant d'octroi. Le
dispatch, la liaison des identifiants et la résolution des politiques sont identiques,
octet pour octet, à ceux de l'exécuteur statique.
Tester votre outil de découverte en local
Testez-le comme n'importe quel autre outil — isolément ou avec scrydon extension test :
scrydon extension test --tool list-record-typesPour un test de bout en bout de l'admission des outils dérivés, utilisez une connexion de préproduction et le panneau Provides → Tools de la page des paramètres de l'extension (décrit dans le guide administrateur).
Vérifiez au minimum les cas suivants :
- Une connexion nouvellement activée découvre des outils sans demande séparée concernant les exécuteurs.
- Les descripteurs de création, de modification et de suppression apparaissent pour les objets réels attendus.
- Deux connexions aux schémas différents affichent des catalogues différents.
- Sync now reflète les objets ajoutés ou supprimés.
- Une actualisation en échec laisse visible le dernier catalogue obtenu avec succès.
Limites
| Limite | Valeur |
|---|---|
| Nombre maximal d'outils dérivés par connexion | 500 (MAX_DERIVED_TOOLS_PER_CONNECTION) ; un octroi peut l'abaisser |
Longueur maximale de descriptor.name | 64 caractères (DESCRIPTOR_NAME_MAX) |
Longueur maximale de descriptor.description | 512 caractères (DESCRIPTOR_DESCRIPTION_MAX) |
Nombre maximal de clés dans dispatch.bind | 20 |
Longueur maximale d'une valeur dispatch.bind | 1024 caractères |
FAQ
Un outil dérivé peut-il appeler un exécuteur différent selon la connexion ?
Non. dispatch.tool est validé au moment de l'admission ; il doit s'agir du même slug
d'exécuteur que celui déclaré par le toolkit installé. Un résultat de découverte peut
utiliser différents exécuteurs déclarés pour différents descripteurs (par exemple
création, modification et suppression), mais il ne peut pas introduire un exécuteur
choisi par la connexion ou non déclaré.
La vérification est refaite à chaque compilation des outils d'un agent : un outil dérivé dont l'exécuteur n'est pas déclaré par son propre toolkit, ou appartient à une autre extension, est affiché comme indisponible et n'est jamais exécuté.
Que se passe-t-il lorsque je modifie le schéma de l'outil exécuteur ?
Les outils dérivés héritent du schéma de l'exécuteur, mises à jour comprises. L'ensemble admis est actualisé à la synchronisation suivante ; les descripteurs qui ne passent plus l'admission sont supprimés.
Un éditeur peut-il déclarer dynamicTools pour un outil Scrydon natif ?
Non. La première version prend uniquement en charge les connexions installées par une organisation.
Après une modification du code d’une extension installée ou de l’autorisation des outils d’une connexion, actualisez les outils découverts. Les outils admis pour un artefact ou une autorisation précédente restent indisponibles jusqu’à une nouvelle admission. Les clés de descripteur dupliquées sont rejetées ensemble ; les autres descripteurs valides peuvent toujours être admis.
Points de terminaison configurés par l’opérateur
Pour un service tel que Twenty dont l’hôte d’API dépend de la connexion, déclarez explicitement un point de terminaison non secret :
configFields: [{
key: "baseUrl",
label: "Instance URL",
required: true,
type: "url",
purpose: "endpoint",
}]Le code de l’extension peut construire ses URL à partir de ctx.profileConfig.baseUrl.
Le point de terminaison doit utiliser HTTPS sur le port 443, sans identifiants
intégrés, paramètres de requête ni fragment. Conservez les clés API dans les
identifiants de la connexion, jamais dans l’URL ou son chemin. Les autres chaînes de
configuration restent des espaces réservés du broker ; type: "url" seul ne rend pas
une valeur visible au code de l’extension.
Le code reçoit l’URL sous forme canonique — hôte en minuscules, sans port par
défaut, sans espaces autour, et sans / final lorsqu’elle n’a pas de chemin —
si bien que https://CRM.example.com/ arrive comme https://crm.example.com et
que ${baseUrl}/rest ne double jamais la barre oblique. Un chemin saisi par
l’administrateur est conservé tel quel, / final compris.
Un administrateur de l’organisation doit autoriser le domaine du point de terminaison
dans la liste d’autorisation de sortie (egress allowlist) de l’organisation.
Chaque exécution est liée au nom d’hôte exact configuré ; les sous-domaines et les
hôtes sans rapport ne sont pas autorisés implicitement. L’entrée doit comporter au
moins deux libellés (example.com, jamais un com seul), et un endpoint qui est
une adresse IP n’est jamais approuvé. La confiance accordée aux hôtes de l’éditeur
et les domaines par défaut de la plateforme ne remplacent pas cette autorisation.
Les protections relatives aux adresses publiques, à l’épinglage DNS, aux
redirections et aux adresses de métadonnées restent actives.