# Triage

{/* Generated from backend/features/recipes/catalogue/triage.yaml by `make arch`. Never edit this page: edit the recipe and run `make arch`, or `--check` fails. */}

Sort each new thread of one connection under the organization's labels, sending some to people and the rest to an agent.

This page is made from the recipe `triage`, version 1, and says nothing the recipe does not. [How a recipe is composed](/cookbook) explains every word it uses.

## Its setup

Each new conversation on \[The connection Triage answers\] is labelled: those with \[The labels that go to people\] wait for a person, and \[The agent that answers what is not for people\] takes the rest.

Each phrase in brackets is a parameter the recipe asks for, named as the table of parameters below names it.

While \[The labels that go to people\] is left blank: Each new conversation on \[The connection Triage answers\] is labelled, and \[The agent that answers what is not for people\] takes every one.

## Its parts, in the order data travels

1. **thread_flow `answers`** — Makes this triage the flow the connection answers each message with.
   - answers the connection `${param.connection}` (the value of the parameter `connection`) with the flow `triage`, in place of the flow it answered with
2. **flow `triage`** — Sorts the first message of each conversation and hands each message to a person or to the agent.
   - step `arrived` runs the tool `first`
   - step `checked` runs the tool `first`
   - step `answered` runs the tool `to_agent`, only while `agent` has a value
   - step `for_a_person` runs the tool `to_people`, only while `agent` is left blank
   - step `read` runs the tool `classify`
   - step `sorted` runs the tool `first`
   - step `labelled` runs the tool `put_label`
   - step `acknowledged` runs the tool `acknowledge`, only while `acknowledgement` has a value
   - step `for_people` runs the tool `to_people`, only while `people_labels` has a value
3. **tool `first`** — Passes on the conversation the message arrived on, for the flow to choose where it goes next.
   - runs the built-in `pass_value`
4. **tool `acknowledge`** — Sends the acknowledgement you wrote at once, even where the connection prepares its replies.
   - runs the built-in `reply_on_thread`
5. **tool `classify`** — Asks the reading model once which of the organization's labels fits the message.
   - runs the built-in `structured_answers`
6. **tool `put_label`** — Puts the label the model answered on the conversation.
   - runs the built-in `label_conversation`
7. **tool `to_people`** — Leaves the conversation waiting for a person, saying why.
   - runs the built-in `hand_to_person`
8. **tool `to_agent`** — Hands the message to the agent you chose, which answers or prepares its answer as the connection says.
   - runs the built-in `hand_to_agent`, only while `agent` has a value

## Its parameters

| Parameter | Kind | What it asks | Value |
|---|---|---|---|
| `connection` | connection | The connection Triage answers | required; fixed once installed |
| `agent` | agent | The agent that answers what is not for people — Leave it blank and every message goes to a person. | may be left blank; fixed once installed |
| `people_labels` | labels | The labels that go to people — A conversation with one of these labels waits for a person; none, and everything goes to the agent. | may be left blank |
| `acknowledgement` | text | Acknowledgement — Sent at once on the first message of each conversation; empty, nothing is sent. | default `""` |

## The labels it proposes

Created at install in the organization's vocabulary, as its own labels and never the recipe's: the client edits, leaves out or keeps its own label instead of each, and those kept that join fill `people_labels`.

| Label | What belongs under it | Joins |
|---|---|---|
| Sales | Wants to buy, asks for a price or a quote, or asks about a product or a service. | no |
| Support | Has a problem or a question with something they already use or bought. | no |
| Billing | Asks about an invoice, a charge, a payment or a refund. | yes |
| Complaint | Complains, is upset, or asks to speak to a person. | yes |

## How its data moves

The flow `triage`:

| Step | Input | Value | Comes from |
|---|---|---|---|
| `arrived` | `value` | `$ref:trigger.thread.interaction_id` | `thread.interaction_id` of what set the run off |
| `checked` | `value` | `$ref:trigger.text` | `text` of what set the run off |
| `answered` | `text` | `$ref:trigger.text` | `text` of what set the run off |
| `answered` | `messages` | `$ref:trigger.messages` | `messages` of what set the run off |
| `for_a_person` | `reason` | `Triage on this connection names no agent, so every message goes to a person.` | fixed |
| `read` | `text` | `$ref:trigger.text` | `text` of what set the run off |
| `sorted` | `value` | `$ref:trigger.thread.interaction_id` | `thread.interaction_id` of what set the run off |
| `labelled` | `add` | `["$ref:read.label"]` | a list of `label` of the step `read`'s answer |
| `acknowledged` | `text` | `${param.acknowledgement}` | replace with the value of the parameter `acknowledgement` |
| `for_people` | `reason` | `Triage put a label on this conversation that the client sends to people.` | fixed |

A value written `$ref:<step>.<path>` is what an earlier step answered, and `$ref:trigger.<path>` is what set the run off. A value with `${...}` in it is a placeholder: building it by hand, replace it with your own.

## Build it yourself

To install it as it is: `POST /api/v1/recipes/{key}/install` with the key `triage` and a value for each parameter. To build the same thing with your own particulars, make each part in this order -- each one may name the ones before it -- with the operations below.

The YAML under each part is the recipe's declaration, not a request body: the API takes other names for the same things (a tool's `builtin` is `source` and `config.builtin`, a step's `tool` is `tool_id`, an edge's `from` is `source_step_id`). [From a recipe to the API](/cookbook#from-a-recipe-to-the-api) on the lead page maps every field, kind by kind.

### 1. tool `first`

Passes on the conversation the message arrived on, for the flow to choose where it goes next.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: first
name: Triage on ${param.connection.name} — where the message arrived
says: Passes on the conversation the message arrived on, for the flow to choose where it goes
  next.
description: 'The step every message runs first, so the flow can branch on whether the conversation''s
  flow has run before. It is one more tool execution per message: every later message costs
  two, the hand-over and this, where a connection that "this agent answers" costs one.'
builtin: pass_value
```

### 2. tool `acknowledge`

Sends the acknowledgement you wrote at once, even where the connection prepares its replies.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: acknowledge
name: Triage on ${param.connection.name} — acknowledgement
says: Sends the acknowledgement you wrote at once, even where the connection prepares its
  replies.
builtin: reply_on_thread
```

### 3. tool `classify`

Asks the reading model once which of the organization's labels fits the message.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: classify
name: Triage on ${param.connection.name} — which label fits
says: Asks the reading model once which of the organization's labels fits the message.
builtin: structured_answers
config:
  fields:
  - key: label
    type: option
    options_from: labels
    description: Which of the organization's labels fits this message.
```

### 4. tool `put_label`

Puts the label the model answered on the conversation.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: put_label
name: Triage on ${param.connection.name} — put the label on
says: Puts the label the model answered on the conversation.
builtin: label_conversation
```

### 5. tool `to_people`

Leaves the conversation waiting for a person, saying why.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: to_people
name: Triage on ${param.connection.name} — to a person
says: Leaves the conversation waiting for a person, saying why.
builtin: hand_to_person
```

### 6. tool `to_agent`

Hands the message to the agent you chose, which answers or prepares its answer as the connection says.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: to_agent
name: Triage on ${param.connection.name} — to ${param.agent.name}
says: Hands the message to the agent you chose, which answers or prepares its answer as the
  connection says.
description: Hands what arrived on ${param.connection.name} to ${param.agent.name}.
builtin: hand_to_agent
config:
  agent_id: ${param.agent}
deadline_seconds: 120
when: ${param.agent}
```

### 7. flow `triage`

Sorts the first message of each conversation and hands each message to a person or to the agent.

- `POST /api/v1/flows` creates the flow.
- `POST /api/v1/flows/{flow_id}/steps` adds each step, naming the tool it runs.
- `POST /api/v1/flows/{flow_id}/edges` adds each edge.
- `PATCH /api/v1/flows/{flow_id}/entry-step` sets the step a run starts at.

```yaml
kind: flow
key: triage
name: Triage on ${param.connection.name}
says: Sorts the first message of each conversation and hands each message to a person or to
  the agent.
steps:
- key: arrived
  tool: ${resource.first}
  params:
    value: $ref:trigger.thread.interaction_id
- key: checked
  tool: ${resource.first}
  params:
    value: $ref:trigger.text
- key: read
  tool: ${resource.classify}
  params:
    text: $ref:trigger.text
- key: labelled
  tool: ${resource.put_label}
  params:
    add:
    - $ref:read.label
- key: sorted
  tool: ${resource.first}
  params:
    value: $ref:trigger.thread.interaction_id
- key: acknowledged
  tool: ${resource.acknowledge}
  params:
    text: ${param.acknowledgement}
  when: ${param.acknowledgement}
- key: for_people
  tool: ${resource.to_people}
  params:
    reason: Triage put a label on this conversation that the client sends to people.
  when: ${param.people_labels}
- key: answered
  tool: ${resource.to_agent}
  params:
    text: $ref:trigger.text
    messages: $ref:trigger.messages
  when: ${param.agent}
- key: for_a_person
  tool: ${resource.to_people}
  params:
    reason: Triage on this connection names no agent, so every message goes to a person.
  unless: ${param.agent}
edges:
- from: arrived
  to: checked
  condition:
    field: trigger.thread.is_first_run
    op: ===
    value: true
- from: arrived
  to: answered
- from: arrived
  to: for_a_person
- from: checked
  to: read
  condition:
    field: trigger.text
    op: '!=='
    value: ''
- from: checked
  to: sorted
- from: read
  to: labelled
  condition:
    field: read.label
    op: exists
- from: read
  to: sorted
- from: labelled
  to: sorted
- from: sorted
  to: acknowledged
- from: sorted
  to: for_people
  condition:
    field: read.label
    op: includes
    value: ${param.people_labels}
  when: ${param.people_labels}
  unless: ${param.acknowledgement}
- from: sorted
  to: answered
  unless: ${param.acknowledgement}
- from: sorted
  to: for_a_person
  unless: ${param.acknowledgement}
- from: acknowledged
  to: for_people
  condition:
    field: read.label
    op: includes
    value: ${param.people_labels}
  when: ${param.people_labels}
- from: acknowledged
  to: answered
- from: acknowledged
  to: for_a_person
```

### 8. thread_flow `answers`

Makes this triage the flow the connection answers each message with.

No public operation places a flow on a connection that already answers. The nearest by hand makes the connection's channel with the flow, which a connection already answered has to be made again for:

- `POST /api/v1/channels` makes the connection's channel, answered by the flow it names.

```yaml
kind: thread_flow
key: answers
name: Triage answers ${param.connection.name}
says: Makes this triage the flow the connection answers each message with.
connection: ${param.connection}
flow: ${resource.triage}
```

## How to adapt it

Choose the connection, the labels that go to people, the agent that answers the rest -- or none, and every message goes to a person -- and, if you want one, the acknowledgement sent at once. Tune what goes where by editing your labels and their lines, which are all the model reads. To build your own, keep its shape: a first step that runs on every message, a branch on whether the thread's flow has run before, the reading with the labels as its answers, the label put on, the acknowledgement after them, and a hand-over chosen by whether that label is one of a list.

## What cannot change once installed

Installed, every part is the recipe's: it is listed where its kind lives, marked as the recipe's, and refuses every edit and deletion by hand, naming the recipe.

- tool `first`: its configuration and fixed values.
- tool `acknowledge`: its configuration and fixed values.
- tool `classify`: its configuration and fixed values.
- tool `put_label`: its configuration and fixed values.
- tool `to_people`: its configuration and fixed values.
- tool `to_agent`: its configuration and fixed values.
- flow `triage`: its steps and edges.
- thread_flow `answers`: the connection it answers and the flow it runs there.

What stays the organization's:

- the values of `people_labels`, `acknowledgement`, changed on the installed recipe and written through to every part that uses them;
- not `connection`: the connection is fixed once installed, because it says which install this is -- answering another connection is installing the recipe there;
- not `agent`: the agent it names, or naming none, is fixed once installed -- answering the connection with another is uninstalling the recipe and installing it again;
- whether the recipe is on, which switches its automations on and off together;
- presentation -- a column's width, a step's position -- which changes nothing it runs.

## What it costs

What its parts consume -- a tool execution, a model's tokens, a message, storage -- is recorded and charged as those parts are, exactly as your own use of them is; nothing is charged for the recipe itself.
