> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.meshapi.ai/docs/guides/llms.txt.
> For full documentation content, see https://developers.meshapi.ai/docs/guides/llms-full.txt.

# Prompt Templates

> Store, version, and reuse prompt configurations — with variable substitution — across your team and apps.

Prompt Templates let you define a system prompt, base conversation turns, and default inference parameters once — then reference them by name from any chat completion request. Instead of hardcoding the same prompt logic in every client, you manage it centrally and inject runtime values using `{{variable}}` slots.

## Authentication

Template management (create, read, update, delete) accepts **either** authentication method:

| Method                  | How                             | Typical use                                 |
| ----------------------- | ------------------------------- | ------------------------------------------- |
| **RSK key** (`rsk_...`) | `Authorization: Bearer rsk_...` | Direct API access from your backend         |
| **Mesh Dashboard**      | Handled automatically           | Managing templates through the dashboard UI |

Using a template at inference time always uses your `rsk_...` key, the same as any other chat completion.

See the [Authentication guide](/docs/guides/authentication) for details on key types.

***

## Creating a Template

Send a `POST /v1/templates` request with a name, an optional system prompt, and any variables you want to parameterize.

<Tabs>
  <Tab title="curl">
    ```bash
    curl https://api.meshapi.ai/v1/templates \
      -H "Authorization: Bearer <YOUR_RSK_KEY>" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "support-agent",
        "description": "Customer support assistant with configurable tone",
        "system": "You are a {{tone}} support agent for {{company}}. Help users resolve their issues politely and accurately.",
        "model": "openai/gpt-4o-mini",
        "params": { "temperature": 0.5, "max_tokens": 512 },
        "variables": ["company", "tone"]
      }'
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts
    import { MeshAPI } from "meshapi-node-sdk";

    const client = new MeshAPI({
      baseUrl: "https://api.meshapi.ai",
      token: "rsk_...",
    });

    const template = await client.templates.create({
      name: "support-agent",
      description: "Customer support assistant with configurable tone",
      system: "You are a {{tone}} support agent for {{company}}. Help users resolve their issues politely and accurately.",
      model: "openai/gpt-4o-mini",
      params: { temperature: 0.5, max_tokens: 512 },
      variables: ["company", "tone"],
    });

    console.log(template.id);
    ```
  </Tab>

  <Tab title="Python">
    ```python
    from meshapi import MeshAPI

    client = MeshAPI(base_url="https://api.meshapi.ai", token="csk_...")

    template = client.templates.create(
        name="support-agent",
        description="Customer support assistant with configurable tone",
        system="You are a {{tone}} support agent for {{company}}. Help users resolve their issues politely and accurately.",
        model="openai/gpt-4o-mini",
        params={"temperature": 0.5, "max_tokens": 512},
        variables=["company", "tone"],
    )

    print(template.id)
    ```
  </Tab>
</Tabs>

**Response:**

```json
{
  "id": "tmpl_01jt3abc...",
  "name": "support-agent",
  "owner": "org_xyz",
  "description": "Customer support assistant with configurable tone",
  "system": "You are a {{tone}} support agent for {{company}}. Help users resolve their issues politely and accurately.",
  "model": "openai/gpt-4o-mini",
  "params": { "temperature": 0.5, "max_tokens": 512 },
  "variables": ["company", "tone"],
  "created_at": "2025-06-01T10:00:00Z",
  "updated_at": "2025-06-01T10:00:00Z"
}
```

***

## Using Variables

Variables use double-brace syntax: `{{ variable_name }}`. Whitespace inside the braces is trimmed, so `{{company}}` and `{{ company }}` are equivalent. Variable names may contain letters, digits, and underscores.

You can place variables in `system` and in any message `content` field:

```json
{
  "name": "onboarding-guide",
  "system": "You are onboarding {{user_name}} to {{product_name}}. Be concise and encouraging.",
  "messages": [
    {
      "role": "assistant",
      "content": "Welcome, {{user_name}}! Let's get you set up with {{product_name}}."
    }
  ]
}
```

The `variables` field (list of strings) is informational — it documents which slots the template expects. It doesn't enforce anything server-side, but it helps callers know what to pass.

<Note>
  **Missing variables at inference time cause a `422` error.** Extra variables
  in the request are silently ignored.
</Note>

***

## Using a Template in Chat Completions

Pass `template` (name or UUID) and `variables` alongside your `messages` in a `POST /v1/chat/completions` request. The template's system prompt and base messages are prepended to your messages before the request is forwarded to the model.

<Tabs>
  <Tab title="curl">
    ```bash
    curl https://api.meshapi.ai/v1/chat/completions \
      -H "Authorization: Bearer <YOUR_RSK_KEY>" \
      -H "Content-Type: application/json" \
      -d '{
        "template": "support-agent",
        "variables": { "company": "Acme Corp", "tone": "friendly" },
        "messages": [{ "role": "user", "content": "How do I reset my password?" }]
      }'
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts
    const response = await client.chat.completions.create({
      template: "support-agent",
      variables: { company: "Acme Corp", tone: "friendly" },
      messages: [{ role: "user", content: "How do I reset my password?" }],
    });

    console.log(response.choices[0]?.message.content);
    ```
  </Tab>

  <Tab title="Python">
    ```python
    response = client.chat.completions.create(
        template="support-agent",
        variables={"company": "Acme Corp", "tone": "friendly"},
        messages=[{"role": "user", "content": "How do I reset my password?"}],
    )

    print(response.choices[0].message.content)
    ```
  </Tab>
</Tabs>

The final messages sent to the model look like this:

```json
[
  {
    "role": "system",
    "content": "You are a friendly support agent for Acme Corp. Help users resolve their issues politely and accurately."
  },
  { "role": "user", "content": "How do I reset my password?" }
]
```

<Note>
  You can reference a template by **name** or **UUID**. Name lookups are scoped
  to your key's owner first, then fall back to global (admin-seeded) templates.
  UUID lookups work across any owner.
</Note>

***

## Parameter Priority

When a template and a request body both specify inference settings, Mesh resolves them in this order (highest wins):

| Priority    | Source            | Example                                            |
| ----------- | ----------------- | -------------------------------------------------- |
| 3 — highest | Request body      | `"temperature": 0.9` in the POST body              |
| 2           | Key defaults      | Default params configured on your API key          |
| 1 — lowest  | Template defaults | `"params": { "temperature": 0.5 }` in the template |

This means you can define sensible defaults in the template and still override them per-request without changing the template.

***

## Managing Templates

### List all templates

```bash
curl https://api.meshapi.ai/v1/templates \
  -H "Authorization: Bearer <YOUR_RSK_KEY>"
```

Returns your owned templates plus any global templates, ordered newest first.

### Get a single template

```bash
curl https://api.meshapi.ai/v1/templates/tmpl_01jt3abc... \
  -H "Authorization: Bearer <YOUR_RSK_KEY>"
```

### Update a template

Only the fields you include are changed — everything else stays the same.

```bash
curl -X PATCH https://api.meshapi.ai/v1/templates/tmpl_01jt3abc... \
  -H "Authorization: Bearer <YOUR_RSK_KEY>" \
  -H "Content-Type: application/json" \
  -d '{ "params": { "temperature": 0.3, "max_tokens": 1024 } }'
```

### Delete a template

```bash
curl -X DELETE https://api.meshapi.ai/v1/templates/tmpl_01jt3abc... \
  -H "Authorization: Bearer <YOUR_RSK_KEY>"
```

Returns `204 No Content` on success.

***

## Global vs. Owned Templates

|                       | Owned               | Global                 |
| --------------------- | ------------------- | ---------------------- |
| **Created by**        | You (via `rsk_...`) | Mesh admins            |
| **Name lookup scope** | Your owner only     | Available to all users |
| **Can edit / delete** | Yes                 | No                     |
| **UUID lookup**       | Shareable by ID     | Shareable by ID        |

Global templates are useful for standard system roles (e.g., a generic coding assistant or translation prompt) that Mesh pre-seeds for all users. If you create a template with the same name as a global one, your owned template takes precedence in name lookups.

<Note>
  UUID-based lookups are intentionally cross-owner — this lets you share a
  template with another team by passing them the template ID. Name-based lookups
  are always scoped to your own account, so there's no risk of accidentally
  using someone else's template by name.
</Note>