Utilisation de l'API et du SDK Cursor Cloud Agents

L'API et le SDK Cursor Cloud Agents vous offrent un contrôle programmatique sur les agents de codage basés dans le cloud. Au lieu de lancer et surveiller manuellement les agents depuis l'éditeur, vous pouvez les démarrer, les orienter en cours d'exécution, capturer leur sortie écran et recevoir des rappels webhook lorsque les tâches sont terminées. Ce guide vous accompagne à travers l'authentification, la gestion du cycle de vie, les modèles d'intégration du SDK et des conseils de dépannage issus d'expériences de développeurs réels.
Prérequis et configuration
Avant de vous intégrer à l'API Cloud Agents, assurez-vous de disposer des éléments suivants :
- Un compte Cursor avec l'accès Cloud Agents activé
- Une clé API générée depuis le tableau de bord des paramètres Cursor
- Node.js 18 ou supérieur (pour le SDK TypeScript/JavaScript)
- Une compréhension de base des modèles de programmation asynchrone
Stockez votre clé API dans une variable d'environnement plutôt que de la coder en dur. Utilisez un fichier .env pendant le développement et un gestionnaire de secrets en production.
Installation du SDK
Installez le SDK Cursor Cloud Agents depuis le registre public :
npm install @cursor/cloud-agents-sdk
# or
yarn add @cursor/cloud-agents-sdk
# or
pnpm add @cursor/cloud-agents-sdk
Vérifiez l'installation en consultant la version du paquet :
npx @cursor/cloud-agents-sdk --version
Authentification à l'API
Chaque requête vers l'API Cloud Agents nécessite un jeton bearer. Le SDK gère cela automatiquement lors de l'initialisation d'un client :
import { CursorCloudClient } from "@cursor/cloud-agents-sdk";
const client = new CursorCloudClient({
apiKey: process.env.CURSOR_API_KEY,
// Optionnel : remplacer le point de terminaison API par défaut
endpoint: "https://api.cursor.sh/v1",
// Optionnel : définir un délai d'expiration par défaut pour toutes les opérations
timeout: 300000, // 5 minutes
});
Si vous préférez les appels HTTP bruts plutôt que le SDK, incluez manuellement l'en-tête :
import os
import requests
headers = {
"Authorization": f"Bearer {os.environ['CURSOR_API_KEY']}",
"Content-Type": "application/json",
}
response = requests.post(
"https://api.cursor.sh/v1/agents",
headers=headers,
json={
"repo": "https://github.com/my-org/my-repo",
"branch": "feature/auth-refactor",
"task": "Refactor the authentication module to use JWT",
},
)
print(response.json())
Ne committez jamais votre clé API dans le contrôle de version. Si une clé est compromise, révoquez-la immédiatement depuis le tableau de bord Cursor et générez-en une nouvelle. Renouvelez les clés régulièrement.
Cycle de vie des agents cloud
Un agent cloud progresse à travers un cycle de vie bien défini. Comprendre chaque état vous aide à construire des pipelines d'automatisation robustes.
États du cycle de vie
| État | Description |
|---|---|
queued | L'agent a été créé et attend un emplacement cloud |
running | L'agent exécute activement la tâche |
paused | L'agent a été mis en pause par un steering en cours d'exécution ou une intervention manuelle |
completed | L'agent a terminé la tâche avec succès |
failed | L'agent a rencontré une erreur dont il n'a pas pu se remettre |
cancelled | L'agent a été annulé par l'utilisateur ou par un délai d'attente |
Création d'un nouvel agent
const agent = await client.agents.create({
repo: "https://github.com/my-org/my-repo",
branch: "feature/payment-gateway",
task: "Integrate Stripe payment gateway with proper error handling",
// Paramètres optionnels
model: "cursor-agent-pro",
maxSteps: 50,
autoMerge: false,
environment: {
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
},
});
console.log(`Agent created with ID: ${agent.id}`);
console.log(`Initial status: ${agent.status}`);
Surveillance du statut de l'agent
Vous pouvez interroger le statut de l'agent ou vous abonner aux mises à jour en temps réel :
// Approche par interrogation
async function waitForCompletion(agentId: string) {
while (true) {
const status = await client.agents.get(agentId);
console.log(`[${new Date().toISOString()}] Status: ${status.state}`);
if (status.state === "completed") {
return status;
}
if (status.state === "failed" || status.state === "cancelled") {
throw new Error(`Agent ended in state: ${status.state}`);
}
await new Promise((resolve) => setTimeout(resolve, 10000)); // interrogation toutes les 10s
}
}
// Approche par flux (recommandée)
const stream = await client.agents.stream(agent.id, (event) => {
console.log(`Event: ${event.type}`, event.data);
});
stream.on("step", (data) => {
console.log(`Agent step: ${data.description}`);
});
stream.on("file_change", (data) => {
console.log(`File modified: ${data.path}`);
});
stream.on("error", (data) => {
console.error(`Agent error: ${data.message}`);
});
Préférez l'approche par flux à l'interrogation. Elle réduit les appels API, fournit des mises à jour à plus faible latence et évite les problèmes de limite de débit pendant les tâches de longue durée.
Steering en cours d'exécution
L'une des fonctionnalités les plus puissantes de l'API Cloud Agents est la capacité d'orienter un agent pendant qu'il s'exécute activement. Cela vous permet de corriger le cap, d'ajouter du contexte ou de changer de direction sans recommencer à zéro.
Envoi d'un message de steering
const steerResult = await client.agents.steer(agent.id, {
message: "Stop using the mock data approach. Please connect to the real database using the connection string in the .env file.",
// Optionnel : attacher une référence de fichier
attachments: ["src/config/database.ts"],
// Optionnel : changer de modèle en cours d'exécution
model: "cursor-agent-pro",
});
console.log(`Steer accepted: ${steerResult.accepted}`);
console.log(`Agent now running with updated context`);
Scénarios de steering courants
Le steering en cours d'exécution est utile dans plusieurs situations :
- Corriger une mauvaise approche : L'agent commence à écrire des tests simulés alors que vous vouliez des tests d'intégration.
- Ajouter du contexte manquant : L'agent ne connaît pas un module utilitaire partagé que vous avez créé la semaine dernière.
- Changer la portée : Vous voulez que l'agent ajoute également de la documentation pour le code qu'il vient d'écrire.
- Imposer des contraintes : L'agent est sur le point de modifier des fichiers en dehors de la portée prévue.
// Exemple : Steering pour ajouter une portée de documentation
await client.agents.steer(agent.id, {
message: "Great progress on the API endpoints. Now also add JSDoc comments to every exported function and update the README with the new endpoint list.",
});
// Exemple : Steering pour imposer une limite de sécurité
await client.agents.steer(agent.id, {
message: "Do not modify any files in the src/legacy/ directory. Those are deprecated modules scheduled for removal.",
});
Les messages de steering sont traités de manière asynchrone. Il y a une brève fenêtre entre l'envoi du steering et son intégration par l'agent. N'envoyez pas plusieurs messages de steering conflictuels en succession rapide, car cela peut confondre l'agent et entraîner un comportement incohérent.
Mise en pause et reprise des agents
// Mettre en pause un agent en cours d'exécution
await client.agents.pause(agent.id);
console.log("Agent paused");
// Examiner l'état actuel
const state = await client.agents.get(agent.id);
console.log("Files changed so far:", state.filesChanged);
// Reprendre quand prêt
await client.agents.resume(agent.id);
console.log("Agent resumed");
API RecordScreen
L'API RecordScreen capture des instantanés visuels de l'écran de l'agent cloud à des moments précis. Cela est inestimable pour le débogage, l'audit et la construction de tableaux de bord visuels.
Capture d'une capture d'écran
// Capturer une seule capture d'écran
const screenshot = await client.agents.recordScreen(agent.id, {
format: "png",
// Optionnel : capturer uniquement une région
region: { x: 0, y: 0, width: 1920, height: 1080 },
// Optionnel : inclure un repère de position du curseur
showCursor: true,
});
// La capture d'écran est renvoyée sous forme de chaîne base64
const fs = require("fs");
fs.writeFileSync(`agent-${agent.id}-screenshot.png`, Buffer.from(screenshot.data, "base64"));
console.log(`Screenshot saved. Size: ${screenshot.width}x${screenshot.height}`);
Enregistrement d'un clip vidéo
// Démarrer un enregistrement d'écran
const recording = await client.agents.recordScreen(agent.id, {
mode: "video",
duration: 30000, // 30 secondes
fps: 15,
format: "webm",
});
// L'enregistrement renvoie une URL téléchargeable
console.log(`Recording available at: ${recording.url}`);
console.log(`Recording expires at: ${recording.expiresAt}`);
Dépannage des échecs RecordScreen
Les appels RecordScreen peuvent échouer pour plusieurs raisons. Voici les problèmes les plus courants et leurs solutions :
RecordScreen renvoie une erreur 409 Conflict si l'agent n'est pas dans l'état running. Assurez-vous que l'agent s'exécute activement avant d'essayer de capturer son écran. Si l'agent a été mis en pause ou a terminé, vous ne pouvez pas enregistrer son écran.
// Wrapper RecordScreen sécurisé avec gestion des erreurs
async function safeRecordScreen(agentId: string, options: any) {
const agent = await client.agents.get(agentId);
if (agent.state !== "running") {
console.warn(`Cannot record screen: agent is in ${agent.state} state`);
return null;
}
try {
return await client.agents.recordScreen(agentId, options);
} catch (error: any) {
if (error.code === "SCREEN_CAPTURE_UNAVAILABLE") {
console.error("Screen capture is not available for this agent configuration.");
console.error("Make sure the agent was launched with screen capture enabled.");
} else if (error.code === "RATE_LIMITED") {
console.error("Too many screen capture requests. Please wait before retrying.");
console.log(`Retry after: ${error.retryAfter} seconds`);
} else {
throw error;
}
return null;
}
}
Pour activer la capture d'écran lors de la création d'un agent, définissez l'option screenCapture :
const agent = await client.agents.create({
repo: "https://github.com/my-org/my-repo",
branch: "main",
task: "Fix the flaky integration tests",
screenCapture: {
enabled: true,
autoCapture: true, // Capturer automatiquement à chaque étape
captureInterval: 5000, // Capturer toutes les 5 secondes
},
});
L'activation de autoCapture génère une chronologie visuelle du travail de l'agent. Vous pouvez rejouer toute la session ultérieurement pour le débogage ou les revues de conformité. Sachez que cela augmente l'utilisation du stockage et peut affecter légèrement les performances de l'agent.
Rappels Webhook
Les webhooks vous permettent de recevoir des notifications en temps réel lorsque des événements d'agent se produisent. C'est essentiel pour construire des pipelines CI/CD automatisés et des tableaux de bord de surveillance.
Enregistrement d'un webhook
const webhook = await client.webhooks.create({
url: "https://my-app.com/api/cursor-webhook",
events: [
"agent.created",
"agent.step_completed",
"agent.completed",
"agent.failed",
"agent.steer_received",
],
// Optionnel : ajouter un secret pour la vérification de signature
secret: process.env.WEBHOOK_SECRET,
});
console.log(`Webhook registered with ID: ${webhook.id}`);
Traitement des charges utiles webhook
Voici un exemple de point de terminaison Express qui reçoit et vérifie les rappels webhook :
const express = require("express");
const crypto = require("crypto");
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/api/cursor-webhook", (req, res) => {
// Vérifier la signature du webhook
const signature = req.headers["x-cursor-signature"];
const expectedSignature = crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
if (signature !== expectedSignature) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body.toString());
switch (event.type) {
case "agent.created":
console.log(`Agent ${event.data.agentId} created for repo ${event.data.repo}`);
break;
case "agent.step_completed":
console.log(`Agent ${event.data.agentId} completed step ${event.data.stepNumber}`);
console.log(` Files changed: ${event.data.filesChanged.join(", ")}`);
break;
case "agent.completed":
console.log(`Agent ${event.data.agentId} completed successfully`);
console.log(` Pull request: ${event.data.pullRequestUrl}`);
// Déclencher le pipeline CI en aval
triggerCIPipeline(event.data.agentId);
break;
case "agent.failed":
console.error(`Agent ${event.data.agentId} failed: ${event.data.error}`);
// Envoyer une alerte au canal d'équipe
sendAlert(event.data);
break;
}
// Toujours répondre avec 200 pour accuser réception
res.status(200).send("OK");
});
app.listen(3000, () => {
console.log("Webhook server listening on port 3000");
});
Vérifiez toujours les signatures webhook. Sans vérification de signature, un attaquant pourrait envoyer des charges utiles webhook falsifiées à votre point de terminaison. L'en-tête x-cursor-signature contient un hachage HMAC-SHA256 du corps de requête brut signé avec votre secret webhook.
Comportement de réessai webhook
Si votre point de terminaison ne répond pas avec un statut 200 dans les 10 secondes, l'API relance la livraison. Le calendrier de réessai est le suivant :
| Tentative | Délai |
|---|---|
| 1er réessai | 1 minute |
| 2e réessai | 5 minutes |
| 3e réessai | 30 minutes |
| 4e réessai | 2 heures |
| Final | 12 heures |
Après la tentative finale, la livraison du webhook est marquée comme échouée et vous devrez vérifier manuellement le statut de l'agent via l'API.
Si votre traitement de webhook implique des opérations de longue durée, répondez immédiatement avec 200 et poussez le travail vers une file d'attente en arrière-plan. Cela évite les délais d'attente et assure une livraison fiable des webhooks.
Modèles d'intégration du SDK
Modèle 1 : Intégration de pipeline CI/CD
Générer automatiquement un agent cloud lorsqu'une pull request est ouverte :
import { CursorCloudClient } from "@cursor/cloud-agents-sdk";
const client = new CursorCloudClient({
apiKey: process.env.CURSOR_API_KEY,
});
export async function onPullRequestOpened(pr: any) {
const agent = await client.agents.create({
repo: pr.repositoryUrl,
branch: pr.headBranch,
task: `Review and improve this pull request. Focus on: ${pr.description}`,
autoMerge: false,
screenCapture: { enabled: true },
});
// Commenter sur la PR avec le lien de l'agent
await pr.addComment(
`A Cursor Cloud Agent is now reviewing this PR. ` +
`Track progress: https://cursor.sh/agents/${agent.id}`
);
return agent;
}
Modèle 2 : Orchestration multi-agents
Exécuter plusieurs agents en parallèle sur différentes tâches :
async function runParallelAgents(repo: string) {
const tasks = [
"Write unit tests for the authentication module",
"Write unit tests for the payment module",
"Write integration tests for the API endpoints",
"Update API documentation with OpenAPI specs",
];
const agents = await Promise.all(
tasks.map((task) =>
client.agents.create({
repo,
branch: "main",
task,
model: "cursor-agent-pro",
})
)
);
console.log(`Launched ${agents.length} agents in parallel`);
// Attendre que tous les agents terminent
const results = await Promise.allSettled(
agents.map((agent) => waitForCompletion(agent.id))
);
// Résumer les résultats
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(`Task ${index + 1}: Completed - ${result.value.filesChanged.length} files changed`);
} else {
console.error(`Task ${index + 1}: Failed - ${result.reason.message}`);
}
});
}
L'exécution de plusieurs agents en parallèle consomme rapidement les ressources cloud. Surveillez votre utilisation et définissez une limite maxSteps raisonnable pour chaque agent afin de contrôler les coûts. Vérifiez la limite d'agents simultanés de votre plan avant de lancer de grands lots.
Modèle 3 : Révision humaine dans la boucle
Combiner les webhooks avec le steering en cours d'exécution pour créer un point de contrôle de révision humaine :
// Lorsque l'agent atteint une certaine étape, mettre en pause pour révision humaine
const stream = await client.agents.stream(agent.id, async (event) => {
if (event.type === "step" && event.data.stepNumber === 10) {
// Mettre en pause l'agent pour révision humaine
await client.agents.pause(agent.id);
// Envoyer une notification au canal de révision
await sendSlackNotification({
channel: "#code-review",
text: `Agent ${agent.id} has paused for review. Check the changes before resuming.`,
});
// Le réviseur humain reprendra ou orientera manuellement l'agent
}
});
Modèle 4 : Récupération automatique d'erreurs
async function runWithRetry(repo: string, task: string, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const agent = await client.agents.create({
repo,
branch: "main",
task,
maxSteps: 30,
});
try {
const result = await waitForCompletion(agent.id);
if (result.state === "completed") {
return result;
}
} catch (error) {
console.error(`Attempt ${attempt} failed: ${error.message}`);
if (attempt < maxRetries) {
// Orienter la prochaine tentative avec le contexte d'erreur
task = `${task}\n\nPrevious attempt failed with: ${error.message}. Please avoid this approach.`;
}
}
}
throw new Error(`Agent failed after ${maxRetries} attempts`);
}
Dépannage des problèmes courants
Agent bloqué dans l'état en file d'attente
Si un agent reste dans l'état queued pendant une période prolongée, cela signifie généralement que tous les emplacements cloud sont occupés.
// Vérifier l'utilisation actuelle de votre compte
const usage = await client.usage.get();
console.log(`Active agents: ${usage.activeAgents}/${usage.maxConcurrentAgents}`);
console.log(`Queue length: ${usage.queueLength}`);
if (usage.activeAgents >= usage.maxConcurrentAgents) {
console.log("All slots are in use. Consider upgrading your plan or waiting for agents to complete.");
}
Erreurs d'authentification SDK
Si vous recevez une erreur 401 Unauthorized, vérifiez les points suivants :
- Votre clé API est valide et n'a pas été révoquée
- La clé a la portée
cloud-agentsactivée - Vous utilisez l'URL de point de terminaison correcte
- La variable d'environnement est correctement chargée
// Déboguer l'authentification
const client = new CursorCloudClient({
apiKey: process.env.CURSOR_API_KEY,
});
try {
const me = await client.auth.verify();
console.log("Authentication successful");
console.log(`Account: ${me.accountName}`);
console.log(`Plan: ${me.plan}`);
console.log(`Scopes: ${me.scopes.join(", ")}`);
} catch (error) {
console.error("Authentication failed:", error.message);
console.log("Check your API key and ensure it has the 'cloud-agents' scope.");
}
Échecs de livraison webhook
Si les webhooks n'arrivent pas à votre point de terminaison :
- Vérifiez que l'URL du webhook est publiquement accessible (pas localhost)
- Confirmez que votre serveur renvoie 200 dans les 10 secondes
- Vérifiez que votre certificat SSL est valide
- Assurez-vous que votre pare-feu autorise les connexions entrantes depuis les plages IP de Cursor
// Tester l'accessibilité du point de terminaison webhook
const test = await client.webhooks.test(webhook.id);
console.log(`Test result: ${test.status}`);
console.log(`Response time: ${test.responseTime}ms`);
if (test.error) {
console.error(`Error: ${test.error}`);
}
Utilisez un service comme webhook.site ou ngrok pendant le développement pour tester rapidement la livraison des webhooks sans déployer un serveur complet. Cela aide à isoler si le problème vient de votre point de terminaison ou de la configuration du webhook.
Résumé des meilleures pratiques
Voici une liste de contrôle des meilleures pratiques à suivre lors de la construction avec l'API et le SDK Cursor Cloud Agents :
- Stockez toujours les clés API dans des variables d'environnement ou un gestionnaire de secrets
- Utilisez le flux plutôt que l'interrogation pour les mises à jour en temps réel
- Implémentez la vérification de signature webhook sur chaque point de terminaison
- Définissez des limites
maxStepsraisonnables pour contrôler les coûts et prévenir les agents incontrôlés - Utilisez le steering en cours d'exécution pour corriger le cap plutôt que de redémarrer les agents
- Activez la capture d'écran pour le débogage et les pistes d'audit sur les tâches critiques
- Implémentez un backoff exponentiel lors des nouvelles tentatives d'appels API échoués
- Surveillez votre utilisation d'agents simultanés pour éviter la famine de file d'attente
- Testez les points de terminaison webhook avec le point de terminaison de test intégré avant la mise en production
- Journalisez tous les événements d'agent pour l'analyse post-mortem et la conformité
Soyez attentif aux limites de débit. L'API applique une limite par défaut de 100 requêtes par minute. Si vous dépassez cette limite, vous recevez une réponse 429 Too Many Requests. Implémentez un backoff exponentiel avec gigue pour gérer les réessais de limite de débit de manière élégante.
Conclusion
L'API et le SDK Cursor Cloud Agents fournissent une interface programmatique puissante pour automatiser les tâches de codage à grande échelle. En combinant la gestion du cycle de vie des agents, le steering en cours d'exécution, l'API RecordScreen et les rappels webhook, vous pouvez construire des pipelines d'automatisation sophistiqués qui s'intègrent de manière transparente à votre flux de travail de développement existant.
Commencez avec une configuration simple à agent unique, puis ajoutez progressivement l'intégration webhook, l'orchestration parallèle et les points de contrôle de révision humaine à mesure que votre confiance grandit. La conception TypeScript-first du SDK facilite son intégration dans les applications Node.js modernes, tandis que l'API HTTP brute prend en charge n'importe quel langage de programmation.