Skip to content
DaneshyarDocs
Sign in
  • Introduction
  • Quickstart
  • API keys
  • Authentication
  • Apps, workspaces, resources
  • Ingestion
  • Chat and sessions
  • Citations
  • Skills
  • Conventions
  • Workspaces
  • Resources
  • Chat
  • Skills
  • Errors
  • Customer support assistant
  • Internal knowledge base
  • Documentation chatbot
  • Embedded widgetOn the roadmap: Soon
  • TypeScript SDKOn the roadmap: Soon
  1. Docs
  2. Concepts
  3. Chat and sessions

Chat and sessions

How threads are stored, how end users are separated, and how retrieval picks passages.

Every question runs against one workspace, for one of your end users, inside a thread the server stores.

Sessions

A session is a thread. Omit session_id and the server creates one, titling it from your first message; pass it back and the conversation continues with the last twenty turns as context.

Sessions are stored server-side and survive anything on your end. You do not need to keep transcripts yourself — though you may want to, since the list endpoints are the only way to read them back.

cURL
JavaScript
Python
curl -X POST "https://api.daneshyar.info/api/v1/workspaces/8f14e45f-ceea-467a-9f4c-1a2b3c4d5e6f/chat/" \
  -H "X-API-Key: dk_live_9f3aC2xQ7mB1vT8sE4nK6pR0jY5wZ2hL" \
  -H "Content-Type: application/json" \
  -d '{
    "external_user_id": "user_4821",
    "session_id": "b6d2e1a4-77c3-4f59-9a10-2e8d6c4b0f37",
    "message": "And for patients over 70?"
  }'

Separating your end users

external_user_id is your identifier for whoever is asking. It is required on every call, and it is what keeps your end users apart despite sharing one API key.

Use a stable identifier from your own system — a user id, not an email or a session cookie. If it changes, that person loses their history. If two people share one, they see each other's.

Nothing validates it. Sending the same value for every user silently merges all of their conversations into one thread, and the model will answer with another person's context in view.

How retrieval works

When a question arrives, the server embeds it and finds the closest passages across the workspace's ready resources by vector similarity, then answers from those passages plus recent conversation history.

  • By default it retrieves the five closest passages across the whole workspace.
  • Pass resource_ids and retrieval is both forced and widened — about fifteen passages, plus a few from each named resource so a document is represented even when it isn't the closest match.
  • A workspace with no ready resources answers from general knowledge instead, without citations. That is the one case where an answer is not grounded in your documents.
There is no relevance threshold. A workspace with ready resources always retrieves something, even for a greeting — so an answer having citations does not by itself mean the question was on-topic.

When the answer is a form

Sometimes the model needs input before it can answer usefully. Instead of guessing, it returns response.type of form with a set of fields to collect.

Example
{
  "status": "ok",
  "data": {
    "assistant_message": {
      "role": "assistant",
      "content": "Which department should I answer for?",
      "response": {
        "type": "form",
        "parts": [{ "text": "Which department should I answer for?", "source": null }],
        "form": {
          "title": "Narrow the question",
          "fields": [
            {
              "name": "department",
              "label": "Department",
              "type": "select",
              "required": true,
              "options": ["Cardiology", "Neurology", "Oncology"]
            }
          ]
        }
      }
    }
  }
}

Each field has a name, a label, a type and a required flag, and may carry a placeholder and options. The types are text, textarea, number, select, checkbox, radio, date and email.

One subtlety: a checkbox field with options is a multi-select group, and the same field without options is a single yes/no toggle. Branch on whether options is present.

There is no endpoint for submitting form answers. Collect them, format them as text, and send them back as an ordinary follow-up message in the same session.
PreviousIngestionNextCitations

On this page

  • Sessions
  • Separating your end users
  • How retrieval works
  • When the answer is a form

Every example on this site runs against the live API. If one doesn't, tell us — that's a bug in the docs.

ServicesAboutTalk to us