---
title: "Create Template"
method: POST
path: "/worker-templates"
tags: ["worker-templates"]
---

# Create Template

`POST /worker-templates`

## Request

- Base URL: `https://api.traversal.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.traversal.com/worker-templates`
- Auth: none declared

## Request body

- CreateWorkerTemplateRequest: Create a reusable worker template. ``mode`` is required rather than defaulted: a template exists to state what a worker should be, and inheriting a column default silently is how you end up with alerts channels running in incident mode. A name already used by a **live** template is rejected with a 409. A deleted template's name is free to reuse — uniqueness is scoped to ``archived_at IS NULL``.
  - `name` string, required: Operator-facing label, unique per organization among live templates.
  - `mode` 'incident' | 'alerts' | 'custom', required: The kind of channel the agent lives in — its standing mission. Drives the swappable mode block in the system prompt (and, later, the toolset). ``escalation`` and others land as localized drop-ins (their standing block + tooling) when that work begins. ``incident`` and ``alerts`` each state a mission the worker owns whatever the operator writes. ``custom`` states none: it supplies only the conduct floor the identity block forward-references, and the operator's ``custom_instruction`` is what gives the worker something to do. A channel that is neither working an incident nor triaging alert fires gets this one rather than being told it is in an incident (PRD-3766). The value is what customer-facing surfaces render, so it reads as the operator's own word for it rather than as an internal category. A member's *name* is persisted, in ``resident_agent_workflow.mode`` and ``resident_agent_template.mode`` — plain varchars with no DB-side value set — and read back through this enum, so adding a member is one deploy but removing or renaming one orphans every row holding it. It also makes a member forward-only: code that predates it raises on a row that carries it, rather than degrading. So a new member wants its read deployed everywhere before anything can write it — either landing the member ahead of the paths that create it, or gating creation while it rolls out. The same names are stored in usage policy bodies. Renaming or removing a member stops a body naming it from parsing, and that disables the template's policies.
  - `custom_instruction` string, nullable: Standing instruction seeded onto workers deployed from this template.
  - `trigger_rule_ids` string[]: Live CHANNEL_JOIN rules to point at the new template. Every id is verified to exist in your organization before the template is created.

## Response `201`

Successful Response

- WorkerTemplateResponse
  - `id` string, required
  - `organization_id` string, required
  - `name` string, required
  - `mode` 'incident' | 'alerts' | 'custom', required: The kind of channel the agent lives in — its standing mission. Drives the swappable mode block in the system prompt (and, later, the toolset). ``escalation`` and others land as localized drop-ins (their standing block + tooling) when that work begins. ``incident`` and ``alerts`` each state a mission the worker owns whatever the operator writes. ``custom`` states none: it supplies only the conduct floor the identity block forward-references, and the operator's ``custom_instruction`` is what gives the worker something to do. A channel that is neither working an incident nor triaging alert fires gets this one rather than being told it is in an incident (PRD-3766). The value is what customer-facing surfaces render, so it reads as the operator's own word for it rather than as an internal category. A member's *name* is persisted, in ``resident_agent_workflow.mode`` and ``resident_agent_template.mode`` — plain varchars with no DB-side value set — and read back through this enum, so adding a member is one deploy but removing or renaming one orphans every row holding it. It also makes a member forward-only: code that predates it raises on a row that carries it, rather than degrading. So a new member wants its read deployed everywhere before anything can write it — either landing the member ahead of the paths that create it, or gating creation while it rolls out. The same names are stored in usage policy bodies. Renaming or removing a member stops a body naming it from parsing, and that disables the template's policies.
  - `custom_instruction` string, nullable, required
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `422`: Validation Error

## Changes

> 66 revisions in range; 9 not diffed.

- **2026-09-02** `3025330cc50d`: 1 warning, 1 info
  - added the new `custom` enum value to the `mode` response property for the response status `201`
  - added the new `custom` enum value to the request property `mode`

[Operation history](https://skmtc.dev/traversal/apis/traversal-api/changes/worker-templates/post.md)

---

[API](https://skmtc.dev/traversal/apis/traversal-api.md) - [All operations](https://skmtc.dev/traversal/apis/traversal-api/llms.txt) - [OpenAPI document](https://skmtc.dev/traversal/apis/traversal-api/revisions/31e1a8b7cf89?raw)
