Référence SDK
Référence API complète pour le SDK @scrydon/sdk-authoring/integrations
Installation
bun add -d @scrydon/sdk-authoring/integrations zodnpm install --save-dev @scrydon/sdk-authoring/integrations zodChemins d'importation
Le SDK utilise des exports de sous-chemins explicites — il n'existe pas d'import barrel racine.
// Helpers de définition (toutes les fonctions define*)
import {
defineVendor, defineProduct, defineTool, defineBlock, defineTriggerBlock,
defineCapabilityLLM, defineCapabilitySTT, defineCapabilityTTS,
defineCapabilityEmbedding, defineCapabilityVideo, defineCapabilityOCR,
defineCapabilityWebhook, defineCapabilityDiscovery,
} from "@scrydon/sdk-authoring/integrations/define";
// Types de runtime (utilisés dans les signatures execute())
import type {
PureContext, PureContextAuth, ToolResponse, ExecutorResult,
RealtimeSession, RealtimeMessage,
} from "@scrydon/sdk-authoring/integrations/context";
// Helpers de filtrage des credentials (lèvent une CredentialKindError en cas de type incompatible)
import {
requireOAuthToken, requireOAuth,
requireApiKey, requireBasicAuth, requireBotToken,
} from "@scrydon/sdk-authoring/integrations/context";
// Types du manifeste (pour les cas d'usage avancés)
import type { ManifestSchema } from "@scrydon/sdk-authoring/integrations/manifest";defineVendor(config)
Conteneur de niveau supérieur pour une intégration. L'export par défaut du point d'entrée doit être le résultat d'un appel à defineVendor().
interface VendorInput {
/** Identifiant unique du fournisseur — alphanumérique minuscule + tirets, commence par une lettre */
id: string;
/** Nom d'affichage */
name: string;
/** Version sémantique (ex. "1.0.0") */
version: string;
/** Description courte */
description?: string;
/** Couleur de marque en hexadécimal (ex. "#FF6B35") */
color?: string;
/** Icône SVG sous forme de chaîne */
icon: string;
/** URL du site web du fournisseur */
website?: string;
/** URL de la documentation */
docsUrl?: string;
/** Catégories (ex. ["tools"], ["llm"], ["database"]) */
categories?: string[];
/** Indique si ce fournisseur est activé par défaut pour les nouvelles organisations */
defaultEnabled?: boolean;
/** Indique si ce fournisseur prend en charge le mode système (client_credentials) */
supportsSystemMode?: boolean;
/** Indique si ce fournisseur nécessite une connectivité réseau externe */
connectivity?: "cloud" | "local" | "hybrid";
/** Configuration de l'authentification */
auth: AuthConfig;
/** Champs configurables par l'administrateur (ex. URL de base pour les services auto-hébergés) */
configFields?: ConfigFieldInput[];
/** Secrets au niveau du fournisseur (résolus par invocation via le Dapr Secret Store) */
secrets?: SecretInput[];
/** Un ou plusieurs produits */
products: ProductDefinition[];
/** Définitions de protocoles optionnelles */
protocols?: ProtocolDefinition[];
/** Configuration du fournisseur LLM (pour les fournisseurs de modèles d'IA) */
llm?: VendorLLMDef;
}Configuration de l'authentification
Le champ auth définit les types de credentials pris en charge par votre fournisseur :
auth: {
credentials: {
none: { type: "none" },
},
default: "none",
}auth: {
credentials: {
apiKey: {
type: "apiKey",
label: "API Key",
description: "Your service API key",
headerName: "Authorization", // HTTP header name
headerPrefix: "Bearer", // Prefix before the key value
},
},
default: "apiKey",
}auth: {
credentials: {
oauth: {
type: "oauth",
label: "Connect Account",
authorizationUrl: "https://example.com/oauth/authorize",
tokenUrl: "https://example.com/oauth/token",
scopes: ["read", "write"],
pkce: true,
useBasicAuth: false,
supportsRefreshTokenRotation: true,
},
},
default: "oauth",
}auth: {
credentials: {
botToken: {
type: "botToken",
label: "Bot Token",
description: "Your bot authentication token",
headerName: "Authorization",
headerPrefix: "Bot",
},
},
default: "botToken",
}Vous pouvez définir plusieurs types de credentials et laisser l'utilisateur choisir :
auth: {
credentials: {
oauth: { type: "oauth", /* ... */ },
apiKey: { type: "apiKey", /* ... */ },
},
default: "oauth", // Lequel afficher en premier
}Champs de configuration
Pour les fournisseurs nécessitant des paramètres configurés par l'administrateur (ex. une URL de base auto-hébergée) :
configFields: [
{
key: "baseUrl",
label: "Base URL",
placeholder: "https://your-instance.example.com",
description: "The base URL of your self-hosted instance",
required: true,
type: "url",
},
],Secrets
Pour les secrets au niveau du fournisseur stockés dans le Dapr Secret Store :
secrets: [
{
key: "WEBHOOK_SIGNING_SECRET",
label: "Webhook Signing Secret",
description: "Used to verify incoming webhook payloads",
required: true,
},
],Les secrets sont disponibles au moment de l'exécution via ctx.secrets["WEBHOOK_SIGNING_SECRET"].
defineProduct(config)
Regroupe des outils et un bloc sous un produit pouvant être activé ou désactivé par organisation.
interface ProductInput {
/** Identifiant unique du produit au sein du fournisseur */
id: string;
/** Nom d'affichage */
name: string;
/** Description courte */
description?: string;
/** Icône SVG sous forme de chaîne (utilise l'icône du fournisseur si absent) */
icon?: string;
/** Référence au credential d'auth.credentials utilisé par ce produit */
credentialRef?: string;
/** Scopes OAuth requis par ce produit */
credentialScopes?: string[];
/** Capacités de runtime */
capabilities: {
tools?: ToolDefinition[];
triggers?: TriggerDefinition[];
runtimes?: {
llm?: LLMCapability;
stt?: STTCapability;
tts?: TTSCapability;
embedding?: EmbeddingCapability;
video?: VideoCapability;
ocr?: OCRCapability;
};
webhooks?: WebhookCapability;
discovery?: DiscoveryCapability;
};
/** La définition du bloc pour l'éditeur de workflow */
block: BlockDefinition;
/** Dépendances NPM (pour l'évaluation des risques au moment de l'upload) */
dependencies?: Array<{
type: "npm";
package: string;
version: string;
reason?: string;
}>;Le tableau dependencies sert de contexte lisible par un humain — chaque entrée inclut un reason expliquant pourquoi la dépendance est nécessaire. La CLI génère automatiquement un SBOM lisible par machine (meta/sbom.cdx.json) qui capture l'ensemble complet des paquets intégrés avec leurs versions et licences. Les deux sont complémentaires : les dépendances déclarées expliquent l'intention, le SBOM fournit l'inventaire auditables.
/** Configuration du mode système (client_credentials) */
systemMode?: {
supported: boolean;
permissions?: string[];
resources?: Array<{
resourceType: string;
displayName: string;
description?: string;
required: boolean;
allowMultiple?: boolean;
}>;
};
}Extensions de consentement système
Les credentials OAuth peuvent déclarer des points d'extension sûrs pour le manifeste afin de gérer des flux de configuration spécifiques au fournisseur, comme le consentement administrateur Microsoft. Cette logique doit rester dans l'intégration : le manifeste doit décrire la forme de l'URL du fournisseur, les champs de configuration de l'organisation requis, et les paramètres de rappel (callback).
Pour la plupart des fournisseurs, implémentez le consentement système via un modèle de redirection déclaratif. C'est la voie recommandée lorsque la plateforme n'a besoin que de construire une URL à partir de valeurs de runtime :
auth: {
credentials: {
oauth: {
type: "oauth",
label: "Microsoft Account",
authorizationUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize",
tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token",
requiredConfig: ["tenantId"],
supportsClientCredentials: true,
clientCredentialScopes: ["https://graph.microsoft.com/.default"],
extensions: {
systemConsent: {
kind: "redirect-template",
urlTemplate: "https://login.microsoftonline.com/{tenantId}/adminconsent",
params: {
client_id: "{clientId}",
redirect_uri: "{redirectUri}",
scope: "{scope}",
state: "{state}",
},
requiredConfig: ["tenantId"],
callback: {
successParam: "admin_consent",
tenantParam: "tenant",
},
},
},
},
},
}La plateforme substitue ces espaces réservés :
| Espace réservé | Valeur |
|---|---|
{clientId} | ID client OAuth résolu pour l'organisation |
{redirectUri} | URL de rappel de consentement administrateur de la plateforme |
{scope} | clientCredentialScopes joints par un espace |
{state} | État CSRF généré par la plateforme |
Toute clé requiredConfig, comme {tenantId} | Valeur de configuration du fournisseur pour l'organisation |
Si un fournisseur ne peut pas être représenté sous forme de modèle d'URL, déclarez une référence de gestionnaire dans le manifeste et implémentez la méthode référencée dans le runtime du fournisseur. La méthode doit être pure : accepter des valeurs de runtime résolues, valider toute configuration spécifique au fournisseur requise, et retourner l'URL de redirection plutôt que de coder en dur la logique du fournisseur dans la plateforme.
extensions: {
systemConsent: {
kind: "handler",
handlerRef: "microsoft.systemConsent.buildUrl",
callback: {
handlerRef: "microsoft.systemConsent.callback",
},
},
}type SystemConsentBuildUrlInput = {
clientId: string;
redirectUri: string;
state?: string;
scopes: string[];
providerConfig: Record<string, string | undefined>;
};
export async function buildUrl(input: SystemConsentBuildUrlInput): Promise<string> {
const tenantId = input.providerConfig.tenantId;
if (!tenantId) {
throw new Error("Microsoft admin consent requires tenantId");
}
const url = new URL(`https://login.microsoftonline.com/${tenantId}/adminconsent`);
url.searchParams.set("client_id", input.clientId);
url.searchParams.set("redirect_uri", input.redirectUri);
url.searchParams.set("scope", input.scopes.join(" "));
if (input.state) {
url.searchParams.set("state", input.state);
}
return url.toString();
}
type SystemConsentCallbackInput = {
query: Record<string, string | undefined>;
providerConfig: Record<string, string | undefined>;
};
export async function callback(input: SystemConsentCallbackInput) {
return {
approved: input.query.admin_consent === "True",
tenantId: input.query.tenant,
};
}Les références de gestionnaire sont des métadonnées du manifeste. Les bundles uploadés doivent aujourd'hui utiliser kind: "redirect-template", sauf si l'application hôte a explicitement câblé l'exécution du runtime pour le gestionnaire référencé.
Fournisseurs multi-produits
Les fournisseurs comme Google ou Microsoft ont plusieurs produits. Chaque produit dispose de son propre bloc dans l'éditeur de workflow et peut être activé indépendamment :
export default defineVendor({
id: "acme",
// ...
products: [
defineProduct({
id: "acme-crm",
name: "Acme CRM",
block: crmBlock,
capabilities: { tools: [listContacts, createContact] },
}),
defineProduct({
id: "acme-email",
name: "Acme Email",
block: emailBlock,
capabilities: { tools: [sendEmail, listInbox] },
}),
],
});defineTool(config)
Définit la logique de runtime d'un outil. C'est ici que se font vos appels API réels, transformations de données ou calculs.
interface ToolInput<TInput, TOutput> {
/** Identifiant unique de l'outil — convention : {vendor}:{product}:{action} */
id: string;
/** Nom d'affichage */
name: string;
/** Version sémantique */
version: string;
/** Description affichée aux utilisateurs et aux agents LLM */
description?: string;
/** Schéma Zod pour la validation de l'entrée */
input: z.ZodType<TInput>;
/** Schéma Zod pour la validation de la sortie */
output: z.ZodType<TOutput>;
/** Métadonnées des paramètres — contrôle la visibilité dans l'interface et auprès des LLM */
params?: Record<string, ParamDef>;
/** La fonction exécutée lors de l'invocation de cet outil */
execute: (input: TInput, ctx: PureContext) => Promise<ToolResponse<TOutput>>;
}
interface ParamDef {
type: string;
required?: boolean;
description?: string;
default?: unknown;
/** Contrôle l'endroit où ce paramètre apparaît */
visibility?: "user-only" | "user-or-llm" | "hidden";
}Visibilité des paramètres
| Visibilité | Qui peut fournir la valeur | Cas d'usage |
|---|---|---|
user-or-llm | L'utilisateur la définit dans l'interface, ou un agent IA la génère | La plupart des paramètres |
user-only | Seul l'utilisateur peut la configurer (masquée du LLM) | Paramètres de connexion, credentials |
hidden | Non affichée dans l'interface ni au LLM — définie par programmation | Identifiants internes, valeurs calculées |
Fonction d'exécution
La fonction execute reçoit l'entrée validée et un PureContext :
import { requireOAuthToken } from "@scrydon/sdk-authoring/integrations/context";
async execute(input, ctx) {
// Utiliser le logger (visible dans les journaux d'exécution du workflow)
ctx.logger.info(`Processing request for org ${ctx.execution.orgId}`);
// Filtrer sur ctx.auth.kind avant de lire les champs de credential.
// Cet exemple suppose que le fournisseur déclare un credential OAuth —
// requireOAuthToken lève une CredentialKindError si le type ne correspond pas.
const accessToken = requireOAuthToken(ctx.auth);
// Effectuer des appels API authentifiés
const response = await fetch("https://api.example.com/data", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(input),
});
if (!response.ok) {
return {
success: false,
output: { error: `API returned ${response.status}` },
error: `HTTP ${response.status}: ${response.statusText}`,
};
}
const data = await response.json();
return {
success: true,
output: data,
metadata: { requestId: response.headers.get("x-request-id") },
};
},PureContext
L'interface PureContext est la seule interface entre la plateforme et le code du bundle. Elle est injectée dans chaque appel à execute() au moment de l'exécution :
/**
* Union discriminée de toutes les formes de credentials que la plateforme peut injecter.
* Filtrez toujours sur `kind` avant de lire les champs de credential.
* Importez les helpers de filtrage depuis @scrydon/sdk-authoring/integrations/context :
* requireOAuthToken(auth) → string (accessToken, lève une erreur en cas d'incompatibilité)
* requireOAuth(auth) → { accessToken, refreshToken?, tokenType?, expiresAt? }
* requireApiKey(auth) → string (apiKey)
* requireBasicAuth(auth) → { username, password }
* requireBotToken(auth) → string (botToken)
* Chaque helper lève une CredentialKindError avec un message actionnable en cas d'incompatibilité.
*/
type PureContextAuth =
| { kind: "oauth"; accessToken: string; refreshToken?: string; tokenType?: string; expiresAt?: number }
| { kind: "apiKey"; apiKey: string }
| { kind: "basicAuth"; username: string; password: string }
| { kind: "botToken"; botToken: string }
| { kind: "none" };
interface PureContext {
/** Credential résolu par la plateforme avant l'invocation */
auth: PureContextAuth;
/** Métadonnées d'exécution pour la journalisation et la corrélation */
execution: {
executionId: string; // Identifiant unique de l'exécution
workflowId?: string; // Identifiant du workflow (si exécuté dans un workflow)
nodeId?: string; // Identifiant du nœud de bloc dans le workflow
orgId: string; // Identifiant de l'organisation
workspaceId?: string; // Identifiant de l'espace de travail
userId?: string; // Utilisateur qui a déclenché l'exécution
};
/** Logger structuré — les appels console sont interceptés dans le sandbox */
logger: {
info(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
debug(message: string, ...args: unknown[]): void;
};
/** Secrets du fournisseur configurés par l'administrateur de l'organisation (résolus par invocation via le Dapr Secret Store) */
secrets: Record<string, string>;
/** Présent lors de l'exécution via un Profil d'intégration — contient les remplacements spécifiques au profil */
profileConfig?: Record<string, unknown>;
}PureContext est importé depuis @scrydon/sdk-authoring/integrations/context. La plateforme le construit avant chaque invocation d'outil — votre code n'a jamais besoin d'en créer un manuellement. Tous les champs sauf auth et execution peuvent être des objets vides si non applicables. auth est une union discriminée (PureContextAuth) ; filtrez toujours sur auth.kind ou utilisez un helper require* avant d'accéder aux champs spécifiques au credential. Consultez Modes d'authentification pour la référence complète de la forme par mode.
ToolResponse
Chaque execute() doit retourner un ToolResponse :
interface ToolResponse<T = unknown> {
/** Indique si l'exécution de l'outil a réussi */
success: boolean;
/** Les données de sortie typées */
output: T;
/** Message d'erreur (affiché à l'utilisateur si success est false) */
error?: string;
/** Métadonnées optionnelles (journalisées mais non transmises aux blocs en aval) */
metadata?: Record<string, unknown>;
}defineBlock(config)
Définit l'interface utilisateur de l'éditeur de workflow — comment le bloc apparaît, quels champs de formulaire il contient et comment les données le traversent.
interface BlockInput {
/** Type de bloc unique — minuscule avec underscores (ex. "acme_crm") */
type: string;
/** Nom d'affichage dans la palette de blocs */
name: string;
/** Description courte */
description?: string;
/** Catégorie du bloc — utiliser "integration" pour les blocs de bundle */
category: string;
/** Couleur de fond en hexadécimal */
bgColor?: string;
/** Mode d'auth : "none", "apiKey", "oauth", "botToken" */
authMode?: string;
/** Champs de formulaire affichés dans le panneau du bloc */
subBlocks?: SubBlockInput[];
/** Les outils que ce bloc peut invoquer */
tools?: {
access: string[];
config?: {
/** Sélection dynamique d'outil en fonction de la saisie de l'utilisateur */
tool: (params: Record<string, any>) => string;
/** Transformation des paramètres avant transmission à l'outil */
params?: (params: Record<string, any>) => any;
};
};
/** Connexions d'entrée depuis les blocs en amont */
inputs?: Record<string, { type: string; description?: string }>;
/** Connexions de sortie vers les blocs en aval */
outputs?: Record<string, { type: string; description?: string }>;
/** Configuration du déclencheur (pour les blocs déclencheurs) */
triggers?: { enabled: boolean; available: string[] };
}Types de SubBlock
Les SubBlocks sont les champs de formulaire qui apparaissent lorsqu'un utilisateur clique sur un bloc :
| Type | Description | Propriétés clés |
|---|---|---|
short-input | Champ de texte sur une ligne | placeholder, password, readOnly, showCopyButton |
long-input | Zone de texte multiligne | placeholder |
code | Éditeur de code avec coloration syntaxique | placeholder, mode |
dropdown | Menu de sélection | options: [{ label, id }] |
combobox | Liste déroulante avec recherche | options, fetchOptions |
slider | Curseur de plage | min, max, step |
switch | Interrupteur à bascule | defaultValue |
oauth-input | Sélecteur de credential OAuth | serviceId, requiredScopes |
Définition de SubBlock
interface SubBlockInput {
/** Identifiant unique du champ dans le bloc */
id: string;
/** Libellé du champ */
title?: string;
/** Type de SubBlock */
type: string;
/** Disposition : "full" (par défaut) ou "half" */
layout?: "full" | "half";
/** Indique si ce champ est obligatoire */
required?: boolean;
/** Texte d'espace réservé */
placeholder?: string;
/** Masquer la saisie en points de mot de passe */
password?: boolean;
/** Valeur par défaut */
defaultValue?: unknown;
/** Options pour liste déroulante/combobox */
options?: Array<{ label: string; id: string }>;
/** Texte d'aide affiché sous le champ */
description?: string;
/** Visibilité conditionnelle basée sur la valeur d'un autre champ */
condition?: { field: string; value: string };
/** Indique si le champ est en lecture seule */
readOnly?: boolean;
/** Afficher un bouton de copie dans le presse-papiers */
showCopyButton?: boolean;
/** Masquer ce champ dans l'interface */
hidden?: boolean;
}Sélection dynamique d'outil
Lorsqu'un bloc dispose de plusieurs outils, utilisez tools.config.tool pour sélectionner lequel s'exécute :
defineBlock({
// ...
subBlocks: [
{
id: "operation",
title: "Operation",
type: "dropdown",
options: [
{ label: "Create", id: "create" },
{ label: "Read", id: "read" },
{ label: "Update", id: "update" },
{ label: "Delete", id: "delete" },
],
},
// ... autres champs
],
tools: {
access: ["acme_create", "acme_read", "acme_update", "acme_delete"],
config: {
tool: (params) => `acme_${params.operation}`,
},
},
});Visibilité conditionnelle
Afficher ou masquer des champs en fonction des valeurs d'autres champs :
subBlocks: [
{
id: "authType",
title: "Auth Type",
type: "dropdown",
options: [
{ label: "API Key", id: "apiKey" },
{ label: "Username/Password", id: "basic" },
],
},
{
id: "apiKey",
title: "API Key",
type: "short-input",
password: true,
condition: { field: "authType", value: "apiKey" },
},
{
id: "username",
title: "Username",
type: "short-input",
condition: { field: "authType", value: "basic" },
},
{
id: "password",
title: "Password",
type: "short-input",
password: true,
condition: { field: "authType", value: "basic" },
},
],defineTriggerBlock(config)
Définit un bloc déclencheur — un membre de workflow à part entière qui s'affiche dans la section latérale « Triggers » et porte des métadonnées de runtime décrivant comment il se déclenche (webhook, polling, ou les deux). La valeur de category est automatiquement définie à "trigger".
interface TriggerBlockInput {
/** Type de bloc unique */
type: string;
/** Nom d'affichage */
name: string;
/** Description */
description?: string;
/** Couleur de fond en hexadécimal */
bgColor?: string;
/** Mode d'auth : "none", "apiKey", "oauth", "botToken" */
authMode?: string;
/** Champs de formulaire pour la configuration du déclencheur */
subBlocks?: SubBlockInput[];
/** Les outils que ce bloc déclencheur peut invoquer */
tools?: {
access: string[];
config?: {
tool?: (params: Record<string, any>) => string;
params?: (params: Record<string, any>) => any;
};
};
/** Connexions d'entrée */
inputs?: Record<string, { type: string; description?: string }>;
/** Schéma de sortie — données émises par le déclencheur */
outputs?: Record<string, { type: string; description?: string }>;
/** Identifiant du fournisseur */
provider?: string;
/** Version sémantique */
version?: string;
/** Configuration de runtime — comment les événements atteignent le moteur de workflow */
runtime?: {
webhook?: {
method?: "POST" | "GET" | "PUT" | "DELETE";
headers?: Record<string, string>;
};
polling?: PollingProvider;
};
}Gestion des secrets
Les fournisseurs peuvent déclarer des secrets chiffrés au repos et résolus par invocation. Les secrets sont limités à l'organisation et au fournisseur, de sorte que chaque organisation dispose de son propre jeu de credentials isolé.
Déclaration des secrets
Définissez les exigences en matière de secrets dans defineVendor() via le tableau secrets :
export default defineVendor({
id: "acme",
name: "Acme",
version: "1.0.0",
icon: acmeIcon,
auth: { credentials: { apiKey: { type: "apiKey", label: "API Key" } }, default: "apiKey" },
secrets: [
{
key: "WEBHOOK_SIGNING_SECRET",
label: "Webhook Signing Secret",
description: "Used to verify incoming webhook payloads",
required: true,
},
{
key: "ENCRYPTION_KEY",
label: "Encryption Key",
description: "AES key for encrypting sensitive payloads",
required: false,
},
],
products: [/* ... */],
});Chaque SecretInput a la forme suivante :
interface SecretInput {
/** Clé unique au sein du fournisseur — doit correspondre à ^[a-zA-Z0-9_-]+$ */
key: string;
/** Libellé lisible affiché dans l'interface d'administration */
label: string;
/** Texte d'aide décrivant l'utilisation de ce secret */
description?: string;
/** Indique si l'intégration nécessite ce secret pour fonctionner */
required: boolean;
}Les clés de secret ne peuvent contenir que des caractères alphanumériques, des tirets et des underscores (^[a-zA-Z0-9_-]+$). Les clés ne correspondant pas à ce format sont rejetées lors de l'enregistrement.
Format des clés de secret
Les secrets sont stockés avec une clé structurée qui les rattache à l'organisation et au fournisseur :
integration:{orgId}:{vendorId}:{key}Par exemple, un secret avec la clé WEBHOOK_SIGNING_SECRET pour le fournisseur acme dans l'organisation org_abc123 est stocké sous :
integration:org_abc123:acme:WEBHOOK_SIGNING_SECRETCela garantit une isolation complète entre les organisations et entre les fournisseurs au sein d'une même organisation.
Chiffrement au repos
Toutes les valeurs de secret sont chiffrées avec AES-256-GCM avant d'être persistées. La stratégie de clé de chiffrement est configurée par organisation — LOCAL, BYOK ou HYOK. Les valeurs de secret ne sont jamais stockées en clair. Consultez Sécurité → Gestion des secrets pour le modèle complet.
Accès aux secrets au moment de l'exécution
Lorsqu'un outil s'exécute, la plateforme résout tous les secrets déclarés pour le fournisseur et les injecte dans ctx.secrets sous forme d'un Record<string, string> plat :
import { defineTool } from "@scrydon/sdk-authoring/integrations/define";
import { z } from "zod";
export const verifyWebhook = defineTool({
id: "acme:webhooks:verify",
name: "Verify Webhook",
version: "1.0.0",
input: z.object({ payload: z.string(), signature: z.string() }),
output: z.object({ valid: z.boolean() }),
async execute(input, ctx) {
const signingSecret = ctx.secrets["WEBHOOK_SIGNING_SECRET"];
if (!signingSecret) {
return { success: false, output: { valid: false }, error: "Webhook signing secret not configured" };
}
const valid = verifyHmac(input.payload, input.signature, signingSecret);
return { success: true, output: { valid } };
},
});L'objet ctx.secrets ne contient que les secrets qui ont été définis par l'administrateur de l'organisation. Si un secret n'a pas été configuré, il sera absent du record. Vérifiez toujours la présence des secrets obligatoires avant de les utiliser.
Interface d'administration
Les administrateurs d'organisation configurent les secrets via l'interface de paramètres d'intégration sous Paramètres > Intégrations > [Fournisseur] > Secrets. L'interface affiche les champs de secret déclarés dans le tableau secrets du fournisseur.
Les valeurs de secret sont en écriture seule — une fois une valeur enregistrée, elle n'est plus jamais affichée. L'interface indique uniquement quelles clés ont été configurées (avec un indicateur masqué) et permet aux administrateurs de les mettre à jour ou de les supprimer.
Points de terminaison API
La plateforme expose trois points de terminaison internes pour la gestion des secrets :
| Point de terminaison | Objectif |
|---|---|
/integrations/admin/bundle-secret-set | Créer ou mettre à jour une valeur de secret |
/integrations/admin/bundle-secret-delete | Supprimer un secret |
/integrations/admin/bundle-secret-list | Lister les clés de secret configurées (les valeurs ne sont jamais retournées) |
Ces points de terminaison sont internes (service à service) et nécessitent que l'appelant soit un service interne autorisé. Ils ne sont pas directement accessibles depuis les applications clientes.
CLI de build
# Construire un bundle
sdk-authoring integrations build [--entry src/index.ts] [--outDir dist]
# Tester un bundle
sdk-authoring integrations test [--level static|sandbox|live] [--tool <id>]Résultat du build
my-vendor-1.0.0.bundle.tar.gz
├── manifest.json # Métadonnées auto-générées (JSON Schemas, définitions UI)
├── dist/
│ └── index.js # ESM compilé et minifié (toutes les dépendances intégrées via esbuild)
├── meta/
│ ├── sbom.cdx.json # SBOM CycloneDX 1.6 (auto-généré)
│ └── metafile.json # Graphe de dépendances esbuild
└── assets/ # Icônes optionnelles
└── icon.svgLa CLI de build intègre toutes les dépendances npm dans le fichier dist/index.js unique et génère automatiquement un SBOM CycloneDX 1.6 dans meta/sbom.cdx.json. Il n'y a pas de npm install au moment de l'exécution — le bundle est entièrement autonome et déterministe.
Règles des identifiants de fournisseur
- Caractères alphanumériques minuscules et tirets uniquement
- Doit commencer par une lettre
- Format :
/^[a-z][a-z0-9-]*$/ - Exemples :
acme,my-vendor,hello-world
Convention des identifiants d'outil
Les identifiants d'outil utilisent le format complet {vendorId}:{productId}:{action} au moment de l'exécution :
hello-world:hello-world:say-hellogoogle:sheets:readslack:messaging:send-message
Forme abrégée : Dans le code d'authoring, vous pouvez utiliser uniquement la partie action (ex. "say-hello", "read"). Le SDK qualifie automatiquement les identifiants courts en ajoutant {vendorId}:{productId}: lors de l'appel à defineVendor(). Toutes les intégrations natives utilisent la forme courte. Si vous utilisez la forme complète, le préfixe vendor/product doit correspondre — la CLI de build valide cela.
Helpers de capacités
Les helpers de capacités encapsulent les configurations de runtime avec une balise de type afin que l'extracteur de manifeste puisse les identifier. Chaque helper retourne sa configuration avec une balise _capability utilisée en interne lors du build.
| Helper | Balise | Objectif |
|---|---|---|
defineCapabilityLLM(config) | llm | Fournisseur LLM complet (chat, complétion, streaming) |
defineCapabilitySTT(config) | stt | Reconnaissance vocale (batch et temps réel) |
defineCapabilityTTS(config) | tts | Synthèse vocale (batch et temps réel) |
defineCapabilityEmbedding(config) | embedding | Génération d'embeddings vectoriels |
defineCapabilityVideo(config) | video | Génération vidéo |
defineCapabilityOCR(config) | ocr | Analyse de documents / reconnaissance optique de caractères |
defineCapabilityWebhook(config) | webhook | Gestion des webhooks spécifiques au fournisseur |
defineCapabilityDiscovery(config) | discovery | Navigation dans les ressources, sélecteurs, portées d'accès |
Tous les helpers sont importés depuis @scrydon/sdk-authoring/integrations/define :
import {
defineCapabilityLLM,
defineCapabilitySTT,
defineCapabilityTTS,
defineCapabilityEmbedding,
defineCapabilityVideo,
defineCapabilityOCR,
defineCapabilityWebhook,
defineCapabilityDiscovery,
} from "@scrydon/sdk-authoring/integrations/define";Les configurations de capacités sont placées dans defineProduct({ capabilities: { runtimes: { ... } } }). L'extracteur de manifeste convertit les fonctions de runtime en indicateurs booléens et extrait les métadonnées des modèles (dimensions, benchmarks, tarification) dans le champ capabilityMeta du manifeste. Consultez Capacités pour des exemples d'utilisation complets de chaque helper.
Schéma du manifeste
La CLI de build génère automatiquement manifest.json à partir de votre appel à defineVendor(). Le manifeste est un instantané sérialisable en JSON des métadonnées de votre fournisseur, sans les fonctions de runtime. Il suit manifestVersion: 1.
Structure de niveau supérieur
{
"$schema": "...", // URL optionnelle du JSON Schema
"manifestVersion": 1, // Toujours 1
"version": "1.0.0", // Version du fournisseur (issue de defineVendor)
"vendor": { ... }, // Métadonnées du fournisseur
"auth": { ... }, // Configuration de l'authentification
"products": [ ... ], // Définitions des produits
"protocols": [ ... ], // Définitions de protocoles (optionnel)
"llm": { ... } // Configuration du fournisseur LLM (optionnel)
}Section fournisseur
Contient les métadonnées d'affichage. Le code de runtime est exclu.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
id | string | Oui | Identifiant du fournisseur (/^[a-z][a-z0-9-]*$/) |
name | string | Oui | Nom d'affichage |
description | string | Non | Description courte |
color | string | Non | Couleur de marque en hexadécimal |
icon | string | Oui | Icône SVG sous forme de chaîne |
website | string | Non | URL du site web du fournisseur |
docsUrl | string | Non | URL de la documentation |
categories | string[] | Non | Étiquettes de catégorie |
defaultEnabled | boolean | Non | Activation automatique pour les nouvelles organisations (par défaut : false) |
supportsSystemMode | boolean | Non | Prend en charge client_credentials (par défaut : false) |
connectivity | "cloud" | "local" | "hybrid" | Non | Exigences réseau |
configFields | ConfigField[] | Non | Champs configurables par l'administrateur |
secrets | Secret[] | Non | Secrets au niveau du fournisseur |
Section produit
Chaque produit dans le tableau products contient :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
id | string | Oui | Identifiant du produit |
name | string | Oui | Nom d'affichage |
capabilities.tools | Tool[] | Non | Définitions d'outils avec JSON Schema entrée/sortie |
capabilities.triggers | Trigger[] | Non | Définitions de déclencheurs |
capabilities.runtimes | object | Non | Indicateurs booléens pour llm, stt, tts, embedding, video, ocr |
capabilities.capabilityMeta | object | Non | Métadonnées de modèles extraites (dimensions d'embedding, modèles STT/TTS, benchmarks) |
capabilities.webhooks | boolean | Non | Indique si le produit gère les webhooks |
capabilities.discovery | boolean | Non | Indique si le produit prend en charge la découverte de ressources |
block | Block | Non | Définition du bloc de l'éditeur de workflow |
dependencies | Dependency[] | Non | Dépendances NPM déclarées avec leurs raisons |
systemMode | object | Non | Configuration du mode système (client_credentials) |
Comment le code de runtime devient des données de manifeste
La CLI de build transforme les définitions de runtime en JSON sûr pour le manifeste :
| Source (defineProduct) | Sortie du manifeste |
|---|---|
runtimes.llm (avec fonction executeRequest) | runtimes.llm: true |
runtimes.embedding (avec fonction embed, modèles avec dimension) | runtimes.embedding: true + capabilityMeta.embeddingModels |
runtimes.stt (avec fonction transcribe, modèles) | runtimes.stt: true + capabilityMeta.sttModels |
runtimes.tts (avec fonction synthesize, modèles) | runtimes.tts: true + capabilityMeta.ttsModels |
input/output d'un outil (schémas Zod) | Objets JSON Schema |
Fonction execute d'un outil | Omise (non sérialisable) |
Fonction tools.config.tool d'un bloc | Omise (sérialisée séparément) |
Le manifeste est ce que la plateforme lit au démarrage pour alimenter le catalogue d'intégrations. Il ne contient aucun code exécutable — uniquement des métadonnées, des JSON Schemas et des définitions UI. L'exécution réelle des outils se fait de manière différée lors de la première invocation d'un outil, en chargeant le dist/index.js du bundle dans un Worker Thread sandboxé.