mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
docs(chats): describe thread context, the follow setting and connector options
Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
2 files changed
+78
-2
No files matched your search
@@ -2228,6 +2228,8 @@ The manifest declares the capability. It needs no tool and no `service` flag:
|
||||
| `kinds[].page` | Optional. The add-on page that adds and edits bindings; it must be a declared page. The Connectors page links to it. |
|
||||
| `kinds[].drafts` | Optional. `true` when the add-on serves the op `draft`. The host then shows the live answer of a direct conversation as a draft instead of a working message. |
|
||||
| `kinds[].previewMs` | Optional. The shortest time between two previews (edits or drafts) of one binding, 250 to 10000 ms. Without it the host waits one second. |
|
||||
| `kinds[].history` | Optional, manifest `api` 2. `{"thread": true, "maxMessages": N}`: the add-on serves the op `history` for threads, and returns at most `maxMessages` (1 to 200; without it the host asks for 30). A kind without it is never asked, so it keeps the behaviour of a platform that cannot give old messages. |
|
||||
| `kinds[].options` | Optional, manifest `api` 2, at most 4. A choice that each binding of the kind makes: `{"id", "title", "description", "values": [{"id", "title"}], "default"}` with 2 to 8 values and a default among them. The host shows the choice on the binding page, checks the owner's value against the declaration, stores it, and sends the value in effect to the add-on in `options` of every `poll`. What the option means is the add-on's own rule. |
|
||||
|
||||
**Outbound: the connector route.** The host calls `POST /connector` on the add-on
|
||||
with the same bearer credential and incarnation header as every other route and a body
|
||||
@@ -2240,6 +2242,28 @@ reference of a message's `media`; the answer is `{"file": {"name", "mime", "data
|
||||
with at most 1 MiB of data) and, for a kind that declares `drafts`, `draft`
|
||||
(`chat`, `thread`, `draftId`, `text`).
|
||||
|
||||
- **Options.** A `poll` carries `options`, a map from each declared option id to the
|
||||
value in effect (the owner's choice, or the default). The host sends it with every
|
||||
poll, so a change reaches the add-on within one poll. The shared route gives it to the
|
||||
platform with `connector.OptionsFrom(ctx)`. The Slack add-on uses it for `followThreads`
|
||||
(`own`, `any` or `never`): the add-on decides which messages are `mention`, so the host
|
||||
only forwards what the add-on marks as addressed to the bot.
|
||||
- **The op `history`.** For a kind that declares `history`, the host calls
|
||||
`{"op": "history", "chat", "thread", "limit", "before"}` when a message in a thread
|
||||
makes a new chat, at most once for that chat. `limit` is the most messages to return
|
||||
(never more than `maxMessages`); `before` is the ID of the message the host handles
|
||||
now, which is not returned. The answer is `{"messages": [...], "truncated": bool}`, oldest
|
||||
first, the newest `limit` messages of the thread. A message is `{"messageId",
|
||||
"senderId", "senderName", "senderUsername", "text", "ts", "own", "media",
|
||||
"mediaNames"}`: `own` marks a message of the bot, `media` is the number of files and
|
||||
`mediaNames` at most 8 names; the bytes of a file are never part of a history.
|
||||
`truncated` says that older messages exist. The text is what people wrote: the host
|
||||
treats it as untrusted, flattens it, bounds it (30 messages and 8 KiB by default),
|
||||
and gives it to the first turn only. A failure or a `rate_limited` answer is
|
||||
logged and the turn goes on without the context; an add-on does not wait out a rate
|
||||
limit in this op. The add-on should read only the thread it is asked for. Core knows no
|
||||
platform: Slack's `conversations.replies` is the add-on's own business. The shared route
|
||||
serves the op for a platform that implements `connector.HistoryReader`.
|
||||
- A `send` with a `messageId` replaces that message of the bot (the host's working
|
||||
message) with the first part of the text and sends the rest as new messages. When
|
||||
the message cannot be edited (it was deleted, or is too old), the first part goes
|
||||
|
||||
@@ -173,8 +173,28 @@ curl -X POST .../api/chats/connectors -d '{"kind": "slack", "name": "Team app",
|
||||
- **A direct message** with the app is a conversation with its sender, like a Telegram
|
||||
chat. A reply in a thread of the direct message is a conversation of that thread.
|
||||
- **A mention** of the app in a channel is answered in the thread of that message. The
|
||||
thread is one chat, shared by everyone who writes in it, and the app follows it:
|
||||
a later reply in that thread reaches the agent without a new mention (for 24 hours).
|
||||
thread is one chat, shared by everyone who writes in it. Which threads the app then
|
||||
follows, so that a later reply reaches the agent without a new mention, is the
|
||||
setting **Threads the bot follows** (`followThreads` in `options`):
|
||||
- `own` (the default): the app follows the threads it started, that is, a mention
|
||||
outside a thread. A mention inside a thread that other people started is answered,
|
||||
and the thread is not followed, so the app does not answer what people write to
|
||||
each other.
|
||||
- `any`: the app also follows a thread that other people started, once it is
|
||||
mentioned in it.
|
||||
- `never`: every message needs a mention.
|
||||
|
||||
A followed thread stays followed for 24 hours after its last message. The add-on keeps
|
||||
the list in its data directory, so a restart of LocalAI or a new Socket Mode link does
|
||||
not make the app forget its threads. The file holds channel IDs and message
|
||||
timestamps only, never a token. The app does not call Slack for a message to find
|
||||
out whether it follows the thread.
|
||||
- **Earlier messages of the thread.** When a mention starts a new chat in a thread, the
|
||||
app reads the earlier messages of that thread once (see
|
||||
[Earlier messages of a thread](#earlier-messages-of-a-thread)). This needs the scopes
|
||||
`channels:history`, `groups:history`, `im:history` and `mpim:history`, which the
|
||||
manifest of the add-on page asks for. An app made with fewer scopes answers without
|
||||
that context; add the scopes and reinstall the app.
|
||||
- **Other channel messages** are not read.
|
||||
- **Answers** are converted from Markdown to Slack's `mrkdwn` (bold, italics, links,
|
||||
lists, code blocks) and split at 4,000 characters, the limit Slack asks for. A turn
|
||||
@@ -274,6 +294,33 @@ gives the same events without one.
|
||||
the server logs it. The binding stays on, so the agent answers again once you
|
||||
restore the folder or choose another one.
|
||||
|
||||
### Earlier messages of a thread
|
||||
|
||||
When the bot is mentioned in a thread, the people there often have talked for a while.
|
||||
For a platform that can give them (Slack; not Telegram, because a bot cannot read the
|
||||
history of a chat), LocalAI asks the add-on for the earlier messages of that thread when
|
||||
the mention makes a new chat, and gives them to the agent with the first message:
|
||||
|
||||
- **Only that thread.** The bot reads the messages of the thread in which it is
|
||||
mentioned, nothing else: not the channel, not other threads, not files. For a file it
|
||||
sees the name and the count. A mention outside a thread reads nothing.
|
||||
- **Once.** The messages are read when the chat of the thread starts. Later turns of the
|
||||
chat do not read them again, and they are not copied into the transcript.
|
||||
- **Bounded.** At most 30 messages and 8 KiB of text. If there are more, the newest are
|
||||
kept, oldest first, one line `Name: text` each. The add-on can lower the number of
|
||||
messages. A thread of more than 1,000 messages is not read at all.
|
||||
- **Untrusted.** The agent gets the lines in a block that says they are messages from
|
||||
other people and not instructions. Control characters and line breaks are removed and
|
||||
the characters `<` and `>` are replaced, so a message cannot close the block. Messages
|
||||
of the bot itself are included, so the agent sees its earlier answers.
|
||||
- **It never blocks the answer.** If the platform refuses, is slow or limits the calls,
|
||||
the agent answers without the context. The server logs the reason once.
|
||||
|
||||
To switch it off for a binding, turn off **Read the earlier messages of a thread** under
|
||||
**How it answers**, or send `"thread_context": false`. An update without `thread_context`
|
||||
keeps the stored value. The setting has no effect on a platform that cannot give
|
||||
earlier messages.
|
||||
|
||||
## How the bot answers
|
||||
|
||||
Each binding has three settings, under **How it answers** on the add-on page and in
|
||||
@@ -319,6 +366,11 @@ that part.
|
||||
| `window` | As `sender`, but a message that comes `window_minutes` (1 to 10,080) or more after the same person's previous message starts a new chat. A thread keeps its chat. |
|
||||
| `thread` | Each message starts a new chat. A reply to an answer of the bot, or to the message that started a chat, goes on in that chat; on Slack, so does a thread under either one. |
|
||||
|
||||
Some add-ons add settings of their own to a binding (for example Slack's **Threads the
|
||||
bot follows**). They appear under **How it answers**, and in the API as `options`, a
|
||||
map from the option id to a value. The add-on declares the allowed values, and an
|
||||
unknown option or value is a 400. An update without `options` keeps the stored values.
|
||||
|
||||
### Files the agent makes (`send_files`)
|
||||
|
||||
On by default. After the answer, the files that the turn wrote or changed go to the
|
||||
|
||||
Reference in new issue
Block a user