temetro is in beta and under active development. Expect things to change.
temetro

Chat agent

The AI chat endpoint — a tool-using agent over patient data.

The chat endpoint runs a tool-using AI agent over the clinic's patient data. It requires a signed-in user, an active clinic, and patient:read. It also honours the clinic's AI policy: if the assistant is disabled for the caller, POST /api/chat returns 403.

MethodPathAuthReturns
POST/api/chatpatient:readA streamed UI-message response (SSE)
GET/api/chat/threadspatient:readYour saved conversations
GET/api/chat/threads/{id}patient:readOne conversation + messages
PUT/api/chat/threads/{id}patient:readSave a conversation snapshot
DELETE/api/chat/threads/{id}patient:readDelete a conversation

Request

{
  "messages": [ /* AI SDK UI messages */ ],
  "model": "claude-sonnet-4-6",
  "effort": "medium",
  "mode": "analysis"
}

The model selects the provider too (e.g. a claude-* id routes to Anthropic, gpt-* to OpenAI, gemini-* to Gemini, the ollama sentinel to your local model). The matching provider key from your AI config is used. If no key is configured for the chosen provider, the request fails with a clear message.

The optional mode (chat | analysis | graph) is the clinician's chosen situation mode. It appends a short directive to the system prompt — analysis steers the assistant toward interpreting patterns across a patient's history, graph toward describing how their problems and visits connect (the UI also renders a record graph). chat (the default) adds nothing.

File attachments. Messages may include AI-SDK file parts (uploaded files). The server reads text-like files (CSV/JSON/TXT/…) into the prompt so the agent can parse them (e.g. a medications list to stock, or a database export to import); images and PDFs are passed through for vision-capable providers. In the UI these render as attachment chips, not raw text.

What the agent can do

The agent can display and add data — but never edits, deletes, or alters the database structure. Every add is a dry-run proposal that streams an approval card; the record is written only after the clinician approves, through the existing RBAC-gated REST endpoint (so an under-privileged role is rejected at commit).

Display (read):

  • getPatient — look up a patient by file number and render record cards.
  • getPatientLabs — pull labs + trend and render a lab chart with high/low flags.
  • searchPatients — find patients by name, then look one up.
  • listAppointments / listTasks / listPrescriptions — render the clinic's schedule, task queue, or prescriptions as list cards.
  • getClinicInfo — the clinic's name / basic info.
  • getAnalytics — clinic KPIs and earnings (billed/paid/outstanding, by month), rendered with an earnings chart.
  • listInventory — stock levels and low-stock items.

Add (propose → approve, nothing written until approved):

  • proposeAppointment / proposeTask / proposePrescription — validate a new record and show an approval card. On Add, the client commits via /api/appointments, /api/tasks, or /api/prescriptions.
  • proposeInventory — parse an uploaded stock/medications list (names, quantities, prices) into inventory items and show an approval card; on Add, commits via /api/inventory. Use this to stock inventory, vs. proposeInvoice which bills a patient.
  • proposeInvoice — parse an uploaded purchase/medication list into invoice line items and show an approval card; on Add, commits via /api/invoices (creating/linking a patient when needed).
  • previewImport — a dry run for migration (or a single add): validates records parsed from an uploaded export and shows an approval card. Nothing is written until the clinician approves and the client calls POST /api/ai/import.

All tools run under the caller's role scoping (a doctor only sees their own panel; reception sees demographics only) — identical to the patient routes.

Response

The endpoint streams an AI-SDK UI-message stream. Alongside the assistant's text it emits custom data parts the clinician's UI renders as rich cards: data-patientCard, data-labCard, data-importPreview, data-appointmentList, data-taskList, data-prescriptionList, data-inventoryList, data-clinicCard, data-analyticsCard, data-actionPreview (an add awaiting approval), data-step (a live Chain-of-Thought step), data-source (a citable record the model can reference), and a data-veilNotice flag.

Each retrieval tool also registers a PHI-free sourceId and emits a data-source part ({ id, title, kind }). The model cites facts inline with a [[src:id]] marker, which the UI renders as a numbered inline citation chip; a sources footer attributes the records when the model omits markers.

Conversations are persisted per user via the /api/chat/threads endpoints (the client saves a snapshot after each exchange and lists/opens them in the sidebar history).

These data parts carry the real record data straight to the clinician. On external providers the model itself only ever receives Veil-redacted results.

On this page