Assivy

Chat & threads

Turns, threads, feedback, memories, and their limits.

A chat is one agent turn on a thread, streamed back as it runs. Threads persist the conversation; feedback rates it; memories let the model remember across it.

Turns

POST /threads/chat runs one turn. Name the stored agent with agentId, or define one inline with an agent object — never both (400). An inline agent needs the agent:create permission.

FieldMeaning
inputRequired. The new messages: [{ role, parts: [{ type: "text", text }] }]. Roles are user or assistant; content is not read.
idThe thread id, client-minted and adopted by the server: 1–128 letters, digits, - or _. Omit to start a new thread.
modelOne of the agent's models. Anything else is a 400.
storefalse runs stateless: history is still read, never persisted. The editor's playground uses this.
toolsTools the user switched on in the composer. A hint to the model, not a filter — every configured tool stays available.
scope.folderIdsUp to 20 knowledge folders for this turn, intersected with the agent's own scope (never widened).
outputPer-turn format (text or json) and JSON Schema definition.
streamOmit for SSE. false returns one JSON body with only this turn's new messages and its text. An object { sendReasoning, sendSources } streams with reasoning (default off) and citation sources (default on).
metadataYour own string tags, stored on the thread: up to 16 keys (64 chars), 512-char values, 8 KB total.

Input messages merge onto stored history by id, so one array covers a new turn, a same-id retry, an approval resume, and a stateless run. New chats navigate to the id before the first write, so a 404 on prefetch means "not created yet", not an error. If the client disconnects mid-stream the loop aborts, but finish handling — persistence and cleanup — still runs.

The chat composer accepts images, text, JSON, PDF, Word, Excel, CSV, and Markdown files up to 10 MB each.

Rate limit. Turns are throttled per user — by default 30 a minute — and chat visitors also share 60 a minute per IP address. Over the limit is a 429 with Retry-After. API-key calls are limited per key instead.

Threads

RouteDoes
GET /threadsEvery thread you may see, newest first — the whole organization with agent:read, otherwise your own; chat visitors always see only their own. Summaries only, so paging stays cheap. Filters: agentId, userId (me for your own; someone else's needs agent:read), q, limit (default 50, max 200), skip.
POST /threadsCreate an empty thread on an agent (agentId, optional title up to 200 chars, metadata) to send the first message to later.
GET /threads/:idMessages plus feedback. Page messages with limit (1–500) and offset.
PATCH /threads/:idRename (title) or update metadata, which merges onto what's stored — the caps apply to the merged result.
DELETE /threads/:idRemove the thread.

Feedback

Thumbs up/down on an assistant reply, from any chat surface including the embedded widget. A negative rating needs a reason: up to 20 picker options (64 chars each) or custom text up to 500 characters. Re-rating overwrites. DELETE /threads/:id/feedback/:messageId withdraws a rating and is idempotent.

Feedback is stored as a human evaluation result, in the same collection the judges write to — so user ratings and evaluation runs read from one verdict store. One caveat: a rating past span retention fails loudly instead of recording a verdict with no evidence behind it.

Memories

Durable per-user facts the model writes for itself with the memory tool — a built-in you turn on per agent. Two tiers:

  • core — injected into every system prompt. Strictly personal: exact owner match, unowned entries reach nobody.
  • notes — retrieved on demand when relevant. Shared rows allowed.

There is no UI — memories are API-only (GET/POST /memories, GET/PATCH/DELETE /memories/:id). An entry has text (up to 8,000 chars), an optional title (up to 200), a tier (default notes), and an optional agentId — without one it is shared across the user's agents. The list filters by agentId and tier, and q switches it to retrieval. Reading needs agent:read; writing needs agent:update.

Reads never throw into a turn (empty on failure); duplicate text collapses by content hash; and if embedding fails the write still lands, reachable by the lexical lane. Retrieval is dense-first with lexical strictly as fallback — an empty dense result is an answer, not a trigger to try harder.

On this page