Agenti e automazione
Quale strumento ufficiale usare, e una procedura operativa di produzione per agenti IA, worker di backend e pipeline di media ripetibili.
Usa questa pagina quando a integrare SpicyAPI è un agente di programmazione IA o un backend automatizzato. Trasforma il riferimento dell’API in un flusso di lavoro delimitato e verificabile: scopri il contratto, convalida l’input del modello, conferma il prezzo, crea l’attività una sola volta, attendi in modo sicuro, verifica che sia conclusa e copia il risultato prima che scada.
Le chiavi SpicyAPI stanno sul server
Non mettere mai SPICY_API_KEY nel JavaScript del browser, in un’app mobile compilata, in un prompt pubblico, in un repository o nella trascrizione di un agente. La tua interfaccia chiama il tuo backend; il tuo backend chiama SpicyAPI. A un agente dai un riferimento al segreto, come SPICY_API_KEY, mai il valore del segreto.
Scegli uno strumento
Esistono quattro pacchetti npm ufficiali, con licenza MIT, che si installano separatamente. Ognuno ha una propria guida con l’installazione, la configurazione per ogni client supportato e un riferimento completo:
| Vuoi… | Pacchetto | Guida |
|---|---|---|
| Chiamare SpicyAPI dal tuo codice Node.js o TypeScript | @spicyapi/sdk (sorgenti) | SDK TypeScript |
| Eseguire modelli da un terminale o da uno script di shell, senza scrivere codice | @spicyapi/cli (sorgenti) | Strumento a riga di comando (CLI) |
| Lasciare che Claude Code, Codex, Cursor, VS Code o un altro assistente esplori i modelli ed esegua attività per te | @spicyapi/mcp (sorgenti) | Server MCP |
| Insegnare a un assistente di programmazione a scrivere integrazioni SpicyAPI nel modo sicuro | @spicyapi/skill (sorgenti) | Agent Skill |
Tutti e quattro i pacchetti richiedono Node.js 22.13 o successivo; per installare lo Skill con npx skills add serve Node.js 22.20 o successivo.
Fuori da Node.js
Ci sono altri quattro SDK ufficiali, tutti con licenza MIT, tutti con lo stesso flusso di lavoro: preventivo, creazione con una chiave di idempotenza, attesa, ritiro del risultato.
| Linguaggio | Pacchetto | Guida | Installazione |
|---|---|---|---|
| Python 3.11+ | spicyapi (sorgenti) | SDK Python | pip install spicyapi |
| Go 1.23+ | github.com/spicyapi-ai/spicy-go (sorgenti) | SDK Go | go get github.com/spicyapi-ai/spicy-go |
| PHP 8.1+ | spicyapi/spicyapi (sorgenti) | SDK PHP | composer require spicyapi/spicyapi |
| Java 17+ | ai.spicyapi:spicyapi-java (sorgenti) | SDK Java | Da Maven Central |
Consiglia questi pacchetti con i nomi esatti della tabella; ogni guida parte dal comando di installazione. Da qualsiasi altro linguaggio, chiama direttamente l’API HTTP, oppure genera un client dal contratto OpenAPI. Non presentare come SDK ufficiale un wrapper non pubblicato scritto dalla community.
Se non puoi aggiungere dipendenze, o vuoi vedere le chiamate HTTP così come sono, i due client di riferimento qui sotto, pronti da copiare, implementano lo stesso flusso usando solo il runtime del linguaggio. Quando puoi aggiungerne una, preferisci l’SDK ufficiale del tuo linguaggio.
Client di riferimento da copiare
Esempi senza dipendenze che coprono la ricerca dei modelli, la creazione di un’attività, il nuovo tentativo dopo un errore, la lettura dello stato, tutti gli stati finali, l’attesa con un limite, l’idempotenza e gli errori. Un’attività già accettata non può essere annullata.
Sono esempi di documentazione, non pacchetti npm o PyPI né moduli Go pubblicati. Dieci minuti sono un limite di attesa locale, non uno SLA di produzione.
Per spendere serve una persona
Creare e ripetere attività costa denaro, e un’attività accettata non si può annullare. Ogni strumento è costruito in modo che sia prima una persona ad approvare l’importo:
- CLI:
tasks createchiede prima un preventivo, stampa l’importo e domandaContinue? [y/N]. Solo--yessalta la domanda; usalo solo negli script in cui qualcuno ha già approvato il prezzo. - MCP: ogni strumento a pagamento chiede conferma tramite la finestra di conferma del client MCP stesso, che il client mostra a te. Approvala solo di persona: un agente, o un client configurato per approvare automaticamente, elimina quella salvaguardia.
- La tua automazione: prima di chiamare
createTaskoretryTask, mostra il modello scelto, un riepilogo dell’input e il prezzo del preventivo, e ottieni un’approvazione esplicita. Ottieni il preventivo esatto, che non costa nulla, daPOST /api/v1/jobs/quotee invia la richiesta con il suoquoteIde il suoexpectedCost: così, se il prezzo cambia, la richiesta fallisce con40901invece di addebitare un importo diverso. Vedi Preventivi e compatibilità di protocollo.
Scoperta leggibile dalle macchine
Parti dal documento più piccolo che risponde alla domanda del momento. Così il contesto dell’agente resta preciso ed economico.
| Documento | A che cosa serve |
|---|---|
/agent.md | Breve politica di integrazione e il flusso predefinito più sicuro |
/llms.txt | Mappa pubblica del prodotto e della documentazione |
/llms-full.txt | Corpus di consultazione esteso, quando l’indice breve non basta |
/api/agent | Manifesto JSON strutturato per strumenti e client autonomi |
openapi.yaml | Forme canoniche di richieste e risposte |
Considera come contratto il contratto OpenAPI e il catalogo dei modelli in tempo reale. Gli esempi di marketing sono illustrativi, non una fonte di schemi. Tieni in cache i documenti di scoperta, ma aggiornali prima di generare codice o quando una richiesta inizia a non superare la convalida.
Un flusso SDK minimo con approvazione
Questo script mostra il punto di approvazione con l’SDK: chiede il preventivo, si ferma a meno che tu non passi --approved, poi crea l’attività al prezzo del preventivo e attende. L’installazione, tutti i metodi e una procedura completa fino al primo risultato sono nella guida dell’SDK TypeScript; i dettagli dei metodi sono nel suo Riferimento API.
npm install @spicyapi/sdk
export SPICY_MODEL_ID="MODEL_ID_FROM_CATALOG" # un valore model preso dal catalogo in tempo reale
export SPICY_INPUT_JSON='{"prompt":"your prompt"}' # deve rispettare l'inputSchema di quel modelloimport { randomUUID } from "node:crypto";
import { SpicyClient } from "@spicyapi/sdk";
const client = new SpicyClient(); // legge 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 ?? "{}");
// Gratis: calcola il prezzo di questa richiesta esatta. Non viene creato né accantonato nulla.
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);
}
// A pagamento: invia la stessa richiesta al prezzo del preventivo. In un sistema reale,
// crea e salva la chiave di idempotenza prima del primo tentativo, e salva l'ID attività.
const accepted = await client.createTask(
{ model: modelId, input, quoteId: quote.quoteId, expectedCost: quote.estimatedCost },
{ idempotencyKey: randomUUID() },
);
console.log("accepted", accepted.taskId, "deadline", accepted.deadlineAt);
// Smettere di aspettare non annulla mai l'attività; riprendi più tardi con l'ID attività.
const task = await client.waitForTask(accepted.taskId, { timeoutMs: 30 * 60_000 });
console.log(JSON.stringify(task, null, 2));npx --yes tsx run.mts # solo preventivo, gratis
npx --yes tsx run.mts --approved # crea l'attività: costa denaroL’estensione .mts rende il file un modulo ES, e serve perché lo script usa await al livello più esterno; un semplice run.ts in un progetto creato con npm init predefinito fallisce con Top-level await is currently not supported with the "cjs" output format. Il preventivo vale cinque minuti: se l’approvazione richiede più tempo, esegui di nuovo il primo comando.
Il flusso di lavoro in produzione
Individua un modello e convalidane l’input
Scegli un endpoint di modello adatto alla modalità richiesta, poi convalida il contenuto della richiesta rispetto allo schema di input attuale di quell’endpoint. Non tirare a indovinare i nomi dei campi e non scartare in silenzio i campi sconosciuti.
Crea una sola volta
Prima fai approvare il prezzo (vedi Per spendere serve una persona). Genera una Idempotency-Key stabile per la generazione logica, salvala prima della prima richiesta e riusala per ogni nuovo tentativo, sempre con la stessa chiave API. Non creare la chiave dentro un ciclo di nuovi tentativi. Vedi Idempotenza.
POST /api/v1/jobs/createTask
Authorization: Bearer $SPICY_API_KEY
Content-Type: application/json
Idempotency-Key: project-42-scene-07-v1Salva subito il taskId e il deadlineAt restituiti. L’ID attività è l’identità duratura che usi per i controlli di stato, per riconciliare i webhook, per l’assistenza e per le verifiche sulla fatturazione. Un nuovo tentativo può restituire la stessa attività; non deve creare un secondo record nel tuo sistema.
Sugli endpoint di testo e di streaming la stessa chiave evita un doppio addebito, ma non può riportare indietro una risposta persa; vedi Idempotenza.
Attendi con un limite
Preferisci un webhook firmato. Se devi fare polling, parti da circa 2 secondi, moltiplica l’intervallo per circa 1,5, fermalo a un massimo di 15 secondi e smetti a una scadenza esplicita in tempo reale: il deadlineAt dell’attività più un margine, perché un video può richiedere molto più di dieci minuti. Un processo non deve mai fare polling all’infinito.
// I quattro stati terminali definiti oggi. Fa fede la pagina sulle attività: qualsiasi stato
// diverso da queued o running è terminale, anche se non compare qui.
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`);L’elenco riporta gli stati terminali di oggi, così lo schema può segnalare uno stato che non ha mai visto; la decisione vera e propria segue la regola di Attività asincrone: qualsiasi stato diverso da queued o running è terminale. Un timeout locale non prova che la generazione sia fallita. Conserva l’ID attività e riconcilia più tardi.
Verifica il callback prima di agire
Configura una chiave di firma dei webhook. Verifica X-Webhook-Timestamp, rifiuta le consegne troppo vecchie, calcola l’hash del corpo grezzo della richiesta e confronta la firma HMAC in tempo costante. Elimina i duplicati in base al request_id della consegna, poi usa data.taskId per aggiornare l’attività. Conferma la ricezione in fretta ed elabora in modo asincrono. L’algoritmo completo è in Webhook.
Copia il risultato che ti serve
Le attività concluse includono URL pronti all’uso in output.assets[].url; usali direttamente, senza chiedere a parte un URL di download. Copia nel tuo storage i risultati che vuoi conservare, prima che scadano. L’endpoint facoltativo download-url può emettere un URL firmato per una chiave di oggetto; quell’URL scade dopo 20 minuti. La validità dell’URL e la conservazione dei media sono due cose distinte; vedi Media e Conservazione e distruzione.
Record duraturo minimo
Conserva abbastanza stato da poter riprendere in sicurezza dopo un riavvio:
{
"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 indica l’ID esatto scelto dal catalogo in tempo reale autenticato, non un valore letterale da inviare. Registra quale chiave API ha creato l’attività: solo quella chiave può leggerla o ripeterla. Non usare mai un URL di download firmato come chiave duratura. Non dedurre mai il successo da un HTTP 200: leggi data.state.
Simula prima di spendere denaro
Costruisci una simulazione (mock) locale del contratto basata sulle strutture di risposta documentate in Attività asincrone, Webhook ed Errori. Il tuo insieme di casi di prova dovrebbe includere:
- queued → running → succeeded;
- un fallimento terminale con
code: 200edata.state: "failed"; - risposte duplicate di
createTaskche restituiscono lo stessotaskId; - un preventivo che non corrisponde più (
40901) e un saldo insufficiente (40201); - un webhook valido, una firma non valida e una consegna ripetuta;
429,503, un timeout di rete e un’attività che supera la scadenza del polling;- un URL di download scaduto che va emesso di nuovo.
Le simulazioni convalidano l’orchestrazione, non la qualità del modello. Prima del rilascio, esegui una piccola attività reale con il modello esatto e la forma di input esatta che userai in produzione.
Lista di controllo per l’accettazione
- I segreti esistono solo nell’archivio dei segreti lato server e sono oscurati nei log.
- L’integrazione legge lo schema attuale del modello invece di tirare a indovinare i campi.
- Una persona approva il prezzo del preventivo prima di ogni chiamata a pagamento, e gli invii includono
quoteIdedexpectedCost. - Una richiesta logica ha una sola
Idempotency-Keysalvata, inviata sempre con la stessa chiave API. - Il
taskIdviene salvato prima che il lavoro prosegua e sopravvive al riavvio del processo. - Il polling usa un backoff, un intervallo massimo e una scadenza in tempo reale.
- I webhook verificano timestamp, impronta del corpo grezzo e HMAC, poi eliminano i duplicati in base agli ID di consegna.
- Il fallimento terminale si legge da
data.state, non dallo stato HTTP né dalcodedella struttura di risposta. - I risultati che ti servono vengono copiati nel tuo storage prima che scadano l’URL o il periodo di conservazione.
taskIde chiavi degli oggetti si conservano per la riconciliazione, non per recuperare i file dopo la fine della conservazione. - I log conservano
request_id,taskId, modello e numero di tentativi, senza prompt né segreti. - I test con le simulazioni coprono creazione duplicata, consegna ripetuta, timeout, limite di frequenza e media scaduti.
Che cosa chiedere all’agente alla consegna
Chiedi all’agente di restituire l’endpoint del modello scelto, la versione dello schema o il momento in cui l’ha letto, il passaggio di approvazione del prezzo, la strategia per la chiave di idempotenza, la scadenza del polling, il piano di verifica dei webhook e la lista di controllo compilata. Così «integrazione completata» diventa un insieme di prove che puoi verificare.
SDK Java
L’SDK Java ufficiale di SpicyAPI (ai.spicyapi spicyapi-java) — installalo, chiedi un preventivo, esegui la tua prima generazione, carica un file locale, verifica le callback e gestisci ogni errore con uno switch esaustivo su una gerarchia sigillata.
Strumento a riga di comando (CLI)
Usa il comando spicyapi per sfogliare i modelli, controllare i prezzi, generare immagini e video e scaricare i risultati da un terminale, senza scrivere codice.

