Appearance
Cloud runtime
By default, turns execute on the Cursor SDK's local harness, on the same machine as the server. Set runtime: "cloud" and turns execute on Cursor cloud agents instead. They're ephemeral VMs that carry a repo checkout, run gh, git, and tests for real, and scale past what one host's disk and CPU can do. The serve host keeps handling routing, host preparation, sessions, and bookkeeping.
A canonical use is a PR driver whose triage runs on cloud VMs. The patterns in this guide come from running one against real PR traffic.
When to switch
A guideline from running PR agents at scale: per-PR worktrees on the serve host don't scale to hundreds of engineers opening PRs. When the job needs a repo checkout at scale, use cloud. The signals:
- The agent must run repo commands (tests, builds,
git) against many different refs concurrently. - Turns are long and heavy, and you don't want them competing with the server for resources.
- The work product is a PR or branch the VM can push, not a local file.
Stay local when the agent is conversational, tool-driven against APIs, or works over host-prepared evidence. Local turns are cheaper, start faster, and support the full authored surface.
Configure it
Cloud runtime is two fields on the agent config.
ts
import { defineAgent } from "@cursor/july";
export default defineAgent({
runtime: "cloud",
cloud: {
repos: [{ url: "https://github.com/org/repo", startingRef: "main" }],
// env / envVars / … forwarded to the Cursor SDK
},
});The host must be signed in (agent-sdk login or CURSOR_API_KEY).
IMPORTANT
Cloud agents run against the Cursor backend under the signed-in account, and every wake spends real cloud-agent budget. Decide explicitly what may trigger one.
What changes on cloud
Cloud turns run on a VM without your authored files, so the runtime mapping shifts:
| Folder or file | Local runtime | Cloud runtime |
|---|---|---|
instructions.* | AGENTS.md in the session workspace | prepended to the first prompt |
Server tools (execution: "server") | in-process SDK custom tools | authenticated HTTP MCP back to the AgentSDK host, when --public-url or --cloud-tools-url is set |
Agent tools (execution: "agent") | scripts in the session workspace | catalog + script bodies on the first prompt |
skills/* | .cursor/skills/ in the workspace | only if present in the cloud repo |
mcp-connections/*.ts | SDK mcpServers | SDK mcpServers (peers need --public-url) |
sandbox/workspace/** | seeded into the session workspace | ignored |
Tool approvals (needsApproval) | supported | not supported; keep approval-gated tools on local turns |
Hosted deployments configure the server-tool MCP URL automatically (cloudToolsUrl, authenticated with the resolved Cursor API key). A self-hosted public server needs --public-url (and --bearer-token when the host is not behind another trusted authentication boundary) so cloud turns can reach those tools. Without either, the server warns at startup and cloud turns omit the server tools.
Approvals are a local-runtime contract. On cloud, a needsApproval tool call rides one HTTP MCP request from the VM, and a parked call would hold that request open until it times out; there is no durable approval flow for cloud turns.
Two more behaviors are cloud-specific. Sessions persist a separate SDK agent id (bc-…), emitted on the stream as agent.bound with a URL to the cloud conversation. Cloud ids are minted during the first send. And peer MCP connections resolve to --public-url for cloud turns, because a VM cannot reach the host's loopback; without one, peers are omitted from cloud turns and the server warns at startup.
Hybrid: local agent, cloud sessions
A local-runtime agent can still open cloud-attached sessions per send. Channel handlers may pass a cloud block (repos pinned to a PR ref, say) in send options, and Slack handlers may return cloud from a mention hook. A PR driver works this way: chat stays local, and the drive flow attaches the PR to a cloud VM. The agent-level cloud config is the base that per-session options merge over.
Patterns that hold up
These come from running a PR driver against real PR traffic:
- One cloud agent per unit of work (per PR, say). Store the
bc-…id keyed by the work unit (an affinity store written from anagent.boundhook) so webhook wakes resume the same conversation instead of booting a fresh VM per event. - Stable continuation keys (
pr:owner/repo#N) so every wake lands on the same session within a channel. - Keep the host deterministic: fetch briefs and metadata on the host, send the VM a compact prompt, and let the VM re-read source of truth with its own
ghandgitinstead of trusting payload snapshots. - Limit exposure: add repository allowlists on webhook channels, because every wake spends the account's budget.
Verify cloud agents
agent-sdk run and eval work unchanged. The trajectory records the same event vocabulary plus agent.bound with the cloud URL, so you can open the cloud conversation for any session. Cloud turns take minutes. Pass generous --timeout-ms values, and keep curl timeouts long when driving channels directly.
What's next
Continue with these pages:
- Agent config: the
runtimeandcloudfields precisely - GitHub guide: the webhook patterns that pair with cloud triage