Skip to main content

crewship hire / crewship rehire

hire provisions a short-lived agent from a template into an existing crew, gives it a TTL, and writes a hire_reason audit row. The agent runs like any permanent crew member until its TTL elapses, at which point a background sweeper ghosts it (sets expired_at, keeps the row + memory files for audit + rehire). rehire resets the TTL on a ghost (or a still-live ephemeral whose operator wants to extend before it ghosts). Same row, same id, same memory files — the agent picks up exactly where it left off, with full continuity. For the lifecycle walkthrough and operator workflows see Ephemeral agents. This page is the canonical CLI reference: flags, error codes, exit semantics.

Per-autonomy-level response

Both commands route through the per-crew autonomy_level policy gate (PR-B F2). The crew’s setting determines what happens to the hire: See Autonomy + self-learning for the matrix and where to set the autonomy level.

crewship hire

Flags

Response

(Shape mirrors hireResponse in internal/api/agents_hire.go. inbox_item_id is added only when a guided hire creates a blocking inbox waitpoint.)

Auto-assigned credentials

On a successful hire, Crewship automatically assigns the available workspace Anthropic credential (type API_KEY or AI_CLI_TOKEN, ordered by creation date) to the new ephemeral agent, so it can authenticate on first run. This is best-effort and never blocks the hire:
  • No Anthropic credential in the workspace → the hire still succeeds and the agent journals credential.auto_assign_empty; the agent will fail to chat until you add one and rehire (or assign manually).
  • You can always override afterwards with crewship credential assign <agent> <credential>.

Exit codes

The CLI exits 0 on success (a 201 live hire or a 202 pending-review hire) and 1 on any failure — the error text printed to stderr names the cause. Common failure causes and the message they carry:

Waiting for a guided approval (--wait)

On a guided-autonomy crew the hire lands as 202 PENDING_REVIEW and needs an operator to run crewship hire approve <agent> before the agent can chat. --wait polls GET /api/v1/agents/{id} (the same route crewship agent get uses) every --wait-interval until the status flips away from PENDING_REVIEW (approved) or the hire ghosts — its TTL elapses before anyone approves it, which the CLI also treats as a resolved (failing) outcome so --wait doesn’t hang forever on an abandoned approval. There is no explicit “denied” state today; a rejected hire is left to expire.

--ttl clamping

The clamp is entirely server-side and silent — the CLI forwards ttl_minutes as-is and does not pre-validate or warn. An out-of-range value (e.g. --ttl 10) still produces a successful hire; the server clamps it into [30, 1440] and the effective value comes back in expires_at (now() + clamped_ttl). Read expires_at on the response to confirm the TTL that actually landed.

crewship rehire

Flags

Effect on the agent row

Quota interaction

  • Rehiring a ghost does NOT count against crews.max_ephemeral_agents — the ghost row already exists; rehire just toggles expired_at to NULL.
  • Rehiring a still-live ephemeral is also free for the same reason (same row).
  • Hiring a fresh ephemeral when the quota is full returns 429 — at that point the operator either raises the quota or rehires a ghost instead of hiring fresh.

Exit codes

Same as hire: 0 on success, 1 on any failure with the cause in the stderr message. Rehire-specific failures:
  • The agent isn’t ephemeral (you can’t rehire a permanent agent — the lifecycle doesn’t apply).
  • The policy rejects rehire on a strict crew (matches the hire rejection — re-promoting a ghost still needs policy approval).

crewship hire approve

Approve a guided-autonomy hire that is parked in PENDING_REVIEW, flipping it to IDLE so it can serve work. This is the terminal counterpart to the UI inbox “Approve” button.
Takes the ephemeral agent’s slug or ID (printed by crewship hire and shown in crewship agent list) as its single positional argument, and calls POST /api/v1/agents/{id}/approve-hire. A 409 comes back if the agent isn’t in PENDING_REVIEW (already approved, or hired under a non-guided autonomy level).

Listing ephemeral agents

crewship agent list shows every agent in the workspace, ephemerals included. Scope to one crew with --crew:
Ephemeral agents appear alongside permanent ones; live vs. ghost state is read off each agent’s expired_at / expires_at fields. Use --format json and jq if you want to filter to just the live or ghost rows:

TTL mid-mission grace

The sweeper that ghosts expired ephemerals (internal/ephemeral/expiry.go, 5-minute ticker) skips agents with status='RUNNING'. A mission in flight finishes even if its TTL elapsed mid-call; the agent ghosts on the next sweep after it idles back to IDLE. This avoids the worst-case “agent was mid-tool-call when ghost flag fired” scenario. The trade-off is that a long-running ephemeral can outlive its TTL by up to one sweep interval (5 min). For stricter timing, provision a permanent agent and crewship agent delete <id> explicitly.

LEAD-driven hire from inside a container

A LEAD-mode agent in active orchestration can hire a sub-agent via the sidecar /spawn endpoint without an operator running crewship hire. The sidecar proxies the request to POST /api/v1/internal/agents/hire and injects MANAGER role into the request context; the policy gate still fires (a strict crew rejects LEAD-driven hires too — autonomy_level is the security boundary, not RBAC). See Ephemeral agents — LEAD-driven hire for the full pattern, including the AgentBrief primitive for handing curated context to the sub-agent.