Skip to content

agents: document GET /v2/agents/regions (ListRegions) - #1296

Merged
amandhaw merged 9 commits into
mainfrom
marsohs-list-regions-openapi
Nov 6, 2026
Merged

amandhaw merged 9 commits into
mainfrom
marsohs-list-regions-openapi

Conversation

@amandhaw

Copy link
Copy Markdown
Contributor

Summary

Documents GET /v2/agents/regions, the per-team region catalog the console renders as its region picker. The default region is always listed and is marked is_default; every other open region is listed only when the team holds its placement grant, so the catalog agrees slug for slug with what a create admits — a picker built from it never offers a region a create refuses.

GET /v2/agents/regions          scope: agent_harness_session:read

200 {"regions":[{"slug":"mem1","is_default":false},{"slug":"ric1","is_default":true}]}

Draft: do not merge yet

This spec describes the production API, and this endpoint is not in production yet. It is implemented by an open internal PR (cthulhu #183673) and is still refused at the edge until the matching extauth change lands. Opened early so the client-generation checks run and the UI work has the contract to build against.

Ready to merge once the implementation is merged and deployed.

Changes

File
resources/agents/agents_list_regions.yml the operation, harness_list_regions
resources/agents/models/definitions.yml harness_region, harness_regions_response
resources/agents/examples/curl/agents_list_regions.yml curl sample
DigitalOcean-public.v2.yaml registers the path

Modeled on agents_list_session_sandbox_sizes — the nearest sibling, a read-only catalog that feeds a picker — down to the response set, the rate-limit headers and the Harness Runtime tag.

Naming

The schemas are harness_region / harness_regions_response rather than region, which already names the Droplet region schema. Without the prefix the bundler renames them to definitions_region and the generated SDK types read as DefinitionsRegion; the prefix also keeps the Go SDK clear of its existing Region.

Verification

make lint passes with 0 errors. The 8 warnings are all pre-existing on main and none are in the files this PR adds or changes. The bundled spec resolves the 200 to #/components/schemas/harness_regions_response, and the collision-renamed schema list is unchanged from main.

Not run: make test (needs the Docker mock proxies), and no live request — the endpoint is not deployed.

Adds the per-team region catalog the console renders as its region
picker. The default region is always listed; every other open region
is listed only when the team holds its placement grant, so the catalog
agrees slug for slug with what a create admits.

Schemas are named harness_region / harness_regions_response rather than
region, which already names the Droplet region schema; without the
prefix the bundler renames them to definitions_region and the generated
SDK types read as DefinitionsRegion.

Implemented by cthulhu #183673.
@@ -0,0 +1,4 @@
lang: bash

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things need addressing before this merges:

1. Path prefix conflicts with #1302
#1302 moves all Harness Runtime routes from /v2/agents to /v2/harness-runtime and calls out this PR by name: new routes should land on the new prefix. As written, /v2/agents/regions will conflict with that change. Could you move it to /v2/harness-runtime/regions, in both the paths: key in DigitalOcean-public.v2.yaml and the curl example URL? The other option is to agree on a merge order with #1302.

2. Descriptions contradict how placement works today
The operation description says every returned slug "is accepted as the region a session or config is created in". is_default is described as "the region a create lands in when none is named". But create_session_request.region on main says:

Optional placement check, not a placement choice: the session is always created in the region whose API host served the request. If set, it must equal that region, or the request fails with 400 and a region_mismatch message. Honored only for teams on the regional routing rollout; ignored otherwise.

So a client can't choose a region by passing a slug. Placement comes from the regional API host it calls. Could the operation description, harness_region.slug and harness_region.is_default explain how a caller actually uses a returned slug, for example which host to target? It would also help to say how this behaves for teams that aren't on the regional routing rollout.

@amandhaw amandhaw Nov 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both points are correct. Done in 0d7cd80.

1. Prefix. The path and the curl example are now /v2/harness-runtime/regions. This removes the conflict with #1302, thus no merge order is necessary.

2. Descriptions. You are right that they contradicted create_session_request.region. A caller does not choose a region with a slug. The host decides the placement. The text now says this:

  • slug names the regional API host to call. ric1 is https://api-ric1.digitalocean.com.
  • is_default names the region that the region-less host, https://api.digitalocean.com, serves.
  • The operation says that the optional region field on a create is a check against the host, not a choice. It also says that a team outside the regional routing rollout sees only the default region, and gets no region field on its responses.

The same text is corrected in godo digitalocean/godo#1209, thus the SDK and the spec agree. That change is a follow-up to digitalocean/godo#1199, because it came after that PR merged.

make lint gives 0 errors.

…g is used

Moves the path and the curl example to /v2/harness-runtime/regions. #1302
moves the documented Harness Runtime surface to that prefix and names
this PR; a new route under /v2/agents would conflict with it.

Rewrites the descriptions. They said a returned slug "is accepted as the
region a session or config is created in", which reads as a placement
choice. create_session_request.region says the opposite: the session is
always created in the region whose API host served the request, and the
body field is only a check against that host.

The slug now names the host to call, is_default names the region the
region-less host serves, and the operation says what a team outside the
regional routing rollout sees.

Reported in review by @DO-rrao.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants