Factories > Integrations
Use the factory API
# Use the factory API Use the factory API to find a factory and start work from a custom integration without managing agent details. Build it into a chat bot, script, or service for any tool Warp doesn't connect to directly. :::note Warp Factories is in **Early Access** and available to a limited set of teams. [Request access](https://www.warp.dev/factories/request-access) to use it with your team. ::: ## Key features * **Discover factories by name** - Search factories your account can access by name or alias, so your integration doesn't need to hardcode factory UIDs. * **Dispatch by UID, not by agent** - Start a run with only a factory's UID. The server resolves the factory's foreman agent for you. * **Ticket metadata built in** - Attach a `ticket_ref` (and optional `ticket_url`) to a dispatched run so the factory's task ties back to your own tracker from the start. * **Continue with the existing Oz API & SDK** - Once a run is dispatched, every other Agent API operation (retrieving status, sending follow-ups) works on it unchanged. ## How it works Earlier integrations that sent work to a factory had to call the lower-level Agent API and pass the factory's foreman agent as an `agent_identity_uid` - an implementation detail a caller had to look up and store out of band. The factory API removes that step: **program against the factory, not the foreman**. A factory exposes a public UID, the same UID shown in the [factory dashboard](/factories/factory-dashboard/) and used by [Factory MCP](/factories/factory-mcp/). Two endpoints work with that UID: * `GET /factory` - list factories your account can access, optionally filtered with a `search` parameter that matches the factory's name or alias, case-insensitively. * `GET /factory/{uid}` - retrieve a single factory by UID. Dispatching work is a single call: * `POST /factory/{uid}/runs` - creates a run on the factory's foreman agent. The server looks up the foreman for you, so the request body only needs a `prompt`, a `title`, and optionally a `ticket_ref`/`ticket_url` pair identifying the originating ticket in your own tracker. The response is an ordinary run: a `run_id`, a `run_url`, and a `state`. From there, the run behaves like any other [cloud agent run](/platform/) - list it, retrieve it, or send it follow-ups through the same [Agent API](/reference/api-and-sdk/) endpoints you'd use for a run started any other way. The factory API only changes how a run gets *started*; everything downstream is unchanged. See the [Agents API Reference](/api) for full parameters and error codes on those run-management endpoints. ## When to use the factory API vs the Agent API Use the factory API to start work whenever the destination is a factory. Reach for the lower-level Agent API only when you're working with a standalone cloud agent that isn't part of a factory, or when you need a capability the factory API doesn't expose yet, such as full orchestration control. | Task | Recommended API | | --- | --- | | Find a factory by name before dispatching to it | factory API - `GET /factory?search=` | | Start a new task on a factory | factory API - `POST /factory/{uid}/runs` | | Continue, monitor, or cancel a run (factory or standalone) | Agent API - `GET /agent/runs/{runId}`, `POST /agent/runs/{runId}/followups`, `POST /agent/runs/{runId}/cancel` | | Run a standalone cloud agent with no factory involved | Agent API - `POST /agent/run` | | Build a multi-agent orchestration | Agent API - see [multi-agent orchestration](/platform/orchestration/) | The Agent API isn't deprecated. Every factory run is still an ordinary run under the hood, so status, follow-ups, and cancellation all go through the same Agent API endpoints regardless of which API started the run. The factory API only replaces the *dispatch* step for factory work. ## Discover a factory Before dispatching work, find the factory's UID. If your integration already stores the UID (for example, from when it was configured), skip ahead to [dispatching a run](#dispatch-a-run-to-a-factory). ### Search factories by name ```python import os from oz_agent_sdk import OzAPI client = OzAPI(api_key=os.environ.get("WARP_API_KEY")) # Find a factory by name or alias — no UIDs needed up front page = client.factories.list(search="payments") factory = page.factories[0] # With the pagination scheme wired, iteration auto-pages for f in client.factories.list(search="payments"): print(f.uid, f.name) ``` The REST equivalent: ```http GET /api/v1/factory?search=payments Authorization: Bearer YOUR_API_KEY ``` ### Retrieve a factory when the UID is already known ```python factory = client.factories.retrieve(factory.uid) ``` ```http GET /api/v1/factory/YOUR_FACTORY_UID Authorization: Bearer YOUR_API_KEY ``` ## Dispatch a run to a factory Dispatching a run only needs the factory's UID, a `prompt`, and a `title`. Foreman resolution happens server-side, so there's no separate lookup step. ```python run = client.factories.runs.create( factory.uid, prompt="Investigate and fix the flaky payment webhook retry test", title="Fix flaky payment webhook retry test", ticket_ref="linear:PAY-123", # optional; omitted -> adhoc ref ) print(run.run_id, run.run_url, run.state) ``` ```http POST /api/v1/factory/YOUR_FACTORY_UID/runs Authorization: Bearer YOUR_API_KEY Content-Type: application/json { "prompt": "Investigate and fix the flaky payment webhook retry test", "title": "Fix flaky payment webhook retry test", "ticket_ref": "linear:PAY-123" } ``` `ticket_ref` identifies the originating ticket in `<source>:<id>` form (for example `linear:PAY-123` or `jira:PROJ-456`). Pass an optional `ticket_url` alongside it so the factory's task record links straight back to your tracker. Omit both to let the server mint an adhoc reference. ## Continue and monitor the run A dispatched run is an ordinary run, so the rest of the Oz API & SDK works on it unchanged: ```python # Check status the same way you would for any other run status = client.agent.runs.retrieve(run.run_id) ``` To steer the run instead of just checking on it, send a follow-up the same way you would for a run started with `POST /agent/run`: ```http POST /api/v1/agent/runs/YOUR_RUN_ID/followups Authorization: Bearer YOUR_API_KEY Content-Type: application/json { "prompt": "Also add a regression test for the retry backoff" } ``` See [key endpoints](/reference/api-and-sdk/#key-endpoints) for the full set of run-management operations, including cancellation. ## Migrating from `agent_identity_uid` If your integration currently dispatches to a factory with the lower-level Agent API, replace the foreman lookup and `agent_identity_uid` with a single factory API call. **Before** - the caller has to already know the foreman's agent UID: ```python client.agent.run(prompt="Fix the flaky test", agent_identity_uid="YOUR_FOREMAN_AGENT_UID") ``` **After** - the caller only needs the factory's UID; the server resolves the foreman: ```python run = client.factories.runs.create( factory.uid, prompt="Fix the flaky test", title="Fix the flaky test", ) ``` The run executes exactly the same way, and existing run-management APIs keep working on it. The `agent_identity_uid` path still works for existing integrations, but new integrations should dispatch through the factory API instead of looking up and storing a foreman agent UID. :::note The Oz API & SDK is in the middle of a rename to align with the Automation Platform: today's `oz_agent_sdk` package and `OzAPI` client will eventually carry renamed Warp Agent and factory API names. The endpoints and fields on this page keep working across that rename; watch the [Python SDK](https://github.com/warpdotdev/oz-sdk-python) and [TypeScript SDK](https://github.com/warpdotdev/oz-sdk-typescript) repos for the updated names. ::: ## Related pages * [Connect your factory](/factories/connect-your-factory/) - Every way work can enter a factory, including the factory API alongside Slack, GitHub, and Factory MCP. * [Build a Mattermost bot for Warp Factories](/guides/external-tools/build-a-mattermost-bot-for-warp-factories/) - A worked example that discovers a factory and dispatches and continues a task from a custom chat integration. * [Factory MCP](/factories/factory-mcp/) - Connect a local coding agent to a factory instead of calling the REST API directly. * [Oz API & SDK](/reference/api-and-sdk/) - Full endpoint reference, SDKs, and error codes for the underlying Agent API. * [How Warp Factories work](/factories/how-factories-work/) - The stages a dispatched task moves through after the foreman picks it up.Tell me about this feature: https://docs.warp.dev/factories/factory-api/Discover factories and dispatch tasks by UID with the public factory API, without learning the foreman agent's internals.
Use the factory API to find a factory and start work from a custom integration without managing agent details. Build it into a chat bot, script, or service for any tool Warp doesn’t connect to directly.
Key features
Section titled “Key features”- Discover factories by name - Search factories your account can access by name or alias, so your integration doesn’t need to hardcode factory UIDs.
- Dispatch by UID, not by agent - Start a run with only a factory’s UID. The server resolves the factory’s foreman agent for you.
- Ticket metadata built in - Attach a
ticket_ref(and optionalticket_url) to a dispatched run so the factory’s task ties back to your own tracker from the start. - Continue with the existing Oz API & SDK - Once a run is dispatched, every other Agent API operation (retrieving status, sending follow-ups) works on it unchanged.
How it works
Section titled “How it works”Earlier integrations that sent work to a factory had to call the lower-level Agent API and pass the factory’s foreman agent as an agent_identity_uid - an implementation detail a caller had to look up and store out of band. The factory API removes that step: program against the factory, not the foreman.
A factory exposes a public UID, the same UID shown in the factory dashboard and used by Factory MCP. Two endpoints work with that UID:
GET /factory- list factories your account can access, optionally filtered with asearchparameter that matches the factory’s name or alias, case-insensitively.GET /factory/{uid}- retrieve a single factory by UID.
Dispatching work is a single call:
POST /factory/{uid}/runs- creates a run on the factory’s foreman agent. The server looks up the foreman for you, so the request body only needs aprompt, atitle, and optionally aticket_ref/ticket_urlpair identifying the originating ticket in your own tracker.
The response is an ordinary run: a run_id, a run_url, and a state. From there, the run behaves like any other cloud agent run - list it, retrieve it, or send it follow-ups through the same Agent API endpoints you’d use for a run started any other way. The factory API only changes how a run gets started; everything downstream is unchanged. See the Agents API Reference for full parameters and error codes on those run-management endpoints.
When to use the factory API vs the Agent API
Section titled “When to use the factory API vs the Agent API”Use the factory API to start work whenever the destination is a factory. Reach for the lower-level Agent API only when you’re working with a standalone cloud agent that isn’t part of a factory, or when you need a capability the factory API doesn’t expose yet, such as full orchestration control.
| Task | Recommended API |
|---|---|
| Find a factory by name before dispatching to it | factory API - GET /factory?search= |
| Start a new task on a factory | factory API - POST /factory/{uid}/runs |
| Continue, monitor, or cancel a run (factory or standalone) | Agent API - GET /agent/runs/{runId}, POST /agent/runs/{runId}/followups, POST /agent/runs/{runId}/cancel |
| Run a standalone cloud agent with no factory involved | Agent API - POST /agent/run |
| Build a multi-agent orchestration | Agent API - see multi-agent orchestration |
The Agent API isn’t deprecated. Every factory run is still an ordinary run under the hood, so status, follow-ups, and cancellation all go through the same Agent API endpoints regardless of which API started the run. The factory API only replaces the dispatch step for factory work.
Discover a factory
Section titled “Discover a factory”Before dispatching work, find the factory’s UID. If your integration already stores the UID (for example, from when it was configured), skip ahead to dispatching a run.
Search factories by name
Section titled “Search factories by name”import osfrom oz_agent_sdk import OzAPI
client = OzAPI(api_key=os.environ.get("WARP_API_KEY"))
# Find a factory by name or alias — no UIDs needed up frontpage = client.factories.list(search="payments")factory = page.factories[0]
# With the pagination scheme wired, iteration auto-pagesfor f in client.factories.list(search="payments"): print(f.uid, f.name)The REST equivalent:
GET /api/v1/factory?search=paymentsAuthorization: Bearer YOUR_API_KEYRetrieve a factory when the UID is already known
Section titled “Retrieve a factory when the UID is already known”factory = client.factories.retrieve(factory.uid)GET /api/v1/factory/YOUR_FACTORY_UIDAuthorization: Bearer YOUR_API_KEYDispatch a run to a factory
Section titled “Dispatch a run to a factory”Dispatching a run only needs the factory’s UID, a prompt, and a title. Foreman resolution happens server-side, so there’s no separate lookup step.
run = client.factories.runs.create( factory.uid, prompt="Investigate and fix the flaky payment webhook retry test", title="Fix flaky payment webhook retry test", ticket_ref="linear:PAY-123", # optional; omitted -> adhoc ref)print(run.run_id, run.run_url, run.state)POST /api/v1/factory/YOUR_FACTORY_UID/runsAuthorization: Bearer YOUR_API_KEYContent-Type: application/json
{ "prompt": "Investigate and fix the flaky payment webhook retry test", "title": "Fix flaky payment webhook retry test", "ticket_ref": "linear:PAY-123"}ticket_ref identifies the originating ticket in <source>:<id> form (for example linear:PAY-123 or jira:PROJ-456). Pass an optional ticket_url alongside it so the factory’s task record links straight back to your tracker. Omit both to let the server mint an adhoc reference.
Continue and monitor the run
Section titled “Continue and monitor the run”A dispatched run is an ordinary run, so the rest of the Oz API & SDK works on it unchanged:
# Check status the same way you would for any other runstatus = client.agent.runs.retrieve(run.run_id)To steer the run instead of just checking on it, send a follow-up the same way you would for a run started with POST /agent/run:
POST /api/v1/agent/runs/YOUR_RUN_ID/followupsAuthorization: Bearer YOUR_API_KEYContent-Type: application/json
{ "prompt": "Also add a regression test for the retry backoff"}See key endpoints for the full set of run-management operations, including cancellation.
Migrating from agent_identity_uid
Section titled “Migrating from agent_identity_uid”If your integration currently dispatches to a factory with the lower-level Agent API, replace the foreman lookup and agent_identity_uid with a single factory API call.
Before - the caller has to already know the foreman’s agent UID:
client.agent.run(prompt="Fix the flaky test", agent_identity_uid="YOUR_FOREMAN_AGENT_UID")After - the caller only needs the factory’s UID; the server resolves the foreman:
run = client.factories.runs.create( factory.uid, prompt="Fix the flaky test", title="Fix the flaky test",)The run executes exactly the same way, and existing run-management APIs keep working on it. The agent_identity_uid path still works for existing integrations, but new integrations should dispatch through the factory API instead of looking up and storing a foreman agent UID.
Related pages
Section titled “Related pages”- Connect your factory - Every way work can enter a factory, including the factory API alongside Slack, GitHub, and Factory MCP.
- Build a Mattermost bot for Warp Factories - A worked example that discovers a factory and dispatches and continues a task from a custom chat integration.
- Factory MCP - Connect a local coding agent to a factory instead of calling the REST API directly.
- Oz API & SDK - Full endpoint reference, SDKs, and error codes for the underlying Agent API.
- How Warp Factories work - The stages a dispatched task moves through after the foreman picks it up.