> ## Documentation Index
> Fetch the complete documentation index at: https://docs.routeway.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Messages & Roles

> Understand how the message array and roles shape every model response.

Every request to Routeway is built around a `messages` array — an ordered list of turns that represents the full conversation context. The model reads the entire array on each call and generates the next turn.

## Message Structure

Each message object has two required fields:

```json theme={null}
{
  "role": "user",
  "content": "What is the capital of France?"
}
```

| Field     | Type            | Description                                                  |
| --------- | --------------- | ------------------------------------------------------------ |
| `role`    | string          | Who sent the message: `system`, `user`, or `assistant`       |
| `content` | string \| array | The message text, or a mixed array of text and media objects |

***

## Roles

### `system`

Sets the model's behavior, persona, and constraints for the entire conversation. Processed before any user message, giving it the highest priority.

```json theme={null}
{
  "role": "system",
  "content": "You are a concise technical assistant. Reply in plain text only, no markdown."
}
```

Use `system` to:

* Define the model's persona or tone
* Restrict the model to a specific domain
* Provide background context or instructions that apply globally

<Tip>
  Put your `system` message first and keep it stable across turns. The model treats it as ground truth for the entire session.
</Tip>

### `user`

A message from the end user (or your application acting as the user). This is the primary way to send instructions and content to the model.

```json theme={null}
{
  "role": "user",
  "content": "Explain how HTTPS works in one paragraph."
}
```

### `assistant`

A message generated by the model. When building multi-turn conversations, append the model's previous responses as `assistant` messages so it can refer back to them.

```json theme={null}
{
  "role": "assistant",
  "content": "HTTPS uses TLS to encrypt data between a client and server..."
}
```

<Info>
  You can also inject `assistant` messages manually — for example, to prime the model with a specific tone or continue a previous conversation without replaying all prior turns.
</Info>

***

## Multi-turn Conversations

To maintain context across turns, include all previous messages in each new request. The model has no memory between API calls — the `messages` array *is* the memory.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import os
    from openai import OpenAI

    client = OpenAI(
        base_url="https://api.routeway.ai/v1",
        api_key=os.getenv("ROUTEWAY_API_KEY")
    )

    messages = [
        {"role": "system", "content": "You are a helpful assistant."}
    ]

    # Turn 1
    messages.append({"role": "user", "content": "What's the boiling point of water?"})
    response = client.chat.completions.create(model="gpt-4o-mini", messages=messages)
    reply = response.choices[0].message.content
    messages.append({"role": "assistant", "content": reply})
    print(reply)

    # Turn 2 — model remembers the previous question
    messages.append({"role": "user", "content": "And at high altitude?"})
    response = client.chat.completions.create(model="gpt-4o-mini", messages=messages)
    print(response.choices[0].message.content)
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      baseURL: "https://api.routeway.ai/v1",
      apiKey: process.env.ROUTEWAY_API_KEY,
    });

    const messages = [
      { role: "system", content: "You are a helpful assistant." },
    ];

    async function chat(userMessage) {
      messages.push({ role: "user", content: userMessage });

      const response = await client.chat.completions.create({
        model: "gpt-4o-mini",
        messages,
      });

      const reply = response.choices[0].message.content;
      messages.push({ role: "assistant", content: reply });
      return reply;
    }

    console.log(await chat("What's the boiling point of water?"));
    console.log(await chat("And at high altitude?"));
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl https://api.routeway.ai/v1/chat/completions \
      -H "Authorization: Bearer $ROUTEWAY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "gpt-4o-mini",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "What is the boiling point of water?"},
          {"role": "assistant", "content": "Water boils at 100°C (212°F) at sea level."},
          {"role": "user", "content": "And at high altitude?"}
        ]
      }'
    ```
  </Tab>
</Tabs>

***

## Rich Content Messages

The `content` field can be an array of typed objects instead of a plain string. This is how you pass images, PDFs, and mixed media alongside text.

```json theme={null}
{
  "role": "user",
  "content": [
    { "type": "text", "text": "What does this chart show?" },
    { "type": "image_url", "image_url": { "url": "https://example.com/chart.png" } }
  ]
}
```

See [Multimodal Inputs](/guides/chat-completions/multimodal-inputs) for the full reference.

***

## Common Patterns

<AccordionGroup>
  <Accordion title="Persona injection" icon="user-round">
    Give the model a name and personality via the `system` message. Consistent persona instructions reduce drift in long conversations.

    ```json theme={null}
    {
      "role": "system",
      "content": "You are Aria, a friendly customer support agent for Acme Corp. Always greet users by name when known."
    }
    ```
  </Accordion>

  <Accordion title="Few-shot examples" icon="list">
    Prepend example `user`/`assistant` pairs to show the model the exact format you want.

    ```json theme={null}
    [
      { "role": "user", "content": "Classify: 'I love this product!'" },
      { "role": "assistant", "content": "positive" },
      { "role": "user", "content": "Classify: 'Broke after one day.'" },
      { "role": "assistant", "content": "negative" },
      { "role": "user", "content": "Classify: 'It is okay I guess.'" }
    ]
    ```
  </Accordion>

  <Accordion title="Context injection" icon="file-text">
    Inject retrieved documents or data into a `user` or `system` message before the question. This is the foundation of RAG (retrieval-augmented generation).

    ```python theme={null}
    context = fetch_relevant_docs(user_query)
    messages = [
        {"role": "system", "content": "Answer only using the provided context."},
        {"role": "user", "content": f"Context:\n{context}\n\nQuestion: {user_query}"}
    ]
    ```
  </Accordion>
</AccordionGroup>

***

## Context Window Limits

The `messages` array is bounded by the model's **context window** — the maximum number of tokens it can process in a single request. Exceeding this limit causes a `400` error.

For long conversations, trim old messages from the middle of the array (keeping the `system` message and the most recent turns) or use [Prompt Caching](/guides/chat-completions/caching) to reduce costs when the prefix is stable.

See [Tokens & Context](/core-concepts/chat-completions/tokens-and-context) for more detail.
