Skip to main content

Command Palette

Search for a command to run...

Cloud Agents

Agent metadata

Cloud Agents can read key-value metadata about the current run from inside the VM: the agent id, who owns it, who submitted this turn, which model is serving, and which repos are checked out. Hooks and install scripts can read those values too.

Agents call this API with their terminal tools. You don't need to run these requests yourself.

To have an agent read metadata, include this in your prompt:

To read agent metadata, follow the instructions athttps://cursor.com/docs/cloud-agent/metadata

This API is local to the agent VM. It is not the caller-owned metadata tags you set when creating an agent with the SDK or Cloud Agents API. Those APIs use Cursor API keys and manage agents from outside the VM.

When something outside the VM needs to verify the agent's identity, have the agent mint an OIDC token instead. Those JWTs are signed and audience-bound. Metadata is not a credential. It can include the current turn's submitter and serving model, which a token shouldn't carry.

Cursor-managed Cloud Agent VMs serve metadata on the same socket as OIDC tokens. Self-hosted workers do not serve this API yet.

Read a value

The agent reads keys over the Unix socket at CURSOR_AGENT_SOCKET. On Cursor-managed VMs the default is /run/cursor/api.sock.

curl --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" \  http://cursor-agent/v1/meta-data/agent/id

Requests are HTTP over a Unix socket. The hostname in the URL is ignored.

List a prefix to see which keys exist:

curl --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" \  http://cursor-agent/v1/meta-data/
agent/owner/turn/workspace/

Then request a key:

curl --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" \  http://cursor-agent/v1/meta-data/owner/user-id

Request

GET /v1/meta-data[/<path>] over the Unix socket. No body or extra headers. Trailing slashes are allowed, so a listed agent/ can be requested as /v1/meta-data/agent/.

A missing key returns 404.

Response

Successful reads are text/plain; charset=utf-8. A key response is the value as text, with nothing else.

KindBody
KeyThe value as a string. Keys with several values put one entry per line.
PrefixOne child per line, sorted. Nested prefixes end with /. The listing ends with a trailing newline.

Error responses are JSON. See Rate limits and errors.

When keys appear

Install scripts can read the same socket. A key is present only when it has a value: turn/ is missing until a coding turn starts, and workspace/branch-name is missing until the run records a branch. Owner, team, and repository keys are available from agent creation onward.

If the socket is missing right after boot, retry the connection.

Keys

Missing keys are omitted from listings and return 404 if requested directly. A listing only includes keys that exist right now.

agent/

KeyWhen presentDescription
agent/idAlwaysCloud Agent id (bcId).
agent/nameWhen knownName shown in the dashboard.
agent/sourceWhen knownHow the agent was started, such as WEBSITE, API, SLACK, or AUTOMATIONS.
agent/runtimeAlwaysmanaged on Cursor-managed Cloud Agent VMs.

owner/

KeyWhen presentDescription
owner/user-idWhen knownCursor user id of the agent owner, as a decimal string. Prefer this over email for allowlists.
owner/user-emailWhen knownLowercased owner email. Email can change.
owner/service-account-idWhen knownService account id when a service account owns the agent.
owner/team-idWhen knownOwning team id, as a decimal string.

turn/

turn/ exists only while a coding turn is active. Between turns those keys are gone. If turn/ is missing, there is no active turn.

Values under turn/ always reflect the current turn. Don't cache them across turns.

KeyWhen presentDescription
turn/idDuring a turnId of this coding turn. Different from agent/id, which is the Cloud Agent id (bcId).
turn/user-idWhen knownCursor user id of the person who submitted this turn, as a decimal string. On a team follow-up this can differ from owner/user-id.
turn/user-emailWhen knownLowercased email of that person.
turn/started-atDuring a turnTurn start as Unix seconds.
turn/modelWhen knownModel serving this turn. If you selected Auto, this is the model that served, not Auto.

OIDC tokens don't include who submitted the turn or which model is serving, because a token can outlive the turn. Read those keys from metadata instead.

workspace/

KeyWhen presentDescription
workspace/repo-urlWhen knownPrimary repository in host/path form, such as github.com/acme/widgets. Hostname is lowercased, with no scheme, credentials, port, query, or .git suffix. On a multi-repo agent, this is only the primary repository.
workspace/repo-urlsWhen the set is knownEvery repository in the workspace, same form as repo-url. Primary repository first, then the rest sorted, one URL per line. Missing means the set isn't known, not that there is only one repo.
workspace/branch-nameWhen knownBranch on the primary repository.
workspace/environment-idWhen knownId of the Cursor environment this run used.
workspace/automation-idFor automationsAutomation id when agent/source is automations.

workspace/repo-url is the primary repository. For the full set, read workspace/repo-urls.

Who can read metadata

Any process that can reach the socket can read every key: the agent, code it runs, and hooks. Treat these values as visible to the whole run.

Metadata is not signed. To prove identity to AWS, GCP, Vault, or your own service, have the agent mint an OIDC token and verify the JWT. Don't forward metadata values as a credential.

Rate limits and errors

Each agent VM can make 120 metadata requests per minute, in bursts of up to 20. The socket also accepts at most 8 connections at once. That cap is shared with OIDC minting.

Retry 429, 503, 500, 502, and 504 with backoff. Treat 403 as fatal: this agent isn't allowed to read metadata.

404 and 405 responses include a usage string that restates how to call the API. Rate-limit and saturation errors stay code-only:

{ "error": "not_found", "usage": "GET /v1/meta-data[/<path>] ..." }
{ "error": "rate_limited" }
HTTPerrorWhen
404not_foundUnknown or missing key
405method_not_allowedNot GET
429rate_limitedOver the per-agent request budget; honor Retry-After
503saturatedToo many connections; honor Retry-After
500host_errorInternal error; retry
502 / 504backend_unreachableCursor couldn't return metadata; retry
Otherbackend_errorCursor rejected the request. 403 is fatal; 503 is retryable

Examples

An agent or hook can compare the turn submitter to the owner. A teammate's follow-up can take a stricter path:

SOCKET="${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}"owner="$(curl -fsS --unix-socket "$SOCKET" \  http://cursor-agent/v1/meta-data/owner/user-id)"turn_user="$(curl -fsS --unix-socket "$SOCKET" \  http://cursor-agent/v1/meta-data/turn/user-id || true)"if [ -n "$turn_user" ] && [ "$turn_user" != "$owner" ]; then  echo "follow-up from user $turn_user; owner is $owner"fi

An agent or hook can tag logs with the agent id and the model that served the turn:

SOCKET="${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}"agent_id="$(curl -fsS --unix-socket "$SOCKET" \  http://cursor-agent/v1/meta-data/agent/id)"model="$(curl -fsS --unix-socket "$SOCKET" \  http://cursor-agent/v1/meta-data/turn/model || true)"echo "cloud_agent_id=$agent_id model=${model:-unknown}"

List every repository in the workspace. repo-urls is one URL per line:

curl -fsS --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" \  http://cursor-agent/v1/meta-data/workspace/repo-urls
github.com/acme/widgetsgithub.com/acme/docs