Feature request: Cloud Agents API live activity stream, stable events, and run summary for third-party chat UIs

Feature request for product/service

– Other –

Describe the request

I’m integrating Cursor Cloud Agents into a third-party chat product where users trigger agents with @cursor from a conversation, similar to native Cursor chat but embedded in our UI.
Today we use the v0 API (POST /v0/agents, GET /v0/agents/{id}, GET /v0/agents/{id}/conversation, webhooks on status changes). It works for launch + final status, but third-party UIs cannot reproduce the native Cloud Agent experience without polling conversation text and guessing progress.
What works today
Launch agent with repository, ref, prompt, model
Webhooks / polling for terminal status (FINISHED, ERROR, STOPPED)
summary, target.prUrl, target.branchName, dashboard URL
GET /conversation for user/assistant message text
What we need (feature requests)

  1. Structured activity / progress events (not just final conversation text)
    In the Cursor app, users see a live feed while an agent runs, e.g.:
    Worked 4m 53s
    Edited 4 files, explored 3 files, other tools +73 -12
    Per-step tool/file operations
    Request: expose a run activity stream as structured events, e.g.:
    {
    “type”: “activity”,
    “timestamp”: “…”,
    “kind”: “file_edit” | “file_read” | “tool_call” | “thinking” | “summary”,
    “message”: “Edited README.md”,
    “metrics”: {
    “filesEdited”: 4,
    “filesExplored”: 3,
    “linesAdded”: 73,
    “linesRemoved”: 12,
    “durationMs”: 293000
    }
    }
    Deliver via SSE or WebSocket on the agent/run, or incremental webhook events — not only on terminal statusChange.
  2. Stable identifiers for conversation sync
    We poll GET /v0/agents/{id}/conversation for live updates. Message id values appear to change between requests (forum thread: unstable message IDs). That makes deduplication and incremental sync fragile.
    Request: stable messageId (or sequence / cursor per message) for incremental consumers.
  3. Rich terminal payload
    For chat UIs we want to persist a final assistant message (summary + links), not the full activity log.
    Request: on FINISHED, include in the agent/run payload (or webhook):
    summary (markdown)
    metrics (duration, files touched, line stats)
    changedFiles (path, additions, deletions) — optional compact list for “Changes” UI
    prUrl, branchName, commitSha when applicable
  4. Clear split: ephemeral stream vs durable summary
    Request: document which fields are:
    Streaming-only (activity feed, tool traces) — not required to persist
    Durable (summary, PR link, final metrics) — safe to store in our database
  5. v1 runs API alignment
    We saw the newer v1 model (agent + run). If v1 is the long-term surface, please document migration from v0 and whether run-level activity streaming will live there first.
    Our use case
    User: @cursor fix the README
    Our UI shows a Connectors section: “Creating cloud agent” (repo, branch, model, prompt)
    While running: live activity (like Cursor app) — session-only, not stored after reload
    When done: persist only final summary + PR/dashboard links in the chat message
    We can hack this with conversation polling today, but structured activity + stable IDs would make integrations reliable and closer to the native product.
    Happy to share more detail or test beta endpoints. Thanks!

Thanks for the detailed write-up. The short answer is that most of what you’re looking for already exists, just on v1 rather than v0.

1. Structured activity events. Every run has an SSE stream:

GET /v1/agents/{id}/runs/{runId}/stream

Events are structured, so there’s nothing to parse out of text:

  • status: run status updates
  • assistant / thinking: text deltas
  • tool_call: { callId, name, status, args?, result?, truncated? }, where name is a public tool name (read_file, run_terminal_cmd, edit_file, mcp) and status moves running to completed
  • interaction_update: richer SDK-shaped events (text-delta, tool-call-started / tool-call-completed, step-started / step-completed, turn-ended). Handle these for full fidelity, or ignore them and use the simplified events above
  • result: { runId, status, text?, durationMs?, git? }
  • heartbeat, error, done

Docs: Cloud Agents API | Cursor Docs
The TypeScript SDK wraps this as run.stream(): Cursor TypeScript SDK | Cursor Documentation

2. Stable identifiers. Use the SSE event id lines. Treat them as opaque and reconnect with Last-Event-ID to resume without gaps or duplicates. callId is stable across a tool call’s running and completed updates. The shifting ids you hit on the v0 conversation endpoint shouldn’t reproduce on the current API, worth re-testing, though the stream removes the polling and dedup problem entirely.

3. Rich terminal payload. Partly there. The result event and GET /v1/agents/{id}/runs/{runId} give final text, durationMs, and git.branches[] with repoUrl, branch, and prUrl. The diff rollup (files edited, lines added and removed, changedFiles[]) isn’t exposed. Fair gap, and we’ve let the team know.

4. Ephemeral vs durable. Already defined. Streams are retained for a window advertised via the X-Cursor-Stream-Retention-Seconds header, after which the endpoint returns 410 stream_expired and you read terminal state from Get A Run. So the activity feed is session-only (matching your UI) and the run’s terminal fields are the durable ones.

5. v1 alignment. v1 is the long-term surface, v0 stays available as legacy. Two gaps before you migrate: webhooks aren’t on v1 yet (the docs flag this, and v0 still has them, so some integrators create via v0 and manage the run on v1), and there’s no v1 REST equivalent of GET /v0/agents/{id}/conversation. For a structured transcript instead of the live stream, the SDK’s run.conversation() returns a per-turn view.

Let me know any follow-up questions!