Scrydon

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 zod
npm install --save-dev @scrydon/sdk-authoring/integrations zod

Chemins 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 valeurCas d'usage
user-or-llmL'utilisateur la définit dans l'interface, ou un agent IA la génèreLa plupart des paramètres
user-onlySeul l'utilisateur peut la configurer (masquée du LLM)Paramètres de connexion, credentials
hiddenNon affichée dans l'interface ni au LLM — définie par programmationIdentifiants 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 :

TypeDescriptionPropriétés clés
short-inputChamp de texte sur une ligneplaceholder, password, readOnly, showCopyButton
long-inputZone de texte multiligneplaceholder
codeÉditeur de code avec coloration syntaxiqueplaceholder, mode
dropdownMenu de sélectionoptions: [{ label, id }]
comboboxListe déroulante avec rechercheoptions, fetchOptions
sliderCurseur de plagemin, max, step
switchInterrupteur à basculedefaultValue
oauth-inputSélecteur de credential OAuthserviceId, 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_SECRET

Cela 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 terminaisonObjectif
/integrations/admin/bundle-secret-setCréer ou mettre à jour une valeur de secret
/integrations/admin/bundle-secret-deleteSupprimer un secret
/integrations/admin/bundle-secret-listLister 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.svg

La 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-hello
  • google:sheets:read
  • slack: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.

HelperBaliseObjectif
defineCapabilityLLM(config)llmFournisseur LLM complet (chat, complétion, streaming)
defineCapabilitySTT(config)sttReconnaissance vocale (batch et temps réel)
defineCapabilityTTS(config)ttsSynthèse vocale (batch et temps réel)
defineCapabilityEmbedding(config)embeddingGénération d'embeddings vectoriels
defineCapabilityVideo(config)videoGénération vidéo
defineCapabilityOCR(config)ocrAnalyse de documents / reconnaissance optique de caractères
defineCapabilityWebhook(config)webhookGestion des webhooks spécifiques au fournisseur
defineCapabilityDiscovery(config)discoveryNavigation 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.

ChampTypeObligatoireDescription
idstringOuiIdentifiant du fournisseur (/^[a-z][a-z0-9-]*$/)
namestringOuiNom d'affichage
descriptionstringNonDescription courte
colorstringNonCouleur de marque en hexadécimal
iconstringOuiIcône SVG sous forme de chaîne
websitestringNonURL du site web du fournisseur
docsUrlstringNonURL de la documentation
categoriesstring[]NonÉtiquettes de catégorie
defaultEnabledbooleanNonActivation automatique pour les nouvelles organisations (par défaut : false)
supportsSystemModebooleanNonPrend en charge client_credentials (par défaut : false)
connectivity"cloud" | "local" | "hybrid"NonExigences réseau
configFieldsConfigField[]NonChamps configurables par l'administrateur
secretsSecret[]NonSecrets au niveau du fournisseur

Section produit

Chaque produit dans le tableau products contient :

ChampTypeObligatoireDescription
idstringOuiIdentifiant du produit
namestringOuiNom d'affichage
capabilities.toolsTool[]NonDéfinitions d'outils avec JSON Schema entrée/sortie
capabilities.triggersTrigger[]NonDéfinitions de déclencheurs
capabilities.runtimesobjectNonIndicateurs booléens pour llm, stt, tts, embedding, video, ocr
capabilities.capabilityMetaobjectNonMétadonnées de modèles extraites (dimensions d'embedding, modèles STT/TTS, benchmarks)
capabilities.webhooksbooleanNonIndique si le produit gère les webhooks
capabilities.discoverybooleanNonIndique si le produit prend en charge la découverte de ressources
blockBlockNonDéfinition du bloc de l'éditeur de workflow
dependenciesDependency[]NonDépendances NPM déclarées avec leurs raisons
systemModeobjectNonConfiguration 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 outilOmise (non sérialisable)
Fonction tools.config.tool d'un blocOmise (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é.

Sur cette page

Sur cette page