Warp Platform API
API for creating, managing, and querying factory and cloud agent runs.
Send work to factories, start standalone agents, list runs, and retrieve
detailed run information.
Base URL: https://app.warp.dev/api/v1
Authentication: Bearer token (Warp API key). Obtain from account settings. Pass as Authorization: Bearer YOUR_API_KEY.
Full machine-readable spec: openapi.json
GET /networking/policies
List built-in network policies
Return Warp-managed network policies grouped by name, with every published
version and its included allowed hosts. Use a name and version in networkPolicy.extends.
Policies do not include the platform's system-required egress rules.
GET /networking/egress-ranges
List Warp-hosted agent egress ranges
Return the canonical IP network ranges used by outbound requests from
Warp-hosted agents.
GET /factory
List factories
List factories accessible to the authenticated principal, restricted
to the request's active team when one is set. An optional team_uid
query parameter overrides the active team and restricts results to a
single team, and an optional search query parameter filters by a
case-insensitive substring match on the factory name or alias.
- ()
- team_uid (query): Optional team UID to filter factories by ownership. Takes
precedence over the X-Warp-Team-Uid header.
- search (query): Case-insensitive substring search over the factory name and
alias.
- limit (query): Maximum number of factories to return (default 50, max 100).
- cursor (query): Opaque cursor returned by a previous list response.
GET /factory/{uid}
Get a factory
Get a factory by its UID.
- uid (path, required): The public UID of the factory.
GET /factory-inbox
List Factory inbox notifications
List unresolved notifications across factories authorized for the
authenticated principal and active team. The default `mine` scope
preserves the personal Inbox and requires user credentials. The
`team` scope lists notifications assigned to any recipient and
can be used by user or agent credentials. Personal read state
(`is_read`) is included only in `mine` scope and omitted in `team`
scope, including when filtering by recipient.
- ()
- scope (query): `mine` returns notifications assigned to the authenticated user
and is the default. `team` returns notifications across live
recipients in the authorized Factory and team scope.
- factory_uid (query): Exact Factory UID filter, intersected with authorized factories.
- recipient_uid (query): Exact public user UID filter within the authorized Factory and
team scope. In `mine` scope this can only match the authenticated
user.
- limit (query): Maximum number of items to return. Defaults to 50.
- cursor (query): Opaque cursor from page_info.next_cursor.
POST /factory-inbox/notifications/read
Mark inbox notifications as read
Mark a batch of notifications as read for the authenticated user after
checking access to each factory. The caller must be a recipient of
each existing notification, and the notification must remain active;
otherwise its outcome is unsuccessful. Missing notifications are
successful no-ops. Outcomes are returned in request order.
POST /factory-inbox/notifications/unread
Mark inbox notifications as unread
Mark a batch of notifications as unread for the authenticated user
after checking access to each factory. The caller must be a recipient
of each existing notification, and the notification must remain active;
otherwise its outcome is unsuccessful. Missing notifications are
successful no-ops. Outcomes are returned in request order.
POST /factory/{uid}/tasks
Create a factory task
Create a task in a factory, bound to an existing agent conversation.
title and conversation_id are required. The stage defaults to TRIAGE. The
conversation's most recent run must be owned by the factory's team,
and a conversation may be bound to at most one live task across all
factories.
- uid (path, required): The public UID of the factory.
GET /factory/{uid}/tasks
List factory tasks
List the factory's tasks with optional filtering and search. List
responses are lean by default; set full_list=true to include
canonical ticket metadata and derived outputs for the returned page.
- uid (path, required): The public UID of the factory.
- stage (query): Filter by task stage. Can be specified multiple times to match any
of the given stages.
- created_by (query): Filter to tasks whose seed run was started by any of these
teammates, each given as their email address. Can be specified
multiple times to match any of the given teammates.
- q (query): Case-insensitive substring search over the task title.
- created_after (query): Filter to tasks created after this timestamp (RFC3339 format).
- created_before (query): Filter to tasks created before this timestamp (RFC3339 format).
- updated_after (query): Filter to tasks updated after this timestamp (RFC3339 format).
- sort_by (query): Sort field for results.
- sort_order (query): Sort direction.
- limit (query): Maximum number of tasks to return (default 50, max 100).
- cursor (query): Opaque cursor returned by a previous list response.
Valid only for the sort_by/sort_order it was issued under; omit
to restart the listing.
- full_list (query): Include canonical ticket_source and ticket_id metadata from each
task's bound run, plus its derived outputs. Defaults to false.
- include_current_run (query): Include each task's current top-level run, resolved in one batch
for the returned page. Defaults to false.
POST /factory/{uid}/runs
Dispatch a run to a factory
Dispatch a run to a factory, using prompt as the run's
prompt and an optional title, ticket_ref, and ticket_url. Returns
the created run; its factory task is created asynchronously and can
be resolved afterwards with GET /factory/{uid}/task-by-run.
- uid (path, required): The public UID of the factory.
GET /factory/{uid}/branches/{branch_uid}
Observe a tracked Factory Branch
Requires Factory view and matching parent Factory/team ownership.
Does not create tracking, request repair, or mutate projections.
Retired tracking remains DELETED until normal permadeletion.
Unverifiable source freshness is UNKNOWN. Requires factory_branches.
- uid (path, required)
- branch_uid (path, required)
DELETE /factory/{uid}/branches/{branch_uid}
Stop tracking a Factory Branch
Requires Factory view plus source.apply. Retirement blocks future
execution boundaries without deleting the Git head, cancelling
already-loaded work, or deleting production resources.
Repeated authorized deletion, including after purge, returns 204.
Requires factory_branches.
- uid (path, required)
- branch_uid (path, required)
POST /factory/{uid}/branches/{branch_uid}/apply
Apply a Factory Branch sync
Requires Factory view and source.apply. Queues a Temporal
reconciliation to the current registered head and returns before
synchronization completes. Publication requires complete projection
authorization. Duplicate requests converge. Read branch status to
observe completion or source errors.
Does not accept a target SHA or repository, create tracking, revive
retired identity, or replace settings on existing runs.
Requires factory_branches.
- uid (path, required)
- branch_uid (path, required)
GET /factory/{uid}/tasks/{task_uid}
Get a factory task
Get a task with its derived outputs, newest-first.
- uid (path, required): The public UID of the factory.
- task_uid (path, required): The public UID of the task.
PATCH /factory/{uid}/tasks/{task_uid}
Update a factory task
Partially update a task's title, description, and/or stage. Last
write wins. Stage writes are unrestricted: any stage-to-stage
transition is allowed, including moving backwards or to completion.
- uid (path, required): The public UID of the factory.
- task_uid (path, required): The public UID of the task.
DELETE /factory/{uid}/tasks/{task_uid}
Delete a factory task
Soft-delete a task. The task disappears from list and get responses
immediately, and its conversation may be bound to a new task.
Deleting a task never deletes artifacts or the conversation.
- uid (path, required): The public UID of the factory.
- task_uid (path, required): The public UID of the task.
POST /factory/{uid}/tasks/{task_uid}/cancel
Stop a factory task
Cancel the task's current top-level run and move the task to
CANCELLED. Every non-terminal descendant of the root run is
cancelled as well.
- uid (path, required): The public UID of the factory.
- task_uid (path, required): The public UID of the task.
GET /factory/{uid}/task-by-conversation
Get a factory task by conversation
Get the factory task bound to an agent conversation. Conversation bindings are
unique across factories, but the lookup is factory-scoped: a task
owned by a different factory is 404.
- uid (path, required): The public UID of the factory.
- conversation_id (query, required): The agent conversation ID the task is bound to.
GET /factory/{uid}/task-by-run
Get a factory task by run
Get the factory task that owns a run: the task bound to the conversation
of the run's root ancestor. The lookup is factory-scoped: a task owned by
a different factory is 404.
- uid (path, required): The public UID of the factory.
- run_id (query, required): Any run ID in the task's run tree.
GET /factory/{uid}/metrics
Get factory metrics
Aggregate productivity metrics for a factory over a UTC date range:
run count, distinct PR count (from PR artifacts, deduped by URL at
first appearance), autonomy, impact, and PR latency. Cost metrics
live under /factory/{uid}/costs. Pass group_by_period to additionally
receive per-period series aligned to period_list.
- uid (path, required): The public UID of the factory.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- group_by_period (query): Optional binning granularity; when omitted, the response
contains aggregates only. Binned requests are capped at 365
periods.
GET /factory/{uid}/costs/per-pr
Get factory cost per PR
Mean per-PR attributed cost for a factory over a UTC date range,
with per-component dollar breakdowns. Previously served as
cost_per_pr on GET /factory/{uid}/metrics. Pass group_by_period to
additionally receive per-period series aligned to period_list.
- uid (path, required): The public UID of the factory.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- group_by_period (query): Optional binning granularity; when omitted, the response
contains aggregates only. Binned requests are capped at 365
periods.
GET /factory/{uid}/costs/breakdown
Get factory spend grouped by a dimension
The factory's spend over a UTC date range, grouped by source, user,
agent, or model. groups lists every entity with nonzero spend in the
range (uncapped); UNKNOWN sorts last. Pass group_by_period to
additionally receive per-period series aligned to period_list.
- uid (path, required): The public UID of the factory.
- group_by (query, required): The dimension to group spend by.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- group_by_period (query): Optional binning granularity; when omitted, the response
contains aggregates only. Binned requests are capped at 365
periods.
GET /factory/{uid}/costs/per-pr/top
Get the factory's most expensive PRs
The costliest PRs first seen in the range, most expensive first, with
per-component cost breakdowns, attribution from each PR's earliest
live root run, and PR detail collected from code-forge webhooks.
PRs that predate webhook PR-fact collection still appear, with null
detail fields.
- uid (path, required): The public UID of the factory.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- limit (query): Maximum PRs to return. Defaults to 20; at most 50.
GET /factory/{uid}/pull-requests
List the factory's pull requests
One record per pull request produced by the factory's runs, newest
opened first. A PR someone opened in one of the factory's
repositories without a factory run (by hand, for example) is not
listed. Each record carries the PR's identity, state and times,
size, human interactions, the runs that produced it, and its cycle
time. Pages are keyset-paginated: pass page_info.next_cursor back as
cursor to continue. Pass updated_after to sync incrementally.
- uid (path, required): The public UID of the factory.
- limit (query): Records per page. Defaults to 50; at most 500.
- cursor (query): Opaque cursor from a previous page's page_info.next_cursor.
- repo (query): Only PRs in this repository, as owner/repo (case-insensitive).
- state (query): Only PRs in these states. Can be specified multiple times to match any of the given states.
- opened_after (query): Only PRs opened after this RFC3339 time (exclusive).
- opened_before (query): Only PRs opened before this RFC3339 time (exclusive).
- merged_after (query): Only PRs merged after this RFC3339 time (exclusive).
- merged_before (query): Only PRs merged before this RFC3339 time (exclusive).
- updated_after (query): Only PRs whose updated_at is after this RFC3339 time
(exclusive). updated_at tracks the PR on the code host; fields
derived from the factory's runs (runs, kickoff_at,
human_interactions.follow_up_message, and the kickoff-based
cycle_time stages) can change without moving it.
GET /factory/{uid}/metrics/run-breakdown
Get the factory's run counts grouped by a dimension
The factory's run counts over a UTC date range, grouped by one
dimension. Pass group_by_period to additionally receive per-period
series aligned to period_list.
- uid (path, required): The public UID of the factory.
- group_by (query, required): The dimension to group run counts by.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- group_by_period (query): Optional binning granularity; when omitted, the response
contains aggregates only. Binned requests are capped at 365
periods.
GET /factory/{uid}/costs/per-pr/by-size
Get the factory's PR cost distribution grouped by PR size
The mean per-PR attributed cost of the factory's PRs first seen in
a UTC date range, grouped by PR size. Pass group_by_period to
additionally receive per-period mean series aligned to
period_list.
- uid (path, required): The public UID of the factory.
- start_date (query): Inclusive RFC3339 range start (UTC). Defaults to end_date minus 30 days.
- end_date (query): Exclusive RFC3339 range end (UTC). Defaults to now.
- group_by_period (query): Optional binning granularity; when omitted, the response
contains aggregates only. Binned requests are capped at 365
periods.
GET /agent
List available agent skills
Retrieve a list of available agents (skills) that can be used to run tasks.
Agents are discovered from environments or a specific repository.
- ()
- repo (query): Optional repository specification to list agents from (format: "owner/repo").
If not provided, lists agents from all accessible environments.
- refresh (query): When true, clears the agent list cache before fetching.
Use this to force a refresh of the available agents.
- sort_by (query): Sort order for the returned agents.
- "name": Sort alphabetically by name (default)
- "last_run": Sort by most recently used
- include_malformed_skills (query): When true, includes skills whose SKILL.md file exists but is
malformed. These variants will have a non-empty `error` field
describing the parse failure. Defaults to false.
GET /agent/connected-self-hosted-workers
List connected self-hosted workers
Retrieve currently connected self-hosted workers for the authenticated principal's team.
Worker presence is derived from worker websocket heartbeats and may be briefly stale.
GET /agent/runs/{runId}/transcript
Get run transcript
Retrieve the raw conversation transcript for an agent run.
Returns a 302 redirect to a time-limited download URL for the transcript.
- runId (path, required): The unique identifier of the run
GET /agent/runs/{runId}/harness-usage
Get raw third-party harness usage
Return the latest cumulative raw usage snapshot retained for a
Claude Code or Codex run. Missing metrics are represented as an
unavailable result rather than zero. Access uses the same run view
authorization as transcript reads.
POST /agent/run
Run an agent task
Spawn a cloud agent with a prompt and optional configuration.
The agent will be queued for execution and assigned a unique run ID.
POST /agent/runs
Run a cloud agent
Spawn a cloud agent with a prompt and optional configuration.
The agent will be queued for execution and assigned a unique run ID.
GET /agent/runs
List agent runs
Retrieve a paginated list of agent runs with optional filtering.
Results default to `sort_by=updated_at` and `sort_order=desc`.
- ()
- limit (query): Maximum number of runs to return
- cursor (query): Pagination cursor from previous response
- sort_by (query): Sort field for results.
- `updated_at`: Sort by last update timestamp (default)
- `created_at`: Sort by creation timestamp
- `title`: Sort alphabetically by run title
- `agent`: Sort alphabetically by skill. Runs without a skill are grouped last.
- sort_order (query): Sort direction
- state (query): Filter by run state. Can be specified multiple times to match any of the given states.
- task_status (query): Filter by high-level task status. Can be specified multiple times to match any value.
`running` matches when the root or any descendant is queued, pending, claimed, or in progress.
`failed`, `blocked`, `cancelled`, and `complete` match the root state only.
- name (query): Filter by agent config name
- model_id (query): Filter by model ID
- creator (query): Filter by creator UID (user or service account)
- executor (query): Filter by the user or agent that executed the run. This will often be the
same as the creator, but not always: users may delegate tasks to agents.
- source (query): Filter by run source type. Can be specified multiple times to match any of the given sources.
- execution_location (query): Filter by where the run executed
- created_after (query): Filter runs created after this timestamp (RFC3339 format)
- created_before (query): Filter runs created before this timestamp (RFC3339 format)
- updated_after (query): Filter runs updated after this timestamp (RFC3339 format)
- environment_id (query): Filter runs by environment ID. Passing the literal value
`empty-environment` matches runs with no environment configured,
rather than omitting the parameter, which applies no environment
filter at all. `empty-environment` can never collide with a real
environment ID: every environment ID is exactly 22 characters
drawn from `[A-Za-z0-9]`, while this sentinel contains a hyphen
and is a different length.
- skill (query): Filter runs by skill spec (e.g., "owner/repo:path/to/SKILL.md").
Alias for skill_spec.
- skill_spec (query): Filter runs by skill spec (e.g., "owner/repo:path/to/SKILL.md")
- schedule_id (query): Filter runs by the scheduled agent ID that created them
- factory_uid (query): Filter runs by one or more factories. Repeating this parameter
matches runs executed by an agent from any selected factory. A UID
outside the caller's accessible factories matches nothing.
- ancestor_run_id (query): Filter runs by ancestor run ID. The referenced run must exist and be accessible to the caller.
- metadata (query): Filter by exact metadata key/value pairs using object notation
(e.g. `metadata[ticket_id]=ACME-238`), combining multiple pairs
with AND semantics, up to 5 per request. Returns
`feature_not_available` when metadata filtering is not enabled.
- artifact_type (query): Filter runs by artifact type
- q (query): Search by full run ID or run URL, or fuzzy match across run title, prompt, and skill_spec
GET /agent/run-by-external-reference
Find the run that produced a given external reference URL
Reverse-looks up the agent run that created an external reference
with the given URL. The URL is matched against the canonical locator stored
when the artifact was reported. Returns 404 when no matching run
exists or when the caller lacks access.
- url (query, required): The canonical URL of the external reference artifact to look up.
POST /agent/runs/batch-get
Get multiple runs by ID
Retrieve run details for 1–100 run IDs. Returns a top-level array in
input order, preserving duplicates with one result per input occurrence.
Each result contains the requested run_id and exactly one of `run`, the
same run object returned by getRun, or `error`, the standard API error
getRun would return for that ID. Authorization and per-run errors
follow getRun semantics. Completed batches return HTTP 200 even when
every result is an error; shared infrastructure failures fail the
request with HTTP 500.
GET /agent/runs/{runId}
Get run details
Retrieve detailed information about a specific agent run,
including the full prompt, session link, and resolved configuration.
- runId (path, required): The unique identifier of the run
GET /agent/runs/{runId}/timeline
Get run timeline
Retrieve chronological setup and lifecycle timeline events for an agent run.
- runId (path, required): The unique identifier of the run
GET /agent/runs/{runId}/diagnostics
Get run diagnostics
Retrieve diagnostics recorded for an agent run.
- runId (path, required): The unique identifier of the run
GET /agent/runs/{runId}/conversation
Get normalized run conversation
Retrieve a run's conversation as a normalized sequence of messages and
nested steps. The response groups text, tool activity, and event content
into structured blocks.
- runId (path, required): The unique identifier of the run
POST /agent/runs/{runId}/cancel
Cancel a run
Cancel an agent run that is currently queued or in progress; once
cancelled, the run transitions to a cancelled state. Not all runs can
be cancelled: a run already in a terminal state, in PENDING, or of an
unsupported type (e.g. local, GitHub Action) is rejected
instead — see the error responses below for each case.
- runId (path, required): The unique identifier of the run to cancel
POST /agent/runs/{runId}/followups
Submit a follow-up message for a run
Send a follow-up message to an existing run. The server transparently
routes the message based on the current state of the run (still
queued, actively running, or ended) and will resume the agent in a new
sandbox if necessary. A 200 response means the follow-up
was accepted; updated run state can be observed via
`GET /agent/runs/{runId}`.
A run that failed during environment setup keeps its retained session
reachable for a bounded debug window. A follow-up sent to an eligible
run in that window is delivered into the retained session to start or
continue a debug agent, without reopening the run: it stays in its
failed state, with its original failure message and error code
unchanged.
- runId (path, required): The unique identifier of the run
POST /agent/runs/{runId}/interrupt
Interrupt the turn currently running on a run
Cancel the request the agent is currently working on without ending
the run or tearing down its sandbox. The run stays in progress and
accepts follow-ups afterwards. Only live runs on the Warp harness
can be interrupted; use `POST /agent/runs/{runId}/cancel` to end a
run outright. A 202 means the platform accepted the cancel; the agent
applies it asynchronously.
- runId (path, required): The unique identifier of the run
GET /agent/runs/{runId}/handoff/attachments
List handoff snapshot attachments for a run
Return fresh presigned download URLs for handoff snapshot files uploaded
by the latest ended execution of this run. An empty list is returned
when no ended execution exists or no snapshot files were uploaded.
This endpoint is useful for third-party harnesses that want to download
the snapshot files produced by a previous execution before starting a
handoff execution themselves.
- runId (path, required): The unique identifier of the run
POST /agent/conversations/{conversation_id}/followups
Submit a follow-up message to the run behind a conversation
The same operation as `POST /agent/runs/{runId}/followups`, targeted
by the conversation the run is serving rather than the run itself.
`attachments` must name ids prepared through
`POST /agent/conversations/{conversation_id}/attachments/prepare` (or
the run-keyed prepare) for the run that is newest at that time. If a
new run appears for the conversation between prepare and follow-up,
the follow-up resolves to the new run and answers 422
`unknown_attachment`; prepare again. A handoff is a new execution of
the same run and does not have this problem.
`mode` only takes effect when the follow-up is queued ahead of the run
starting or starts a new execution; a follow-up injected into a live
session runs in the session's current mode.
- conversation_id (path, required): The UUID of the Warp-native conversation
POST /agent/conversations/{conversation_id}/interrupt
Interrupt the turn running on the run behind a conversation
The same operation as `POST /agent/runs/{runId}/interrupt`, addressed
by the conversation the run is serving. The run is picked with the
same policy as the conversation follow-up route, and the caller must
be able to view the conversation and the resolved run.
- conversation_id (path, required): The UUID of the Warp-native conversation
GET /agent/conversations/{conversation_id}
Get normalized conversation
Retrieve a conversation directly by conversation ID in Warp's
normalized task/message format.
- conversation_id (path, required): The unique identifier of the conversation
GET /agent/conversations/{conversation_id}/transcript
Get conversation transcript
Retrieve the raw conversation transcript for a conversation.
Returns a 302 redirect to a time-limited download URL for the transcript.
Supported for third-party harness conversations (Claude Code, Codex, Gemini).
- conversation_id (path, required): The unique identifier of the conversation
GET /agent/conversations/{conversation_id}/screenshots/{screenshot_uid}/download
Download a stored computer-use screenshot
Download a computer-use screenshot that was offloaded
from the conversation's task history into object storage. The
response is a redirect to a short-lived signed URL, so clients must
follow redirects to receive the image. Requires view access to the
conversation named in the path; a fork's history may reference
screenshots stored under its source conversation's ID.
- conversation_id (path, required): The unique identifier of the conversation that owns the screenshot
- screenshot_uid (path, required): The unique identifier of the stored screenshot
POST /agent/schedules
Create a scheduled agent
Create a new scheduled agent that runs on a cron schedule.
The agent will be triggered automatically based on the cron expression.
GET /agent/schedules
List scheduled agents
Retrieve all scheduled agents accessible to the authenticated user.
Results are sorted alphabetically by name.
GET /agent/schedules/{scheduleId}
Get scheduled agent details
Retrieve detailed information about a specific scheduled agent,
including its configuration, history, and next scheduled run time.
- scheduleId (path, required): The unique identifier of the scheduled agent
PUT /agent/schedules/{scheduleId}
Update a scheduled agent
Update an existing scheduled agent's configuration.
All fields except agent_config are required.
- scheduleId (path, required): The unique identifier of the scheduled agent
DELETE /agent/schedules/{scheduleId}
Delete a scheduled agent
Delete a scheduled agent. This will stop all future scheduled runs.
- scheduleId (path, required): The unique identifier of the scheduled agent
POST /agent/schedules/{scheduleId}/pause
Pause a scheduled agent
Pause a scheduled agent. The agent will not run until resumed.
- scheduleId (path, required): The unique identifier of the scheduled agent
POST /agent/schedules/{scheduleId}/resume
Resume a scheduled agent
Resume a paused scheduled agent. The agent will start running
according to its cron schedule.
- scheduleId (path, required): The unique identifier of the scheduled agent
GET /agent/environments
List environments
Retrieve cloud environments accessible to the authenticated principal.
Returns environments the caller owns, has been granted guest access to,
or has accessed via link sharing.
- ()
- sort_by (query): Sort order for the returned environments.
- `name`: alphabetical by environment name
- `last_updated`: most recently updated first (default)
GET /agent/models
List available models
Retrieve the list of LLM models available to the authenticated user for
agent runs. The response includes which model is the default, as well as
per-model metadata such as provider, cost, and whether the model is
currently disabled (and why).
GET /agent/artifacts/{artifactUid}
Get artifact details
Retrieve an artifact by its UUID: a time-limited signed download URL
for downloadable file-like artifacts, or the current plan content
inline for plan artifacts. Public artifacts can be read without
authentication; private artifacts require the caller to be
authenticated and authorized.
- artifactUid (path, required): The unique identifier (UUID) of the artifact
GET /agent/artifacts/{artifactUid}/download
Download an artifact
Redirect to a temporary signed download URL for a downloadable artifact.
Public artifacts can be downloaded without authentication; private
artifacts require the caller to be authenticated and authorized.
- artifactUid (path, required): The unique identifier (UUID) of the artifact
PATCH /factory/{uid}/scorers/{scorer_uid}
Update a scorer's definition
Apply a partial update to a scorer's definition; omitted fields are
left unchanged, but at least one field must be provided, and the
owning factory is immutable. Each update bumps the scorer's version
without invalidating any scoring judge already in flight, since
judges validate against the definition snapshot taken at dispatch
time, and historical scores keep their recorded classification
values. Supplying `scope_mode` or `agent_uids` replaces the scorer's
scope in full.
- scorer_uid (path, required): The scorer identifier
DELETE /factory/{uid}/scorers/{scorer_uid}
Delete a scorer
Permanently delete a scorer. This is not reversible and it is not an
archive: the scorer's scoring attempts, scores, judge reasoning, self-improvement
config, and self-improvement triage results go with it, and the scorer stops
being readable through this API as soon as the call returns.
The underlying rows and the judge-reasoning blobs stored outside the
database are destroyed shortly afterwards by the deletion sweep, which
removes each blob before the record that references it and retries until
both are gone.
- scorer_uid (path, required): The scorer identifier
GET /agent/conversations/{conversationId}/block-snapshot
Download a conversation's block snapshot
Redirect to a signed storage URL for the serialized block snapshot.
Set redirect=false to return the URL as JSON instead. Both modes require
permission to view the conversation.
- conversationId (path, required)
- ()
POST /agent/identities
Create an agent
Create a new agent in the caller's active team. Agents act autonomously with their
own permissions, configuration, and identity.
GET /agent/identities
List agents
List all agents on the caller's team.
- ()
- factory_uid (query): Optional UID of a Factory to filter by. When provided, only agents
linked to that factory are returned.
- branch_uid (query): Optional Factory branch UID. Requires factory_uid and access to that
factory. Returns only active agents in that branch; when omitted,
only production agents are returned.
POST /factory/{uid}/scorers
Create a scorer
Create an active run scorer for a factory with either selected-agent or
all-agent scope. Creating a scorer does not start scoring. Pass
self_improvement_enabled to also turn on self-improvement for the new scorer in the same
request; the scorer and its self-improvement config are created atomically.
GET /factory/{uid}/scorers
List agent scorers
List the scorers in the factory named in the path, including scope agents
and aggregate scoring stats.
- ()
- start_date (query): Legacy summary range start (RFC3339 UTC, inclusive). Accepted
and validated for compatibility; does not affect the list
response. Must be provided together with end_date and be
strictly before it.
- end_date (query): Legacy summary range end (RFC3339 UTC, exclusive). See start_date.
GET /factory/{uid}/scorers/{scorer_uid}/results
List results for a scorer
List the scorer's most recent scoring attempts, newest first. A
failed attempt carries no classification. Pagination is a keyset
cursor over attempted_at with the attempt id as a stable tiebreak.
Repeat `run_id` to return all matching results without pagination; unknown runs are omitted.
Reasons are read from object storage only when include_reasons is true.
- ()
- scorer_uid (path, required): The scorer identifier
- limit (query): Maximum number of results to return (1-100, default 50)
- cursor (query): Opaque cursor returned by a previous list response.
- include_reasons (query): Include reason availability and readable judge reasoning.
- run_id (query): Exact run filters, repeated once per run. Values are trimmed and
deduplicated; require 1-100 distinct nonblank runs when present.
Cannot be combined with cursor or limit.
GET /factory/{uid}/scorers/{scorer_uid}/metrics
Get scorer metrics over a date range
Returns a period-aligned pass-rate series plus a full-range aggregate
for the scorer, computed directly from every live
score in [start_date, end_date).
Binning follows the same day/week/month rules and 365-period cap as
`GET /factory/{uid}/metrics`.
- ()
- scorer_uid (path, required): The scorer identifier
- start_date (query): RFC3339 UTC range start, inclusive. Defaults to 30 days before end_date.
- end_date (query): RFC3339 UTC range end, exclusive. Defaults to now.
- group_by_period (query): Binning granularity for the series. Defaults to day.
- include_cost (query): Include the scorer's judge-run cost for each period. Defaults to false.
POST /factory/{factory_uid}/runs/{run_id}/scorer_dispatch
Manually dispatch scorers for a run
Evaluate one run with the scorers in `scorer_uids`. To evaluate multiple
runs with one scorer, use
`/factory/{factory_uid}/scorers/{scorer_uid}/dispatch`.
Manual dispatch skips automatic scoring's cool-down and sampling
(including 0%) and supports older or previously scored runs.
Requires manage access to the factory and view access to the run.
The run must have a conversation and be executed by a factory agent,
not be a scoring job. The run and scorers must belong to this factory
and team. Each scorer must be configured for the run's agent and must
not be benchmark-managed.
Provide 1–100 scorer UUIDs. Run and scorer UUIDs must be nonzero.
Invalid selections reject the whole request before any scoring jobs start.
Returns dispatch outcomes, not completed scores. Valid requests can have
individual failures; inspect each result's `status` and `error`.
- factory_uid (path, required): The factory containing the run and scorers.
- run_id (path, required)
POST /factory/{factory_uid}/scorers/{scorer_uid}/dispatch
Manually dispatch a scorer for selected runs
Evaluate the runs in `run_ids` with one scorer. To evaluate one run with
multiple scorers, use
`/factory/{factory_uid}/runs/{run_id}/scorer_dispatch`.
Manual dispatch skips automatic scoring's cool-down and sampling
(including 0%) and supports older or previously scored runs.
Requires manage access to the factory and view access to every run.
Runs must have conversations and be executed by factory agents,
not be scoring jobs. The scorer and runs must belong to this factory
and team. The scorer must be configured for each run's agent and must
not be benchmark-managed.
Provide 1–100 run UUIDs. Run and scorer UUIDs must be nonzero.
Invalid selections reject the whole request before any scoring jobs start.
Returns dispatch outcomes, not completed scores. Valid requests can have
individual failures; inspect each result's `status` and `error`.
- factory_uid (path, required): The factory containing the scorer and runs.
- scorer_uid (path, required)
GET /factory/runs/{run_id}/scores
Read a run's current scores
List the current live attempt for each evaluation that has attempted
the given run, most recent attempt first. Excludes a deleted
evaluation's data.
Requires only view access to the run, since reading scores is part of viewing
the run.
- run_id (path, required): The run identifier
GET /agent/identities/{uid}
Retrieve an agent
Retrieve a single agent by its unique identifier.
- uid (path, required): The unique identifier of the agent
PUT /agent/identities/{uid}
Update an agent
Update an existing agent.
- uid (path, required): The unique identifier of the agent
DELETE /agent/identities/{uid}
Delete an agent
Delete an agent. All API keys associated with the
agent are deleted atomically.
- uid (path, required): The unique identifier of the agent
GET /agent/sessions/{sessionUuid}/redirect
Get session redirect
Check whether a shared session should redirect to a conversation
transcript, returning a conversation_id if the agent sandbox has
finished and conversation data is available (or an empty object if
no redirect is needed). Public and unauthenticated, so anonymous
viewers can resolve a shared session link before signing in; access
to the underlying transcript is still gated by conversation
link-sharing.
- sessionUuid (path, required): The UUID of the shared session
GET /agent/conversations/{conversationId}/redirect
Get conversation redirect
Check whether a conversation should redirect to a live shared
session, returning a session_id if the underlying ambient agent task
still has one (or an empty object if no redirect is needed). Public
and unauthenticated, so anonymous viewers can resolve a shared
conversation link before signing in; access to the underlying live
session is still gated by the session-sharing service ACLs.
- conversationId (path, required): The ID of the conversation
POST /factory/{factory_uid}/benchmarks
Create a benchmark suite
GET /factory/{factory_uid}/benchmarks
List benchmark suites
- ()
- limit (query)
- cursor (query)
GET /factory/{factory_uid}/benchmarks/{suite_uid}
Get a benchmark suite with its tasks and configurations
PATCH /factory/{factory_uid}/benchmarks/{suite_uid}
Edit a benchmark suite
DELETE /factory/{factory_uid}/benchmarks/{suite_uid}
Soft-delete a benchmark suite
POST /factory/{factory_uid}/benchmarks/{suite_uid}/tasks
Create a benchmark suite task
This adds a single hand-authored task to a suite, without needing
to resend the whole task list. A title, prompt, and success
criteria are required, and if a `source_run_id` is included, the
caller must have permission to read that run. Adding the exact
same task twice simply returns the existing one (so retrying is
safe), while reusing a title with different content is rejected
as a conflict — and on a `code.storage`-managed Factory, the task
is saved as a file and returned from that file.
GET /factory/{factory_uid}/benchmarks/{suite_uid}/tasks/{task_uid}
Get one benchmark suite task
- ()
- ()
- task_uid (path, required)
PATCH /factory/{factory_uid}/benchmarks/{suite_uid}/tasks/{task_uid}
Edit one benchmark suite task
Edits a single task in place without resending the suite's full task
list. Omitted fields keep their current values. title, prompt, and
success_criteria reject null and empty-after-trim values. An
explicit null source_run_id clears provenance. An explicit empty
starting_repo_refs or tags clears that field.
- ()
- ()
- task_uid (path, required)
DELETE /factory/{factory_uid}/benchmarks/{suite_uid}/tasks/{task_uid}
Delete one benchmark suite task
- ()
- ()
- task_uid (path, required)
POST /factory/{factory_uid}/benchmarks/{suite_uid}/runs
Launch a benchmark run from the current suite version
Each successful request creates a new run. Launch is not idempotent:
disable automatic retries for this request and reconcile an uncertain
outcome by listing runs before launching again.
Retries are a client transport option, not a request-body field.
In the TypeScript SDK, pass { maxRetries: 0 } as the request options.
In the Python SDK, call create through client.with_options(max_retries=0).
These options do not change execution retries within the benchmark run.
GET /factory/{factory_uid}/benchmarks/{suite_uid}/runs
List benchmark runs
List runs launched from this benchmark suite. Each entry contains the
run's status and execution/scoring progress. Use `include` to add launch
settings, aggregate results, or the creator's display name to each entry.
The response contains a page of runs in `data` and continuation
information in `page_info`. Retained runs remain readable after the
suite is deleted; an unknown suite returns an empty list.
- ()
- ()
- ()
- state (query)
- limit (query)
- cursor (query)
GET /factory/{factory_uid}/benchmarks/{suite_uid}/runs/{run_uid}
Get benchmark run detail
Retrieve a benchmark run's status and execution/scoring progress.
By default, the response omits launch settings and aggregate results.
Use `include` to add these fields or the creator's display name.
Retrieve trials separately for individual scores and execution history.
POST /factory/{factory_uid}/benchmarks/{suite_uid}/runs/{run_uid}/cancel
Cancel an in-flight benchmark run
GET /factory/{factory_uid}/benchmarks/{suite_uid}/runs/{run_uid}/results
Get benchmark run results
Retrieve aggregate outcomes, coverage, and costs for the run.
Task and tag filters select the trials used to calculate the results.
By default, the response contains summary fields without detailed
metric arrays; use `include` to add those arrays.
Configuration and scorer filters limit returned metric rows without
changing the summary or comparison populations. Results cover the whole
selected dataset, independently of trial-list pages, and are not paginated.
GET /factory/{factory_uid}/benchmarks/{suite_uid}/runs/{run_uid}/trials
List benchmark trials or find the trial for an agent run
Each trial represents one task, configuration, and repetition within
the benchmark run. The response contains a page of trials in `data`
and continuation information in `page_info`. Use `include` to add
scores, metrics, or retained execution history to each trial.
Repeated values match any value within a filter; different filters
must all match.
To find the trial for a primary agent execution, pass `agent_run_id`.
This returns zero or one trial, with `matched_attempt_number` identifying
the matching attempt. Judge runs and spawned descendant runs do not match.
This lookup accepts `include` and an omitted `limit` or `limit=1`, but
no cursor or other filters. Filtering by scorer is not supported.
- ()
- ()
- ()
- ()
- ()
- ()
- configuration_uid (query)
- state (query)
- agent_run_id (query)
- limit (query)
- cursor (query): Pass the previous response's page_info.next_cursor with the same filters to retrieve the next page.
GET /factory/{factory_uid}/benchmarks/{suite_uid}/runs/{run_uid}/trials/{trial_uid}
Retrieve an individual benchmark trial within a run
Retrieve the trial's execution and scoring status for one task,
configuration, and repetition within the run. Include results to
retrieve its scores and metrics, or details to retrieve retained
execution attempts and judge history. Each requested expansion is
complete. Selection and pagination parameters are not supported.
- ()
- ()
- ()
- ()
- trial_uid (path, required)
GET /factory-files/schemas
List the supported Factory file schema versions
Returns every Factory file schema version this server can describe,
with a link to each version's schema bundle.
- If-None-Match (header): A previously returned ETag. A match returns 304 with no body.
GET /factory-files/schemas/{schema_version}
Get the JSON Schema bundle for one Factory file schema version
Returns every JSON Schema 2020-12 document describing one Factory file
schema version, as a single bundle so the relative `$id` and `$ref`
identities between the documents keep resolving.
- schema_version (path, required): A Factory file schema version, for example `v1alpha1`.
- If-None-Match (header): A previously returned ETag. A match returns 304 with no body.
GET /factory-files/schemas/{schema_version}/{document}
Get one Factory file schema document
Returns a single generated JSON Schema document on its own, rather
than inside the bundle envelope, so it can be used directly as a
schema reference. A document served here resolves its relative
`$ref`s against its siblings at this same path, which is what each
document's `$id` assumes, making the URL usable directly from an
editor or YAML language server, for example:
```yaml
# yaml-language-server: $schema=/api/v1/factory-files/schemas/v1alpha1/factory.schema.json
```
- schema_version (path, required): Factory file schema version, such as v1alpha1
- document (path, required): Document file name: common.schema.json, factory.schema.json,
agent.schema.json, automation.schema.json, runner.schema.json, or
scorer.schema.json