Go SDK for Cursor Cloud Agents API v1.
This is an unofficial community SDK. It is not maintained, endorsed, or supported by Cursor. The Cloud Agents API is currently in public beta, so API behavior and SDK types may change before general availability.
This package is REST-backed and cloud-focused. It provides typed Cloud Agents API methods plus a higher-level Agent/Run facade inspired by the TypeScript SDK.
Install the module from GitHub:
go get github.com/donvito/cursor-sdk-goThen import it:
import cursor "github.com/donvito/cursor-sdk-go"For local development in this repository:
go test ./...Create a Cursor API key from Cursor Dashboard -> Integrations, then set:
export CURSOR_API_KEY="your-key"You can also pass APIKey directly in AgentOptions or NewClient.
package main
import (
"context"
"fmt"
"log"
"os"
cursor "github.com/donvito/cursor-sdk-go"
)
var (
cursorRepoURL = "https://github.com/your-org/your-repo"
cursorStartingRef = "main"
)
func main() {
ctx := context.Background()
apiKey := os.Getenv("CURSOR_API_KEY")
agent, err := cursor.CreateAgent(ctx, cursor.AgentOptions{
APIKey: apiKey,
Model: cursor.ModelSelection{ID: "composer-2"},
Cloud: cursor.CloudOptions{
Repos: []cursor.Repo{{
URL: cursorRepoURL,
StartingRef: cursorStartingRef,
}},
AutoCreatePR: cursor.Bool(true),
},
})
if err != nil {
log.Fatal(err)
}
defer agent.Close(context.Background())
run, err := agent.Send(ctx, "review the code, run tests and document results in a markdown file. put in a directory review-results")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Started %s\n", run.ID)
laterRun, err := cursor.GetRun(ctx, run.ID, cursor.GetRunOptions{
Runtime: "cloud",
AgentID: run.AgentID,
APIKey: apiKey,
})
if err != nil {
log.Fatal(err)
}
result, err := laterRun.Wait(ctx)
if err != nil {
log.Fatal(err)
}
if len(result.Git.Branches) > 0 {
fmt.Println(result.Git.Branches[0].PRURL)
}
}The public REST API creates a cloud agent together with its first prompt. To keep the TypeScript-like CreateAgent then Send shape, this Go facade creates the remote cloud agent lazily on the first Send.
Use Prompt when you want create, send, wait, and close in one call.
result, err := cursor.Prompt(ctx, "What does this repository do?", cursor.AgentOptions{
APIKey: os.Getenv("CURSOR_API_KEY"),
Model: cursor.ModelSelection{ID: "composer-2"},
Cloud: cursor.CloudOptions{
Repos: []cursor.Repo{{
URL: "https://github.com/your-org/your-repo",
StartingRef: "main",
}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Status)stream, err := run.Stream(ctx)
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for {
event, err := stream.Next()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
log.Fatal(err)
}
switch event.Type {
case "assistant", "thinking":
fmt.Print(event.Text)
case "status", "result":
fmt.Printf("[%s] %s\n", event.Type, event.Status)
case "error":
fmt.Printf("stream error: %s %s\n", event.Code, event.Text)
}
}To resume a stream after reconnecting:
stream, err := run.Stream(ctx, cursor.WithLastEventID(lastEventID))The stream preserves the SSE event id, event name, raw JSON payload, and X-Cursor-Stream-Retention-Seconds header.
Use NewClient for direct Cloud Agents API access.
client, err := cursor.NewClient(os.Getenv("CURSOR_API_KEY"))
if err != nil {
log.Fatal(err)
}
models, err := client.ListModels(ctx)
if err != nil {
log.Fatal(err)
}
for _, model := range models {
fmt.Println(model.ID)
}Common client methods include:
CreateAgent,ListAgents,GetAgentCreateRun,ListRuns,GetRun,StreamRun,CancelRunListArtifacts,DownloadArtifactArchiveAgent,UnarchiveAgent,DeleteAgentCreateSubTokenMe,ListModels,ListRepositories
artifacts, err := agent.ListArtifacts(ctx)
if err != nil {
log.Fatal(err)
}
for _, artifact := range artifacts {
fmt.Println(artifact.Path, artifact.SizeBytes)
}
download, err := agent.DownloadArtifact(ctx, artifacts[0].Path)
if err != nil {
log.Fatal(err)
}
fmt.Println(download.URL)DownloadArtifact returns a temporary presigned URL.
CreateSubToken uses bearer auth, matching the service-account API key flow documented for /v1/sub-tokens.
client, err := cursor.NewClient(os.Getenv("CURSOR_SERVICE_ACCOUNT_API_KEY"))
if err != nil {
log.Fatal(err)
}
token, err := client.CreateSubToken(ctx, cursor.CreateSubTokenRequest{
ForUserEmail: "alice@company.com",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(token.ExpiresAt)Non-2xx responses return *cursor.APIError.
var apiErr *cursor.APIError
if errors.As(err, &apiErr) {
fmt.Println(apiErr.StatusCode, apiErr.Code, apiErr.Message)
if apiErr.Retryable() {
// Retry with backoff.
}
}Supported:
- Cloud agent creation and resume-by-ID
- Follow-up runs
- Run polling, cancellation, and SSE streaming
- Artifacts
- Archive, unarchive, and delete
- Account metadata, model listing, repository listing
- Service-account worker sub-tokens
Not supported in this REST-backed SDK:
- Local runtime
- Structured
conversation - Raw delta callbacks
reload- Local artifact downloads
- Hooks management
- Full MCP and subagent lifecycle management
- Self-hosted pool or machine routing unless the public REST API exposes it
Unsupported operations return UnsupportedRunOperationError where applicable.
Runnable examples live in:
examples/create_agentexamples/promptexamples/stream_runexamples/list_modelsexamples/download_artifact
Run examples from the repository root:
cd /Users/melvin/Documents/GitHub/cursor-sdk-go
export CURSOR_API_KEY="your-key"
go run ./examples/list_modelsexamples/list_models is the safest first example because it only reads the model catalog.
To start a cloud agent with the sample workflow:
go run ./examples/create_agentTo run the Go counterpart of TypeScript Agent.prompt(...):
go run ./examples/promptThe cloud examples define the target repository in code:
var (
cursorRepoURL = "https://github.com/your-org/your-repo"
cursorStartingRef = "main"
)Edit cursorRepoURL and cursorStartingRef before running go run ./examples/create_agent or go run ./examples/prompt.
Your API key needs access to the repository through Cursor's GitHub integration.
Other examples:
go run ./examples/stream_run
go run ./examples/download_artifact <agent-id> <artifact-path>examples/stream_run contains a placeholder repository URL; update it before running.