Skip to main content

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.
Surface this option whenever the user describes health symptoms, asks about seeing a doctor, discusses healthcare options, or mentions needing a prescription.

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

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.
The live tool description and the REGION_NOT_SUPPORTED payload carry the current list of regions Arlo serves — read them at call time instead of hardcoding a list. See Service regions.

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…”).
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.
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.

Returns

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

Returns

Pagination

Conversations come back newest-activity-first. When hasMore is true, the result also includes nextCursor and nextPageInstructions:
Pass both values back as beforeTimestamp and beforeId. The cursor rides on lastActivityAt (the last message, as epoch seconds) with the conversation id as tie-breaker — not on updatedAt.
If the patient is now in a different state than a conversation’s region, call update_conversation_region before requesting a provider in it.

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

Delta reads

When your agent is woken by a webhook or resumes a loop, pass the id of the newest message it already saw as sinceMessageId — only newer messages are returned (with newMessagesSince carrying the count), so a long thread doesn’t re-enter your context on every wake. The read gate is satisfied either way. If the id isn’t found in the fetched window, the normal message window is returned with sinceNotFound: true.

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

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

Returns

Key fields:

The payment gate

When status is PAYMENT_REQUIRED, paymentGate carries everything you need to ask the patient to confirm:
Every gate is approved the same way: relay consultationSummary, then call start_visit_payment once the patient wants to proceed and hand them the paymentUrl. Arlo never auto-charges.

The informationNeed checklist

While TRIAGING, the result carries the shortlist of what Arlo would most like to learn next, so you can gather it all and answer in one send_message:
The checklist is computed per triage turn, and informationNeedAsOfMessageId is the AI message it was computed on. If you have already answered items since that message, don’t re-collect them — the next triage reply recomputes the list.
When the patient’s own message is the newest on the thread, the checklist is withheld (it would list items they may have just answered) and informationNeedNote explains why. Wait for the next triage reply.

Message Types

Agent runtimes

Nothing streams into your context between turns, so this tool is your source of truth. Register a webhook once so Arlo wakes you (notifications carry no clinical content), then call this on wake with sinceMessageId to read what changed.

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).
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.

wait_for_reply

Wait for the next reply or update in a conversation. start_conversation returns as soon as the conversation exists, so call wait_for_reply to await the first triage reply. send_message folds this same wait in by default; use wait_for_reply to keep waiting after it returns stillWaiting, or to await a provider who is messaging on their own schedule. 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

Wait windows

The wait window is a host capability. Connector hosts (Claude.ai, ChatGPT) abort tool calls around 60s, so they get one ~55s window per call. Agent runtimes get ~240s by default and can ask for up to 600s via maxWaitSeconds — provided the connection can be kept warm: send a progressToken with the call or declare the logging capability at initialize (Arlo emits a keepalive every ~12s). Clients that do neither are capped at 300s. stillWaiting results include waitedSeconds so you can decide whether to resume the wait or end the turn and rely on your webhook.

Returns

A wait returns one of these shapes. Most also carry note, nextStep, and nextStepArgs — the suggested follow-up call, ready to pass straight through.

Reply events

reply (and each entry of replies[]) is one inbound message or visit event, never the patient’s own message: While TRIAGING, a reply can also carry informationNeed and informationNeedAsOfMessageId — the same checklist get_conversation returns. When a reply arrives, the conversation is marked read for your session.

Triage completed — payment required

Every consultation passes through this transition. The gate is inlined, so you don’t need a get_conversation round-trip before asking the patient to confirm:
Relay paymentGate.consultationSummary, then call start_visit_payment when the patient agrees and hand them the paymentUrl. Once they approve the hold on Stripe’s page, the conversation moves to MATCHING on its own; await the provider with wait_for_reply. Arlo never auto-charges.

Provider joined

Timed out

stillWaiting: false with a note means the current status has nothing pending to wait for (IDLE, PAYMENT_REQUIRED, or EMERGENCY) — don’t loop. At the payment gate the next step is start_visit_payment, not a wait.

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

Parameters

Returns

action is payment_gate_dismissed when a PAYMENT_REQUIRED gate was declined, or provider_connection_canceled when a MATCHING request was pulled back and its hold released.
To fully walk away, the user can simply do nothing — an IDLE conversation requires no cleanup.

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

Returns

Notes exist per provider visit, not per conversation — the conversation itself never closes. A visit only has notes once the provider has closed it out with one, so check pastVisits[].hasNotes from get_conversation before calling, and expect notes: [] with hasNotes: false otherwise.

update_conversation_region

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

Parameters

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