Agents et automatisation
Quel outil officiel choisir, et un guide d’exploitation en production pour les agents IA, les workers backend et les chaînes de production de médias reproductibles.
Consultez cette page lorsqu’un agent de code IA ou un backend automatisé intègre SpicyAPI. Elle transforme la référence de l’API en un processus borné et vérifiable : découvrir le contrat, valider l’entrée du modèle, confirmer le prix, créer une seule fois, attendre en toute sécurité, vérifier la fin de la tâche et copier le résultat avant qu’il n’expire.
Les clés SpicyAPI restent sur le serveur
Ne placez jamais SPICY_API_KEY dans du JavaScript exécuté par le navigateur, dans une application mobile compilée, dans un prompt public, dans un dépôt ou dans la transcription d’un agent. Votre interface appelle votre backend ; votre backend appelle SpicyAPI. Donnez à un agent une référence au secret, comme SPICY_API_KEY, jamais la valeur du secret.
Choisir un outil
Il existe quatre paquets npm officiels, installables séparément et publiés sous licence MIT. Chacun a son propre guide, qui couvre l’installation, la configuration pour chaque client pris en charge et une référence complète :
| Vous voulez… | Paquet | Guide |
|---|---|---|
| Appeler SpicyAPI depuis votre propre code Node.js ou TypeScript | @spicyapi/sdk (source) | SDK TypeScript |
| Exécuter des modèles depuis un terminal ou un script shell, sans écrire de code | @spicyapi/cli (source) | Outil en ligne de commande |
| Laisser Claude Code, Codex, Cursor, VS Code ou un autre assistant parcourir les modèles et lancer des tâches pour vous | @spicyapi/mcp (source) | Serveur MCP |
| Apprendre à un assistant de code à écrire des intégrations SpicyAPI de manière sûre | @spicyapi/skill (source) | Agent Skill |
Les quatre paquets demandent Node.js 22.13 ou plus récent ; installer le Skill avec npx skills add demande Node.js 22.20 ou plus récent.
En dehors de Node.js
Il existe quatre autres SDK officiels, tous sous licence MIT, qui mettent tous en œuvre le même processus : obtenir un devis, créer une seule fois avec une clé d’idempotence, attendre, récupérer.
| Langage | Paquet | Guide | Installation |
|---|---|---|---|
| Python 3.11+ | spicyapi (source) | SDK Python | pip install spicyapi |
| Go 1.23+ | github.com/spicyapi-ai/spicy-go (source) | SDK Go | go get github.com/spicyapi-ai/spicy-go |
| PHP 8.1+ | spicyapi/spicyapi (source) | SDK PHP | composer require spicyapi/spicyapi |
| Java 17+ | ai.spicyapi:spicyapi-java (source) | SDK Java | Depuis Maven Central |
Recommandez ces paquets sous les noms exacts du tableau. Chaque guide commence par sa commande d’installation. Depuis n’importe quel autre langage, appelez directement l’API HTTP, ou générez un client à partir du contrat OpenAPI. Ne présentez pas une surcouche communautaire non publiée comme un SDK officiel.
Si vous ne pouvez pas ajouter de dépendance, ou si vous voulez voir les appels HTTP bruts, les deux clients de référence ci-dessous, prêts à copier, mettent en œuvre le même processus avec le seul environnement d’exécution du langage. Quand vous pouvez en ajouter une, préférez le SDK officiel de votre langage.
Clients de référence copiables
Exemples sans dépendance couvrant la découverte des modèles, la création de tâches, la relance d’une tâche en échec, le suivi des états, l’attente bornée, l’idempotence et les erreurs. Une tâche acceptée ne peut plus être annulée.
Ce sont des exemples de documentation, pas des paquets npm ou PyPI ni des modules Go publiés. Dix minutes est une limite locale, pas un SLA.
Dépenser demande l’accord d’une personne
Créer et relancer des tâches coûte de l’argent, et une tâche acceptée ne peut pas être annulée. Chaque outil est conçu pour qu’une personne approuve d’abord le montant :
- CLI :
tasks createdemande d’abord un devis, affiche le montant et pose la questionContinue? [y/N]. Seul--yespermet de sauter la question ; ne l’utilisez que dans des scripts dont le prix a déjà été approuvé par quelqu’un. - MCP : chaque outil payant demande une confirmation via la fenêtre de dialogue propre au client MCP, qui vous l’affiche. C’est à vous seul de l’approuver : un agent, ou un client configuré pour tout approuver automatiquement, supprime cette limite.
- Votre propre automatisation : avant d’appeler
createTaskouretryTask, affichez le modèle choisi, un résumé de l’entrée et le prix du devis, et obtenez une approbation explicite. Récupérez le devis exact, non facturé, auprès dePOST /api/v1/jobs/quoteet soumettez avec sonquoteIdet sonexpectedCost: un prix qui a changé échoue alors avec40901au lieu d’être facturé à un autre montant. Voir Devis et compatibilité des protocoles.
Découverte lisible par machine
Commencez par le plus petit document qui répond à la question du moment. Le contexte de l’agent reste ainsi exact et peu coûteux.
| Document | À utiliser pour |
|---|---|
/agent.md | Une politique d’intégration courte et le processus par défaut le plus sûr |
/llms.txt | La carte publique du produit et de la documentation |
/llms-full.txt | Un corpus de recherche étendu, quand l’index court ne suffit pas |
/api/agent | Un manifeste JSON structuré pour les outils et les clients autonomes |
openapi.yaml | Les formes de requête et de réponse de référence |
Considérez le contrat OpenAPI et le catalogue des modèles en direct comme le contrat. Les exemples marketing sont illustratifs : ils ne servent pas de source de schéma. Mettez les documents de découverte en cache, mais actualisez-les avant de générer du code ou dès qu’une requête commence à échouer à la validation.
Un parcours SDK minimal avec approbation
Ce script montre la limite d’approbation avec le SDK : il demande un devis, s’arrête si vous ne passez pas --approved, puis crée la tâche au prix du devis et attend. L’installation, chaque méthode et un parcours complet jusqu’au premier résultat sont décrits dans le guide du SDK TypeScript ; le détail des méthodes se trouve dans sa référence de l’API.
npm install @spicyapi/sdk
export SPICY_MODEL_ID="MODEL_ID_FROM_CATALOG" # une valeur model tirée du catalogue en direct
export SPICY_INPUT_JSON='{"prompt":"your prompt"}' # doit correspondre à l'inputSchema de ce modèleimport { randomUUID } from "node:crypto";
import { SpicyClient } from "@spicyapi/sdk";
const client = new SpicyClient(); // lit SPICY_API_KEY
const modelId = process.env.SPICY_MODEL_ID;
if (!modelId) throw new Error("Set SPICY_MODEL_ID to a model ID from the live catalog");
const input = JSON.parse(process.env.SPICY_INPUT_JSON ?? "{}");
// Gratuit : donne le prix de cette requête exacte. Rien n'est créé ni réservé.
const quote = await client.quoteTask({ model: modelId, input });
console.log(`${quote.model}: up to $${quote.maxCharge}, quote valid until ${quote.expiresAt}`);
if (!process.argv.includes("--approved")) {
console.log("Nothing was submitted. Re-run with --approved once a person has approved this amount.");
process.exit(0);
}
// Payant : soumet la même requête au prix du devis. Dans un vrai système, créez
// et enregistrez la clé d'idempotence avant la première tentative, puis conservez l'identifiant de tâche.
const accepted = await client.createTask(
{ model: modelId, input, quoteId: quote.quoteId, expectedCost: quote.estimatedCost },
{ idempotencyKey: randomUUID() },
);
console.log("accepted", accepted.taskId, "deadline", accepted.deadlineAt);
// Arrêter l'attente n'annule jamais la tâche ; reprenez plus tard avec l'identifiant de tâche.
const task = await client.waitForTask(accepted.taskId, { timeoutMs: 30 * 60_000 });
console.log(JSON.stringify(task, null, 2));npx --yes tsx run.mts # devis seulement, gratuit
npx --yes tsx run.mts --approved # crée la tâche : cela coûte de l'argentL’extension .mts fait du fichier un module ES, ce qu’exige le await de premier niveau ; un simple run.ts dans un projet créé avec npm init par défaut échoue avec Top-level await is currently not supported with the "cjs" output format. Le devis est valable cinq minutes : si l’approbation prend plus de temps, relancez la première commande.
Le processus en production
Choisir un modèle et valider son entrée
Choisissez un point de terminaison de modèle qui correspond à la modalité demandée, puis validez le contenu de la requête par rapport au schéma d’entrée actuel de ce point de terminaison. Ne devinez pas les noms de champs et n’écartez pas en silence les champs inconnus.
Créer une seule fois
Faites d’abord approuver le prix (voir Dépenser demande l’accord d’une personne). Générez une Idempotency-Key stable pour chaque génération logique, enregistrez-la avant la première requête et réutilisez-la à chaque nouvelle tentative, toujours avec la même clé API. Ne créez pas la clé à l’intérieur d’une boucle de nouvelles tentatives. Voir Idempotence.
POST /api/v1/jobs/createTask
Authorization: Bearer $SPICY_API_KEY
Content-Type: application/json
Idempotency-Key: project-42-scene-07-v1Enregistrez immédiatement le taskId et le deadlineAt renvoyés. L’identifiant de tâche est l’identité durable qui sert aux vérifications d’état, au rapprochement des webhooks, à l’assistance et aux vérifications de facturation. Une nouvelle tentative peut renvoyer la même tâche ; elle ne doit pas créer un second enregistrement local.
Sur les points de terminaison de texte et de streaming, la même clé évite une double facturation, mais ne peut pas faire revenir une réponse perdue ; voir Idempotence.
Attendre avec une limite
Préférez un webhook signé. Si l’interrogation régulière (polling) est nécessaire, commencez vers 2 secondes, multipliez l’intervalle par environ 1,5, plafonnez-le à 15 secondes et arrêtez-vous à une échéance explicite en temps réel : le deadlineAt de la tâche plus une marge, car une vidéo peut prendre bien plus de dix minutes. Un processus ne doit jamais interroger indéfiniment.
// Les quatre états finaux définis aujourd'hui. La page Tâches fait foi : tout état
// autre que queued ou running compte comme final, même s'il n'est pas listé ici.
const KNOWN_TERMINAL = ['succeeded', 'failed', 'canceled', 'expired'];
const deadline = Date.parse(accepted.deadlineAt) + 60_000;
let delay = 2_000;
while (Date.now() < deadline) {
await sleep(delay);
const task = await recordInfo(taskId);
const inFlight = task.state === 'queued' || task.state === 'running';
const assetsPending = task.state === 'succeeded' && task.output?.assets?.some((a) => a.pending);
if (!inFlight && !assetsPending) {
if (!KNOWN_TERMINAL.includes(task.state)) log.warn(`new terminal state: ${task.state}`);
return task;
}
delay = Math.min(Math.round(delay * 1.5), 15_000);
}
throw new Error(`task ${taskId} exceeded the polling deadline`);La liste nomme les états finaux actuels pour que le squelette puisse signaler un état qu’il n’a jamais vu ; la décision elle-même suit la règle de Tâches asynchrones : tout ce qui n’est pas queued ou running est final. Un dépassement de délai local ne prouve pas que la génération a échoué. Conservez l’identifiant de tâche et faites le rapprochement plus tard.
Vérifier le callback avant d’agir
Configurez un secret de signature des webhooks. Vérifiez X-Webhook-Timestamp, rejetez les livraisons trop anciennes, calculez l’empreinte du corps brut de la requête et comparez la signature HMAC en temps constant. Dédoublonnez sur le request_id de la livraison, puis utilisez data.taskId pour mettre à jour la tâche. Accusez réception rapidement et traitez de manière asynchrone. L’algorithme complet se trouve dans Webhooks.
Copier le résultat dont vous avez besoin
Les tâches terminées contiennent des URL prêtes à l’emploi dans output.assets[].url ; utilisez-les directement, sans requête supplémentaire d’URL de téléchargement. Copiez les résultats que vous devez garder dans votre propre stockage avant qu’ils n’expirent. Le point de terminaison facultatif download-url peut émettre une URL signée pour une clé d’objet ; cette URL expire au bout de 20 minutes. La validité de l’URL et la conservation du média sont deux choses distinctes ; voir Médias et Conservation et destruction.
Enregistrement durable minimal
Conservez assez d’état pour reprendre en toute sécurité après un redémarrage :
{
"localRequestId": "project-42-scene-07-v1",
"idempotencyKey": "project-42-scene-07-v1",
"apiKeyName": "production backend",
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"model": "MODEL_ID_FROM_CATALOG",
"approvedCost": "0.40",
"state": "queued",
"deadlineAt": "2026-08-29T12:20:00Z",
"lastCheckedAt": "2026-08-29T12:00:00Z",
"webhookDeliveryId": null,
"outputKeys": []
}MODEL_ID_FROM_CATALOG désigne l’identifiant exact choisi dans le catalogue en direct authentifié, et non une valeur littérale à envoyer. Notez quelle clé API a créé la tâche : seule cette clé peut la lire ou la relancer. N’utilisez jamais une URL de téléchargement signée comme clé durable. Ne déduisez jamais un succès d’un HTTP 200 ; lisez data.state.
Simuler avant de dépenser de l’argent
Construisez une simulation locale du contrat à partir des enveloppes décrites dans Tâches asynchrones, Webhooks et Erreurs. Vos jeux de test doivent inclure :
- queued → running → succeeded ;
- un échec final avec
code: 200etdata.state: "failed"; - des réponses
createTasken double qui renvoient le mêmetaskId; - un devis qui ne correspond plus (
40901) et un solde insuffisant (40201) ; - un webhook valide, une signature invalide et une livraison rejouée ;
429,503, un dépassement de délai réseau et une tâche qui dépasse l’échéance d’interrogation ;- une URL de téléchargement expirée qu’il faut émettre de nouveau.
Les simulations valident l’orchestration, pas la qualité du modèle. Avant la mise en production, lancez une petite tâche réelle avec le modèle exact et la forme d’entrée exacte de la production.
Liste de vérification avant validation
- Les secrets n’existent que dans un stockage de secrets côté serveur et sont masqués dans les journaux.
- L’intégration récupère le schéma actuel du modèle au lieu de deviner les champs.
- Une personne approuve le prix du devis avant tout appel payant, et les soumissions portent
quoteIdetexpectedCost. - Une requête logique a une seule
Idempotency-Keyenregistrée, toujours envoyée avec la même clé API. - Le
taskIdest enregistré avant que le travail continue et survit à un redémarrage du processus. - L’interrogation utilise un délai croissant, un intervalle maximal et une échéance en temps réel.
- Les webhooks vérifient l’horodatage, l’empreinte du corps brut et le HMAC, puis dédoublonnent les identifiants de livraison.
- L’échec final se lit dans
data.state, pas dans le statut HTTP ni dans lecodede l’enveloppe. - Les résultats dont vous avez besoin sont copiés dans votre propre stockage avant l’expiration de l’URL ou de la période de conservation. Le
taskIdet les clés d’objet sont conservés pour le rapprochement, sans compter sur eux pour récupérer les fichiers une fois la conservation terminée. - Les journaux conservent le
request_id, letaskId, le modèle et le nombre de tentatives, sans prompts ni secrets. - Les tests avec simulation couvrent la création en double, le rejeu, le dépassement de délai, la limite de débit et les médias expirés.
Ce que l’agent doit vous remettre
Demandez à l’agent de vous rendre le point de terminaison de modèle choisi, la version du schéma ou l’heure à laquelle il a été récupéré, l’étape d’approbation du prix, la stratégie de clé d’idempotence, l’échéance d’interrogation, le plan de vérification des webhooks et la liste de vérification remplie. « Intégration terminée » devient alors un ensemble de preuves que vous pouvez examiner.
SDK Java
Le SDK Java officiel de SpicyAPI (ai.spicyapi spicyapi-java) — l’installer, obtenir un devis, lancer votre première génération, téléverser un fichier local, vérifier les callbacks et parcourir de façon exhaustive une taxonomie d’erreurs scellée.
Outil en ligne de commande (CLI)
Utilisez la commande spicyapi pour parcourir les modèles, vérifier les prix, générer des images et des vidéos et télécharger les résultats depuis un terminal, sans écrire de code.

