Skip to main content
Crews are isolated agent teams, each with its own container resources, network policy, and members. A crew bundles the runtime sandbox (memory/CPU/TTL, runtime image, devcontainer/mise config), the egress posture (free vs restricted with an allowed-domain list), an autonomy policy, an optional shared persona, and cross-crew connections that gate agent-to-agent messaging. All crew endpoints require authentication and workspace context (the workspace_id query parameter).

Endpoints

MethodEndpointPurpose
GET/api/v1/crewsList crews in a workspace
POST/api/v1/crewsCreate a crew
GET/api/v1/crews/{crewId}Get a single crew
PATCH / PUT/api/v1/crews/{crewId}Update a crew
DELETE/api/v1/crews/{crewId}Soft-delete a crew
GET/api/v1/crews/{crewId}/membersList crew members
POST/api/v1/crews/{crewId}/membersAdd a crew member
PATCH/api/v1/crews/{crewId}/members/{memberId}Update a member’s per-crew role
DELETE/api/v1/crews/{crewId}/members/{memberId}Remove a crew member
GET/api/v1/crews/{crewId}/personaGet the crew persona
PUT/api/v1/crews/{crewId}/personaSet the crew persona
DELETE/api/v1/crews/{crewId}/personaReset the crew persona
GET/api/v1/crews/{crewId}/policyGet the crew autonomy policy
PUT/api/v1/crews/{crewId}/policySet the crew autonomy policy
POST/api/v1/crews/{crewId}/apply-avatar-styleApply an avatar style across agents
GET/api/v1/crew-connectionsList crew connections
POST/api/v1/crew-connectionsCreate a crew connection
DELETE/api/v1/crew-connections/{connectionId}Delete a crew connection
GET/api/v1/crews/{crewId}/filesList files in the crew workspace
GET/api/v1/crews/{crewId}/files/downloadDownload a file
PUT/api/v1/crews/{crewId}/files/saveSave/upload a file
GET/api/v1/crews/{crewId}/assignmentsList task assignments
GET/api/v1/crews/{crewId}/peer-conversationsList peer conversations
GET/api/v1/crews/{crewId}/standupGet the crew standup summary
GET/api/v1/crews/{crewId}/escalationsList crew escalations
PATCH/api/v1/escalations/{escalationId}/resolveResolve an escalation
GET/api/v1/escalations/pending-countCount pending escalations

Crew CRUD

Create, read, update, and soft-delete crews and their container/network configuration.

List Crews

GET /api/v1/crews?workspace_id={workspaceId}
Returns all crews in the workspace, ordered by creation date descending. Auth: Session or CLI token + workspace membership Response: 200 OK
[
  {
    "id": "cm1abc123",
    "workspace_id": "ws_123",
    "name": "Engineering",
    "slug": "engineering",
    "description": "Core engineering team",
    "color": "blue",
    "icon": "code",
    "avatar_style": "bottts",
    "container_memory_mb": 4096,
    "container_cpus": 2.0,
    "container_ttl_hours": 24,
    "network_mode": "restricted",
    "allowed_domains": ["api.github.com", "registry.npmjs.org"],
    "mcp_config_json": null,
    "escalation_config": null,
    "issue_prefix": "ENG",
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z",
    "_count": {
      "agents": 3,
      "members": 2
    }
  }
]

Response Fields

FieldTypeDescription
idstringCrew ID
workspace_idstringParent workspace ID
namestringDisplay name
slugstringURL-safe identifier
descriptionstring?Crew description
colorstring?Palette color ID
iconstring?Lucide icon name
avatar_stylestring?Avatar style for agents (e.g., "bottts")
container_memory_mbintegerContainer memory limit in MB
container_cpusnumberContainer CPU limit
container_ttl_hoursinteger?Container TTL in hours
network_modestring"free" or "restricted"
allowed_domainsstring[]Allowed domains (restricted mode only)
mcp_config_jsonstring?Raw MCP server config JSON
escalation_configstring?Escalation policy config JSON
runtime_imagestring?Custom runtime image (e.g., ghcr.io/org/runtime:1.0)
devcontainer_configstring?Raw devcontainer.json (max 100 KB)
mise_configstring?Raw mise config TOML (max 10 KB)
services_jsonstring?Sidecar services JSON (max 64 KB)
cached_imagestring?Locally built image tag (set by provisioner)
config_hashstring?Hash of devcontainer/mise/runtime inputs used for cached_image
max_ephemeral_agentsintegerPer-crew quota enforced by the hire flow; always present on List/Get/Update responses
issue_prefixstring?Issue identifier prefix (e.g., "ENG"); always null on List (only populated by Get)
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp
_count.agentsintegerNumber of active agents
_count.membersintegerNumber of crew members

Create Crew

POST /api/v1/crews?workspace_id={workspaceId}
Auth: Session or CLI token + OWNER, ADMIN, or MANAGER role Request Body:
FieldTypeRequiredDefaultDescription
namestringYesDisplay name (2-100 characters)
slugstringYesURL-safe identifier (2-50 chars, ^[a-z0-9][a-z0-9_-]*$)
descriptionstringNonullCrew description
colorstringNonullPalette ID (blue, emerald, violet, amber, rose, cyan, lime, fuchsia)
iconstringNonullLucide icon name (code, rocket, clipboard, etc.)
container_memory_mbintegerNo4096Container memory limit in MB
container_cpusnumberNo2.0Container CPU limit
container_ttl_hoursintegerNonullContainer time-to-live in hours
network_modestringNo"free""free" or "restricted"
allowed_domainsstring[]No[]Allowed domains when network_mode is "restricted" (ignored otherwise)
runtime_imagestringNonullCustom runtime image; existence is validated against the registry before insert
devcontainer_configstringNonullRaw devcontainer.json (max 100 KB; parsed for syntax)
mise_configstringNonullRaw mise config TOML (max 10 KB; parsed for syntax)
services_jsonstringNonullSidecar services JSON (max 64 KB; structurally validated)
{
  "name": "Engineering",
  "slug": "engineering",
  "description": "Core engineering team",
  "color": "blue",
  "icon": "code",
  "container_memory_mb": 4096,
  "container_cpus": 2.0,
  "network_mode": "restricted",
  "allowed_domains": ["api.github.com", "registry.npmjs.org"]
}
Response: 201 Created — returns the created crew object (same shape as List response item). Error Responses:
StatusCondition
400Invalid name/slug length or format, invalid network_mode, invalid domain entry, runtime_image not found in registry, oversize or invalid devcontainer_config/mise_config/services_json
402License crew limit exceeded
403Insufficient role
409Slug already taken in this workspace

Get Crew

GET /api/v1/crews/{crewId}?workspace_id={workspaceId}
Auth: Session or CLI token + workspace membership
Path ParameterDescription
crewIdCrew ID
Response: 200 OK — full crew object including _count, issue_prefix, mcp_config_json, and escalation_config.
StatusCondition
404Crew not found or does not belong to workspace

Update Crew

PATCH /api/v1/crews/{crewId}?workspace_id={workspaceId}
PUT /api/v1/crews/{crewId}?workspace_id={workspaceId}
Both PATCH and PUT are supported and behave identically (partial update — only provided fields are changed). Auth: Session or CLI token + OWNER or ADMIN role Request Body: All fields are optional.
FieldTypeDescription
namestringDisplay name (2-100 characters)
slugstringURL-safe identifier (2-50 characters)
descriptionstringCrew description
colorstringPalette ID
iconstringLucide icon name
avatar_stylestringAvatar style for agents
container_memory_mbintegerContainer memory limit in MB
container_cpusnumberContainer CPU limit
container_ttl_hoursintegerContainer TTL in hours (0 clears it to null; negative is rejected)
max_ephemeral_agentsintegerPer-crew hire-flow quota; must be between 0 and 100
network_modestring"free" or "restricted"
allowed_domainsstring[]Allowed domains (restricted mode)
mcp_config_jsonstringRaw MCP server config JSON (must contain mcpServers object)
escalation_configstringEscalation policy config JSON (thresholds 0-1, auto_approve_threshold > require_approval_below)
issue_prefixstringIssue identifier prefix (e.g., "ENG"); empty string clears
runtime_imagestringCustom runtime image (empty string clears; existence validated)
devcontainer_configstringRaw devcontainer.json (empty string clears; max 100 KB)
mise_configstringRaw mise config TOML (empty string clears; max 10 KB)
services_jsonstringSidecar services JSON (empty/whitespace clears; max 64 KB)
Response: 200 OK — updated crew object.
Changing network_mode, allowed_domains, or services_json triggers a container restart so the docker provider picks up the new policy / sidecar set on the next agent run. Changing runtime_image, devcontainer_config, or mise_config invalidates cached_image + config_hash to force a rebuild.
StatusCondition
400Invalid field values (name/slug length, slug format, network_mode, domain entry, container_ttl_hours negative, max_ephemeral_agents outside 0-100, MCP JSON missing mcpServers, escalation thresholds out of range, oversize or invalid devcontainer_config/mise_config/services_json, runtime_image not found)
403Insufficient role
404Crew not found
409Slug already taken

Delete Crew

DELETE /api/v1/crews/{crewId}?workspace_id={workspaceId}
Soft-deletes the crew (sets deleted_at) and cascade-deletes its missions, mission tasks, and crew members so identifier prefixes can be reused. The slug is rewritten to {slug}_deleted_{id} on next Create reuse.
Auth: Session or CLI token + OWNER or ADMIN role Response: 200 OK
{ "success": true }
StatusCondition
403Insufficient role
404Crew not found
WebSocket event: crew.deleted broadcast to workspace:{workspaceId}

Members

Manage the per-crew membership roster and optional per-crew role overrides that win over the workspace role for crew-scoped permissions.

List Members

GET /api/v1/crews/{crewId}/members?workspace_id={workspaceId}
Response: 200 OK — array of member objects.

Add Member

POST /api/v1/crews/{crewId}/members?workspace_id={workspaceId}
Auth: OWNER, ADMIN, or MANAGER role Request Body:
FieldTypeRequiredDescription
user_idstringYesTarget user’s ID (must already be a workspace member)
rolestringNoOptional per-crew role override — one of OWNER, ADMIN, MANAGER, MEMBER, VIEWER. Omit to inherit the workspace role.
{
  "user_id": "user_abc123",
  "role": "MANAGER"
}
Response: 201 Created — member object with nested user (id/email/full_name/avatar_url). The role override is not echoed on the Add response (it is only included by List Members).
StatusCondition
400Missing user_id, invalid role, or user is not a workspace member
404Crew not found
409User is already a member of this crew

Update Member Role

PATCH /api/v1/crews/{crewId}/members/{memberId}?workspace_id={workspaceId}
Content-Type: application/json
Elevate or clear the per-crew role override. The crew-member row carries an optional role column that, when set, wins over the workspace-level role for permissions scoped to this crew. Clearing it (empty or omitted role) drops the member back to inheriting their workspace role. Auth: OWNER or ADMIN role on the workspace. A per-crew ADMIN is not allowed to reshape membership — that could ladder a MEMBER straight to OWNER and bypass the workspace gate. Request Body:
FieldTypeRequiredDescription
rolestringNoOne of OWNER, ADMIN, MANAGER, MEMBER, VIEWER. Omit or pass "" to clear the override (member inherits workspace role).
{ "role": "ADMIN" }
Response: 200 OK — a status envelope echoing the applied role (an empty role means the override was cleared):
{ "status": "updated", "role": "ADMIN" }
StatusCondition
400role is not in the enum set
403Caller is not workspace OWNER / ADMIN
404Crew or member not found

Remove Member

DELETE /api/v1/crews/{crewId}/members/{memberId}?workspace_id={workspaceId}
Auth: OWNER or ADMIN role Response: 200 OK
{ "success": true }
StatusCondition
404Crew or member not found

Persona

The crew layer of the persona stack — PERSONA.md markdown that the orchestrator injects into every agent in the crew, used as the default when an agent has no agent-layer file. Resolution is layered: the agent layer wins if present; otherwise crew default; otherwise the synthesised “You are the …” stub. See the Agent Persona section in the agents reference for the cross-layer model and cap_bytes (1500). All three endpoints are operator-only; there is no crew-flavoured suggest analog (agents propose into their own layer, not the crew default).

Get Crew Persona

GET /api/v1/crews/{crewId}/persona
Response: 200 OK
{
  "crew_id": "crew-uuid",
  "layer": "crew",
  "content": "# Default persona for this crew...\n",
  "bytes": 412,
  "cap_bytes": 1500
}
Unlike GET /agents/{id}/persona, this endpoint does not report a from_default flag — the crew layer either has a file or it doesn’t. When empty, content is "" and clients fall through to the per-agent synthesised default.

Set Crew Persona

PUT /api/v1/crews/{crewId}/persona
Content-Type: application/json
Writes the crew layer file. Records a row in memory_versions keyed to the crew-layer path so the history endpoint can replay the chain. Request:
{ "content": "# Default persona for this crew\n\n..." }
Response: 200 OK{ "layer": "crew", "bytes": N, "updated": "<rfc3339>" }
StatusCondition
413content exceeds cap_bytes (1500)
404Crew not found
500Storage write / fsync failure

Reset Crew Persona

DELETE /api/v1/crews/{crewId}/persona
Removes the crew layer file. Subsequent reads return empty content and agents fall back to their per-role synthesised default. Response: 204 No Content

Policy

Each crew carries an autonomy posture that gates every HITL-relevant decision the orchestrator makes — memory writes, skill creation, behavior-monitor escalations, persona suggestions, ephemeral spawns. The dial is read by every PR-B / PR-C subsystem via the shared policy.Resolver. The CLI counterpart is crewship policy get/set.
FieldValuesMeaning
autonomy_levelstrict / guided / trusted / fullHow much an agent can do without operator approval. strict queues everything; full auto-applies most decisions.
behavior_modewarn / blockWhat the behavior monitor does on a flagged action — warn lets it through with a journal entry, block rejects.

Get Crew Policy

GET /api/v1/crews/{crewId}/policy
Response: 200 OK
{
  "crew_id": "crew-uuid",
  "autonomy_level": "guided",
  "behavior_mode": "warn",
  "set_by_user_id": "user-uuid",
  "set_at": "2026-05-26T14:22:10Z",
  "reason": "Default for newly-onboarded crews"
}
set_by_user_id / set_at / reason are omitted on crews whose policy still matches the seed defaults (no operator has ever flipped it). On crews that have been touched at least once, the audit triple records who, when, why.

Set Crew Policy

PUT /api/v1/crews/{crewId}/policy
Content-Type: application/json
Replaces the policy. Records the audit triple (set_by_user_id, set_at, reason) atomically with the value change and invalidates the resolver cache so the next decision sees the new state. Auth: Session or CLI token + workspace membership (no additional role gate) Request:
{
  "autonomy_level": "trusted",
  "behavior_mode": "block",
  "reason": "Crew has cleared 30 days of approvals without an override"
}
FieldRequiredNotes
autonomy_levelyesMust be one of the four enum values; other strings return 400.
behavior_modeyeswarn or block. Missing field returns 400 (no silent default).
reasonconditionalRequired only when autonomy_level=full — non-empty, persisted on the audit triple. Optional for strict / guided / trusted.
Response: 200 OK — same shape as GET, reflecting the new state and the freshly-recorded audit triple.
StatusCondition
400Invalid enum value, the forbidden full + block combination, or reason missing when autonomy_level=full
404Crew not found

Avatar

Bulk-apply an avatar style across a crew’s agents, or clear per-agent overrides.

Apply Avatar Style

POST /api/v1/crews/{crewId}/apply-avatar-style?workspace_id={workspaceId}
Applies an avatar_style to all non-deleted agents in the crew, or clears per-agent overrides. Auth: OWNER or ADMIN role Request Body:
FieldTypeRequiredDescription
avatar_stylestringConditionalStyle to apply (required unless reset_overrides is true)
reset_overridesbooleanNoWhen true, clears avatar_style on every agent (ignores avatar_style)
Response: 200 OK
{ "updated": 3, "style": "bottts" }
When reset_overrides is true, the response is { "updated": N, "reset": true }.
StatusCondition
400avatar_style missing and reset_overrides not set
404Crew not found

Connections

Crew connections define which crews can communicate with each other for cross-crew task assignment and messaging.

List Connections

GET /api/v1/crew-connections?workspace_id={workspaceId}
Response: 200 OK — array of connection objects:
[
  {
    "id": "cc_abc",
    "workspace_id": "ws_123",
    "from_crew_id": "crew_abc",
    "from_crew_name": "Engineering",
    "from_crew_slug": "engineering",
    "to_crew_id": "crew_xyz",
    "to_crew_name": "Design",
    "to_crew_slug": "design",
    "direction": "bidirectional",
    "status": "active",
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z"
  }
]

Create Connection

POST /api/v1/crew-connections?workspace_id={workspaceId}
Auth: OWNER, ADMIN, or MANAGER role Request Body:
FieldTypeRequiredDefaultDescription
from_crew_idstringYesSource crew ID
to_crew_idstringYesTarget crew ID (must differ from from_crew_id)
directionstringNo"bidirectional""bidirectional" or "unidirectional"
{
  "from_crew_id": "crew_abc",
  "to_crew_id": "crew_xyz",
  "direction": "bidirectional"
}
Response: 201 Created
{ "id": "cc_abc" }
StatusCondition
400Missing IDs, same source/target, or invalid direction
404One or both crews not found in this workspace
409Connection already exists (or other UNIQUE/constraint violation)

Delete Connection

DELETE /api/v1/crew-connections/{connectionId}?workspace_id={workspaceId}
Auth: OWNER, ADMIN, or MANAGER role Response: 204 No Content
StatusCondition
404Connection not found

Crew Files (Proxy)

File operations are proxied through the crewshipd sidecar to the crew’s container filesystem.
EndpointMethodDescription
GET /api/v1/crews/{crewId}/filesGETList files in crew workspace
GET /api/v1/crews/{crewId}/files/download?path=...GETDownload a file
PUT /api/v1/crews/{crewId}/files/savePUTSave/upload a file

Crew Assignments

GET /api/v1/crews/{crewId}/assignments?workspace_id={workspaceId}
List task assignments for a crew. Response: 200 OK — array of assignment objects.

Crew Peer Conversations

GET /api/v1/crews/{crewId}/peer-conversations?workspace_id={workspaceId}
List peer-to-peer conversations between agents in a crew.

Crew Standup

GET /api/v1/crews/{crewId}/standup?workspace_id={workspaceId}
Get standup summary for a crew.

Crew Escalations

List Escalations

GET /api/v1/crews/{crewId}/escalations?workspace_id={workspaceId}

Resolve Escalation

PATCH /api/v1/escalations/{escalationId}/resolve?workspace_id={workspaceId}

Pending Escalation Count

GET /api/v1/escalations/pending-count?workspace_id={workspaceId}
Returns count of pending escalations across the workspace.