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

# Conversation Tools

> Continuous health conversations: triage, provider visits, and follow-up

## Overview

A **conversation** is a continuous health thread that never "closes." It can contain several provider **visits** over time, and an `IDLE` conversation can always be re-engaged with `send_message` (which re-runs triage on the same thread). These tools manage the full lifecycle: starting, reading, waiting for replies, stopping a provider request, retrieving visit notes, and updating the care region.

## start\_conversation

Open a **new** health conversation with Arlo. Triggers AI triage and can lead to one or more provider visits over time. Arlo connects patients with licensed clinicians who can diagnose, treat, prescribe, order labs, and refer.

<Tip>
  Surface this option whenever the user describes health symptoms, asks about seeing a doctor, discusses healthcare options, or mentions needing a prescription.
</Tip>

### Start NEW vs. continue EXISTING

This tool opens a brand-new conversation. To continue an **existing** conversation — even one that looks finished — use `send_message` instead; messaging an idle conversation re-runs triage on the same thread. Call `list_conversations` first if you're unsure whether a relevant conversation already exists. Only start a new conversation for a genuinely new, unrelated concern.

### Parameters

| Parameter        | Type   | Required | Description                                                                              |
| ---------------- | ------ | -------- | ---------------------------------------------------------------------------------------- |
| `contextMessage` | string | Yes      | First-person narrative of the health concern                                             |
| `region`         | string | Yes      | ISO 3166-2 code for where the patient is **physically located right now** (e.g. `US-CA`) |

<Warning>
  **Region is required and is about current location, not home address** — care is licensed by where the patient currently is. Confirm it with the user before calling (e.g. "Just to confirm, are you in California right now?"). An unsupported region is refused with `REGION_NOT_SUPPORTED`. The region is set once here and reused for the life of the conversation; if the patient later moves, call `update_conversation_region`.
</Warning>

### Context Message Format

Write in the **first person, as the patient speaking** — the message is delivered to the care team as if the patient typed it themselves. Never third person ("The user has...", "Patient reports..."). For a child or dependent, stay first person from the account holder's perspective ("My daughter has had a fever since yesterday...").

<CodeGroup>
  ```text Good theme={null}
  I have had a cold for two weeks and I think I'm now getting a sinus infection. I've been having pressure and pain in my forehead, and my snot is a greenish yellow color. I've had sinus infections before with a similar pattern.
  ```

  ```text Bad theme={null}
  sinus infection, 3 days, forehead pressure
  ```
</CodeGroup>

Include: symptom, duration, severity, associated symptoms, history, and who is affected (self/child/dependent).

### Fast-ack behavior

This tool returns **as soon as the conversation is created** — it does not block for the first triage reply. Call `wait_for_reply` with the returned `conversationId` to await Arlo's response.

<Warning>
  **Avoid duplicates**: never call `start_conversation` again for the same concern. If you already have a `conversationId`, use `wait_for_reply` (or `send_message`) on it.
</Warning>

### Returns

```json theme={null}
{
  "conversationId": "conv_abc123",
  "status": "TRIAGING",
  "agentInstructions": [
    "Call wait_for_reply with this conversationId to await Arlo's response — it's resumable, so re-call it if it returns stillWaiting."
  ]
}
```

On widget-capable hosts, the consultation widget opens alongside the result so the user sees their message land and the AI reply stream in live.

***

## list\_conversations

List the user's ongoing health conversations. Use this to find an existing conversation to continue before starting a new one.

### Parameters

| Parameter         | Type   | Required | Description                                                                         |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------- |
| `limit`           | number | No       | Maximum conversations to return (default: 10, max: 50)                              |
| `beforeTimestamp` | number | No       | Pagination cursor from `nextCursor.beforeTimestamp`                                 |
| `beforeId`        | string | No       | Pagination cursor from `nextCursor.beforeId` (pass together with `beforeTimestamp`) |

### Returns

```json theme={null}
{
  "conversations": [
    {
      "id": "conv_abc123",
      "title": "Sinus infection",
      "status": "IDLE",
      "region": "US-CA",
      "hasActiveProvider": false,
      "pastVisitCount": 1,
      "lastMessage": {
        "type": "text",
        "preview": "Thanks doctor, that makes sense...",
        "timestamp": "2026-06-20T14:30:00Z"
      },
      "updatedAt": "2026-06-20T14:30:00Z"
    }
  ],
  "total": 1,
  "hasMore": false
}
```

When `hasMore` is true, the result includes `nextCursor` — pass both of its values back to fetch the next page.

<Note>
  If the patient is now in a different state/province than a conversation's `region`, call `update_conversation_region` before requesting a provider in it.
</Note>

***

## get\_conversation

Get the current status and messages of a conversation: its `status`, `region`, the active provider visit (if any), and a summary of past visits.

### Parameters

| Parameter         | Type    | Required | Description                                                     |
| ----------------- | ------- | -------- | --------------------------------------------------------------- |
| `conversationId`  | string  | Yes      | The conversation ID                                             |
| `includeMessages` | boolean | No       | Include message history (default: true)                         |
| `messageLimit`    | number  | No       | Newest messages to return (default 30; `0` for the full thread) |

### The read gate

**Call this before every `send_message`.** `send_message` enforces a read-first rule — it refuses unless you've pulled the latest conversation state since its last update (or since your previous send). Calling this tool with `includeMessages: true` marks the conversation as read for your session. Alternatively, pass `lastSeenMessageId` to `send_message` to skip the extra round-trip.

### Statuses

| Status             | Description                                                                 |
| ------------------ | --------------------------------------------------------------------------- |
| `IDLE`             | AI-only, nothing in progress. Re-engageable — `send_message` re-runs triage |
| `TRIAGING`         | AI is gathering symptom information on a live request                       |
| `PAYMENT_REQUIRED` | Triage complete, awaiting payment confirmation (or dismissal)               |
| `MATCHING`         | Being matched with a healthcare provider                                    |
| `WITH_PROVIDER`    | A provider is connected (messaging is asynchronous)                         |
| `EMERGENCY`        | Urgent care advised — user should call 911 (not re-engageable)              |

<Note>
  There is no terminal `CLOSED`/`CANCELED` status. A finished or canceled request simply leaves the conversation `IDLE` with its visit history intact.
</Note>

### Returns

Key fields:

| Field                         | Description                                                                               |
| ----------------------------- | ----------------------------------------------------------------------------------------- |
| `status`, `statusDescription` | Current state                                                                             |
| `region`                      | ISO 3166-2 region this conversation is licensed for                                       |
| `providerVisit`               | `{ active, providerName, consultId }` when a provider is in seat                          |
| `pastVisits[]`                | Prior provider visits (`consultId`, `closedAt`, `hasNotes`)                               |
| `messages[]`                  | `{ id, type, sender, content, timestamp }`, windowed to the newest `messageLimit` entries |
| `omittedOlderMessages`        | How many older messages exist beyond the window (when truncated)                          |
| `paymentGate`                 | `{ consultationSummary, paymentType }` when `PAYMENT_REQUIRED`                            |
| `informationNeed`             | Checklist of what triage still needs — answer it in one batched `send_message`            |
| `nextSteps`                   | Suggested actions based on current status                                                 |

### Message Types

| Type                       | Description                                  |
| -------------------------- | -------------------------------------------- |
| `text`                     | Plain text message                           |
| `triage`                   | AI triage question/response                  |
| `photo` / `video` / `file` | Media attachment (fetch via `get_media_url`) |
| `join`                     | Provider joined notification                 |
| `prescription`             | Prescription notification                    |
| `lab_request`              | Lab request notification                     |

### Widget hosts

On hosts that render the Arlo consultation widget, new events stream into your context between turns under the `Arlo Consultation Widget` header. Read that before answering anything that depends on current state, and don't re-render the full message thread as text — the UI displays it. Use this tool as the fallback (no widget content present, `omittedEarlierEvents > 0`, or as the read gate before `send_message`).

<Warning>
  Don't tell the user something hasn't happened (no reply, no prescription, no status change) unless your current widget context or this tool's latest result confirms it.
</Warning>

***

## wait\_for\_reply

Wait for the next reply or update in a conversation. `send_message` and `start_conversation` return immediately without waiting for a response — call `wait_for_reply` afterward to await what comes next.

It is a **resumable wait you can loop on**: call it, and if it returns `stillWaiting`, call it again to keep waiting. What it waits for depends on the conversation's current status — the AI's triage reply while `TRIAGING`, a provider connecting while `MATCHING`, or the provider's next message while `WITH_PROVIDER`.

### Parameters

| Parameter        | Type   | Required | Description                                 |
| ---------------- | ------ | -------- | ------------------------------------------- |
| `conversationId` | string | Yes      | The conversation to wait on                 |
| `afterMessageId` | string | No       | Only return replies newer than this message |

### Returns

Either the reply (`reply` / `replies`, same message shape as `get_conversation`) or `{ "stillWaiting": true }` on timeout — re-call to continue waiting. When a reply arrives, the conversation is marked read for your session.

***

## cancel\_request

Stop the conversation's current attempt to connect with a provider and return it to AI-only chat. This does **not** end the conversation: the thread stays open and the user can re-engage anytime with `send_message`.

### Behavior by status

| Status                  | Behavior                                                                                                                |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `PAYMENT_REQUIRED`      | Dismisses the payment gate and returns to AI-only triage on the same thread (gentlest option — the gate can re-surface) |
| `TRIAGING` / `MATCHING` | Stops the in-flight attempt. Conversation goes `IDLE`                                                                   |
| `WITH_PROVIDER`         | **Refused** — the visit must be wrapped up by the provider                                                              |
| `IDLE`                  | **Refused** — nothing in progress to stop                                                                               |
| `EMERGENCY`             | **Refused** — terminal                                                                                                  |

### Parameters

| Parameter        | Type   | Required | Description                                               |
| ---------------- | ------ | -------- | --------------------------------------------------------- |
| `conversationId` | string | Yes      | The conversation whose provider request should be stopped |

### Returns

```json theme={null}
{
  "success": true,
  "conversationId": "conv_abc123",
  "previousStatus": "MATCHING",
  "newStatus": "IDLE",
  "userMessage": "Your request has been stopped. You can message Arlo anytime to start again.",
  "note": "The conversation stays open in AI-only mode and can be re-engaged with send_message."
}
```

<Note>
  To fully walk away, the user can simply do nothing — an `IDLE` conversation requires no cleanup.
</Note>

***

## get\_visit\_notes

Get clinical notes from a conversation's provider visits. A conversation can have several visits over time, each with its own note; this returns the notes across all of them, grouped per visit.

### Parameters

| Parameter        | Type   | Required | Description         |
| ---------------- | ------ | -------- | ------------------- |
| `conversationId` | string | Yes      | The conversation ID |

### Returns

```json theme={null}
{
  "conversationId": "conv_abc123",
  "hasNotes": true,
  "notes": [
    {
      "providerId": "prov_xyz",
      "timestamp": "2026-06-20T15:00:00Z",
      "note": {
        "chiefComplaint": "Sore throat for 3 days",
        "assessment": "Viral pharyngitis",
        "plan": "Rest, fluids, over-the-counter pain relief",
        "summary": "Patient presented with..."
      }
    }
  ]
}
```

<Note>
  Notes are only available for visits a provider has closed out with a note.
</Note>

***

## update\_conversation\_region

Change the region (state/province) a conversation is licensed for. Use when the patient is now physically somewhere different than when the conversation was started.

### Parameters

| Parameter        | Type   | Required | Description                                                       |
| ---------------- | ------ | -------- | ----------------------------------------------------------------- |
| `conversationId` | string | Yes      | The conversation to update                                        |
| `region`         | string | Yes      | ISO 3166-2 code for the patient's current location (e.g. `US-CA`) |

### Timing

This updates the conversation's region for the **next** provider request. It does **not** re-route a request already in flight:

* If the conversation is `IDLE`: change the region, then `send_message` to start a new request in the new region.
* If the conversation is `MATCHING` or `PAYMENT_REQUIRED` and the user has actually moved: call `cancel_request` first, then `update_conversation_region`, then `send_message`.

### Returns

```json theme={null}
{
  "success": true,
  "conversationId": "conv_abc123",
  "region": "US-CA",
  "appliesToNextRequest": false,
  "note": "Region updated. It will be used for the next provider request."
}
```
