# Answer your first thread

The shortest path from a product with Support available to a thread that has been answered. It takes seven steps and configures nothing beforehand: the status dictionary seeds itself the first time you read it.

Every step here is an MCP tool call. The same operations exist over the REST API under `/support`, and the same work is done by hand in the Workspace app — Support is headless and has no screens of its own, so there is no Product App page to open instead.

Nothing in this guide involves an end user's Lessly account, because there is no such thing. `user_8842` below is an identifier from your own user base: Support stores it verbatim and resolves nothing about it.

## 1. Read the status dictionary

[`support_status_list`](/reference/mcp-tools/support_status_list)

A product that has never touched its settings gets four statuses seeded on this first call:

```json
{
  "statuses": [
    { "id": "b48d8d0d…", "name": "open", "color": "#2563eb", "order": 0, "category": "open", "archived": false },
    { "id": "87e60f77…", "name": "pending", "color": "#d97706", "order": 1, "category": "pending", "archived": false },
    { "id": "d6284a3e…", "name": "resolved", "color": "#16a34a", "order": 2, "category": "resolved", "archived": false },
    { "id": "4463741a…", "name": "closed", "color": "#6b7280", "order": 3, "category": "closed", "archived": false }
  ]
}
```

Keep the `open` and `pending` ids: you need them in step 5.

The `name` is what people see and you may change it. The `category` is what Support itself reads, and it is fixed once threads sit on the status. More in [Statuses](/ship/support/statuses).

## 2. Create the agent who will answer

An agent is the profile an end user sees next to a reply. It is Support's own entity, not a projection of a Lessly account.

[`support_agent_create`](/reference/mcp-tools/support_agent_create)

```json
{ "displayName": "Maria", "title": "Support engineer" }
```

```json
{
  "id": "13c893aa…",
  "displayName": "Maria",
  "title": "Support engineer",
  "avatarUrl": null,
  "lesslyUserId": null,
  "isActive": true
}
```

`lesslyUserId` is optional and left empty here. Bind it when a human should sign into the Workspace app and work as this profile; leave it out for a bot or for your own backend, which replies exactly the same way. More in [Agents](/ship/support/agents).

## 3. Open a thread on behalf of an end user

[`support_thread_create`](/reference/mcp-tools/support_thread_create)

```json
{
  "type": "ticket",
  "title": "Cannot upload my avatar",
  "authorExternalId": "user_8842",
  "authorDisplay": "Alex Fern"
}
```

```json
{
  "id": "b50f26b4…",
  "type": "ticket",
  "title": "Cannot upload my avatar",
  "status": { "name": "open", "category": "open" },
  "priority": "normal",
  "authorExternalId": "user_8842",
  "authorDisplay": "Alex Fern",
  "assignedAgentId": null,
  "labels": [],
  "lastReplyAt": null
}
```

`type` is `ticket` when the end user wants something fixed and `feedback` when the input is unsolicited. There is no status argument: the thread opens on the product's default open status — the non-archived `open`-category status with the lowest display order. More in [Threads and messages](/ship/support/threads-and-messages).

## 4. Put the thread on an agent

[`support_thread_assign`](/reference/mcp-tools/support_thread_assign)

```json
{ "id": "b50f26b4…", "agentId": "13c893aa…" }
```

The thread comes back with `assignedAgentId` set. Passing `null` instead returns it to the unassigned queue, which is an ordinary move rather than an error.

## 5. Write the conversation

The end user's own words go in as an inbound message, through [`support_message_create`](/reference/mcp-tools/support_message_create):

```json
{
  "threadId": "b50f26b4…",
  "direction": "inbound",
  "authorExternalId": "user_8842",
  "body": "The upload button does nothing when I pick a PNG."
}
```

Maria's answer is outbound and authored by the agent:

```json
{
  "threadId": "b50f26b4…",
  "direction": "outbound",
  "authorAgentId": "13c893aa…",
  "body": "Thanks for the report. Which browser are you on?"
}
```

Exactly one of the two author fields is set on each message — never both and never neither. Both messages come back with `"visibility": "public"`, which is the default; an `internal` note is stored the same way and is never shown to the end user.

## 6. Park the thread, and watch it come back

Maria is waiting on the customer, so the thread moves to `pending` with [`support_thread_status_set`](/reference/mcp-tools/support_thread_status_set):

```json
{ "id": "b50f26b4…", "statusId": "87e60f77…" }
```

Any status may follow any other — there are no transition rules, and the category is never a parameter: it comes from the status the thread lands on.

Then the customer answers:

```json
{
  "threadId": "b50f26b4…",
  "direction": "inbound",
  "authorExternalId": "user_8842",
  "body": "Firefox 141 on Windows."
}
```

Read the thread back with [`support_thread_get`](/reference/mcp-tools/support_thread_get):

```json
{
  "id": "b50f26b4…",
  "status": { "id": "b48d8d0d…", "name": "open", "category": "open" },
  "assignedAgentId": "13c893aa…",
  "lastReplyAt": "2026-08-19T17:11:32.344Z"
}
```

Nobody moved it. A **public inbound** message on a thread parked in the `pending` category pulls that thread back to `open` — the one automatic transition Support has. It reads the category and not the name, so renaming `pending` to "waiting on customer" keeps it working. An internal note does not trigger it, and neither does an outbound message.

## 7. Read the queue and the conversation

The thread now sits in the open queue. [`support_thread_list`](/reference/mcp-tools/support_thread_list):

```json
{ "category": "open", "limit": 2 }
```

Threads come back newest first, and every filter lives on this call: type, status, status category, assignee, external author, labels, creation window.

The conversation itself reads forward, oldest first. [`support_message_list`](/reference/mcp-tools/support_message_list):

```json
{ "threadId": "b50f26b4…", "visibility": "public" }
```

Asking for `public` returns what the end user would see. Omit `visibility` and public messages and internal notes come back together.

## What you just did

The product now has a seeded status dictionary, one agent profile, and one ticket that was opened on behalf of an external end user, assigned, answered, parked and reopened by the customer's own reply.

## What to do next

- [Threads and messages](/ship/support/threads-and-messages): filtering the queue, and catching up on everything you missed.
- [Labels and attachments](/ship/support/labels-and-attachments): tags, and sending a file with a message.
- [Receive Support events](/ship/support/webhooks): hearing about a reply without polling for it.
