Coder profiles
A coder profile is the set of settings a builder uses for one card: the model, the effort, a turn or step guard, and how long the build may run. OPVS keeps one catalog of profiles. A card names the profile it wants, the builder's desk fetches it when the build starts, and your workspace can change three of its settings. The dashboard's Coder settings page uses the same routes.
Before you call¶
Every route takes a personal access token, Authorization: Bearer $OPVS_PAT, and acts on the workspace the token belongs to. No extra token scope is needed.
| Group | Who may call | Token scope |
|---|---|---|
| Read profiles and their history | any active member | any |
| Change or reset a setting | a workspace admin | any |
A change applies to builds that start after it. A build already running keeps the settings it started with.
Profile keys¶
A key is <coder>.<tier>. The coders your workspace can use are claude, codex, openhands, opencode and pi; the coder field of a profile spells Claude as claude_code. The tiers are the five card task types, coding, docs, research, design and test, plus hard.
To use a profile, put its key in the card's agent_context.profile, for example codex.coding. A desk whose coder does not match the key skips the profile and builds with its own defaults; a profile never fails a build.
The hard tier¶
Every coder has a .hard profile for risky or large cards, such as sidecar, migration, security or billing work. It uses the highest effort and the largest turn or step guard that coder takes, and lets the build run for 180 minutes. The dashboard's Coder profiles page shows only the five task-type profiles of each coder, so read and change the hard tier through these routes.
| Key | Model | Effort | Guard | Time limit |
|---|---|---|---|---|
claude.hard |
claude-opus-5-5 |
max |
400 turns | 180 min |
codex.hard |
the account's default | high |
none | 180 min |
openhands.hard |
the model the card pins | high |
500 steps | 180 min |
opencode.hard |
MiniMax-M3 |
high |
300 steps | 180 min |
pi.hard |
MiniMax-M3 |
high |
none | 180 min |
How long a build may run¶
A profile's limits.wall_minutes asks for a time limit; the desk decides. A build gets the desk's own limit (120 minutes unless the desk owner changed it) or the profile's request, whichever is longer, and never more than the desk's ceiling (240 minutes by default). A profile with wall_minutes: null runs on the desk's own limit. wall_minutes cannot be changed per workspace.
The profile object¶
| Field | Type | Meaning |
|---|---|---|
key |
string | The profile key, such as codex.hard |
version |
string | sha256: and 12 hex characters, a digest of the settings a build receives. It changes when any of them change |
coder |
string | claude_code, codex, openhands, opencode or pi |
recommended_for |
array of strings | The cards the profile is meant for: a task type for a task-type profile, one sentence for a hard profile |
model |
string or null | The model; null means the coder's own default, or for OpenHands the model the card pins |
effort |
string or null | The reasoning effort the coder is started with |
fallback_model |
string or null | Always null today |
limits.max_turns |
integer or null | Claude's turn guard |
limits.max_steps |
integer or null | OpenHands' and OpenCode's step guard |
limits.wall_minutes |
number or null | The time limit the profile asks for (see above) |
env |
object or null | OpenHands settings the desk applies; platform only |
reason |
string | Why the platform chose these values |
sources.model, sources.effort, sources.limit_value |
string | platform, or brand when your workspace changed that setting |
platform_defaults |
object | model, effort and limit_value as the platform sets them: what a reset returns to |
limit_value is the turn guard for a Claude profile and the step guard for an OpenHands or OpenCode profile.
Read profiles¶
GET /api/v1/factory/coder-profiles¶
Returns every profile your workspace can use, with your workspace's changes applied.
curl "https://api.opvs.ai/api/v1/factory/coder-profiles?coder=codex&task_type=coding" \
-H "Authorization: Bearer $OPVS_PAT"
# Response 200, application/json
# [{"key": "codex.coding", "version": "sha256:77f8246408d6", "coder": "codex",
# "recommended_for": ["coding"], "model": null, "effort": "high",
# "fallback_model": null,
# "limits": {"max_turns": null, "max_steps": null, "wall_minutes": null},
# "env": null,
# "reason": "Seat requires the account-default model; owner-equivalent high effort",
# "sources": {"model": "platform", "effort": "platform", "limit_value": "platform"},
# "platform_defaults": {"model": null, "effort": "high", "limit_value": null}}]
# Without a token the route returns a 401 error.
Query parameters: coder (string, optional): one coder, such as codex. task_type (string, optional): profiles recommended for that task type. A value that matches nothing returns []. Hard profiles carry a sentence in recommended_for, so task_type does not select them: read them by key.
Errors
| Status | When | Resolution |
|---|---|---|
401 |
no token, or the token is not valid | send Authorization: Bearer $OPVS_PAT with a live token |
GET /api/v1/factory/coder-profiles/{key}¶
Returns one profile, with your workspace's changes applied. This is the call a desk makes when a build starts.
curl "https://api.opvs.ai/api/v1/factory/coder-profiles/codex.hard" \
-H "Authorization: Bearer $OPVS_PAT"
# Response 200, application/json
# {"key": "codex.hard", "version": "sha256:0fd3789f000f", "coder": "codex",
# "recommended_for": ["Risky or large cards, especially sidecar, migration, security, or billing work"],
# "model": null, "effort": "high", "fallback_model": null,
# "limits": {"max_turns": null, "max_steps": null, "wall_minutes": 180.0},
# "env": null,
# "reason": "Hard tier: account-default Codex model, highest effort, and extended wall time",
# "sources": {"model": "platform", "effort": "platform", "limit_value": "platform"},
# "platform_defaults": {"model": null, "effort": "high", "limit_value": null}}
# A key that does not exist returns a 404 error.
Errors
| Status | When | Resolution |
|---|---|---|
401 |
no token, or the token is not valid | send a live token |
404 Not found |
no profile has that key, or its coder is not available to your workspace | list the profiles and use a returned key |
GET /api/v1/factory/coder-profiles/{key}/history¶
Returns every change your workspace made to one profile, newest first. A profile nobody changed returns [].
curl "https://api.opvs.ai/api/v1/factory/coder-profiles/claude.hard/history" \
-H "Authorization: Bearer $OPVS_PAT"
# Response 200, application/json (one change shown)
# [{"id": 41, "profile_key": "claude.hard", "field": "effort",
# "old_value": null, "new_value": "high",
# "actor_user_id": 482, "actor_role": "brand_admin",
# "created_at": "2026-10-16T12:04:51.203117Z"}]
# A key that does not exist returns a 404 error.
Response: field is model, effort or limit_value. old_value and new_value are strings, or null when the setting was at the platform default. actor_role is brand_admin or platform_admin.
Errors
| Status | When | Resolution |
|---|---|---|
401 |
no token, or the token is not valid | send a live token |
404 Not found |
no profile has that key, or its coder is not available to your workspace | use a key from the profile list |
Change a profile for your workspace¶
A workspace admin can change three settings of any profile: model, effort and limit_value. Each change is recorded in the history. Everything else, including the time limit, stays as the platform sets it.
PUT /api/v1/factory/coder-profiles/{key}/override¶
Sets one or more settings and returns the profile as builds will now receive it. Settings you leave out keep their current value.
curl -X PUT "https://api.opvs.ai/api/v1/factory/coder-profiles/claude.hard/override" \
-H "Authorization: Bearer $OPVS_PAT" \
-H "Content-Type: application/json" \
-d '{"effort": "high", "limit_value": 300}'
# Response 200, application/json
# {"key": "claude.hard", "version": "sha256:814f7fca5264", "coder": "claude_code",
# "recommended_for": ["Risky or large cards, especially sidecar, migration, security, or billing work"],
# "model": "claude-opus-5-5", "effort": "high", "fallback_model": null,
# "limits": {"max_turns": 300, "max_steps": null, "wall_minutes": 180.0},
# "env": null,
# "reason": "Hard tier: strongest Claude model and effort, largest turn guard, and extended wall time",
# "sources": {"model": "platform", "effort": "brand", "limit_value": "brand"},
# "platform_defaults": {"model": "claude-opus-5-5", "effort": "max", "limit_value": 400}}
# A member who is not an admin gets a 403 error; a value the profile does not take gets a 422 error.
Request body (send at least one):
| Field | Type | Accepted values |
|---|---|---|
model |
string | claude-opus-5-5 or claude-sonnet-5. Codex and OpenHands profiles take no model |
effort |
string | low, medium or high. OpenHands profiles take no effort |
limit_value |
integer | From 1 up to the profile's platform_defaults.limit_value. Only a profile with a turn or step guard takes one |
Errors
| Status | When | Resolution |
|---|---|---|
401 |
no token, or the token is not valid | send a live token |
403 Brand admin access required |
you are not an admin of this workspace | ask an admin, or make the change in Coder settings as one |
404 Not found |
no profile has that key, or its coder is not available to your workspace | use a key from the profile list |
422 Set at least one override field |
the body is empty | send model, effort or limit_value |
422 <field> is platform-only and cannot be overridden |
the body names fallback_model, tools, permissions, credentials, env or OPVS_OH_VENV |
send only model, effort or limit_value |
422 <field> is not an editable coder profile field |
the body names any other unknown field, such as wall_minutes |
send only model, effort or limit_value |
422 Codex doesn't take a model choice in a profile |
model on a Codex profile |
leave model out; Codex uses the account's default model |
422 OpenHands profiles take their model from the build, not the profile |
model on an OpenHands profile |
pin the model on the card instead |
422 model must be one of: claude-opus-5-5, claude-sonnet-5 |
any other model name | use one of the two names |
422 OpenHands doesn't take an effort choice in a profile |
effort on an OpenHands profile |
leave effort out |
422 effort must be one of: low, medium, high |
any other effort, including max |
use low, medium or high; reset the field to return to the platform's value |
422 This profile doesn't take a limit choice |
limit_value on a profile whose platform_defaults.limit_value is null |
leave limit_value out |
422 limit_value must be from 1 up to the platform default of 400 |
limit_value is not a whole number, or is below 1 |
send an integer of 1 or more |
422 500 is above the platform limit of 400 for this profile. Lower it, or leave it at the platform default. |
limit_value is above the platform default |
send a value up to platform_defaults.limit_value |
The numbers in the last two messages are the profile's own platform default; 400 and 500 are an example.
DELETE /api/v1/factory/coder-profiles/{key}/override/{field}¶
Returns one setting to the platform's value and returns the profile as builds will now receive it. {field} is model, effort or limit_value. Resetting a setting your workspace never changed changes nothing and returns the profile.
curl -X DELETE "https://api.opvs.ai/api/v1/factory/coder-profiles/claude.hard/override/effort" \
-H "Authorization: Bearer $OPVS_PAT"
# Response 200: the profile, with "effort": "max" and sources.effort = "platform" again.
# A member who is not an admin gets a 403 error.
Errors
| Status | When | Resolution |
|---|---|---|
401 |
no token, or the token is not valid | send a live token |
403 Brand admin access required |
you are not an admin of this workspace | ask an admin |
404 Not found |
no profile has that key, or its coder is not available to your workspace | use a key from the profile list |
422 <field> is platform-only and cannot be overridden or <field> is not an editable coder profile field |
{field} is not model, effort or limit_value |
use one of the three |
422 with the same message as the PUT |
the profile has no such setting, such as model on a Codex profile |
nothing to reset; leave it |