Bots und interaktive Nachrichten

Ein Bot-Konto ist ein Benutzerkonto, das für ein Programm erstellt wurde. Es hat einen eigenen Namen, ein eigenes Bild und eigene Tokens und zeigt neben dem Namen ein BOT-Tag an. Diese Seite behandelt auch KI-Agenten, die Sie selbst ausführen, sowie die interaktiven Teile von Nachrichten: Schaltflächen, Menüs und Dialoge, die von jeder Integration verwendet werden können.

Warum ein Bot-Konto

  • Seine Nachrichten stammen von einer klaren Identität mit dem Kennzeichen BOT, anstatt vom Konto einer Kollegin oder eines Kollegen.
  • Seine Tokens funktionieren weiter, wenn die Person, die es eingerichtet hat, ihre Rolle wechselt oder das Unternehmen verlässt (außer der Server deaktiviert die Bots inaktiver Besitzer, siehe unten).
  • Bots können sich nicht mit einem Passwort anmelden und sehen die Web-App nie.

Apps erstellen ihre eigenen Bots, wie z. B. die Todo- oder Playbooks-Bots, über die Plugin-API (EnsureBotUser). KI-Agenten sind ebenfalls Bot-Konten einer eigenen Art, die mit einem AGENT-Tag angezeigt werden: siehe Agenten.

Bot-Konten aktivieren

Ein Systemadministrator aktiviert Aktiviere Bot-Kontoerstellung in Systemkonsole › Integrationen › Bot-Konten (ServiceSettings.EnableBotAccountCreation, AM_SERVICESETTINGS_ENABLEBOTACCOUNTCREATION). Standardmäßig ist es deaktiviert. Nur Systemadministratoren können Bots erstellen, es sei denn, sie gewähren diese Berechtigung in den Einstellung für Berechtigungen auch anderen Rollen.

Auf derselben Seite deaktiviert Deaktiviere Bot-Konten, wenn der Besitzer deaktiviert ist (ServiceSettings.DisableBotsWhenOwnerIsDeactivated, standardmäßig aktiv) einen Bot, wenn das Konto seines Besitzers deaktiviert wird.

Einen Bot erstellen

  1. Öffnen Sie das Community-Menü, dann Teameinstellungen, klicken Sie am Ende der Registerkarten auf Integrationen, dann auf Bot-Konten und Bot-Konto hinzufügen.
  2. Geben Sie einen Benutzernamen (Kleinbuchstaben, Zahlen, Punkte, Bindestriche und Unterstriche) sowie optional ein Bot-Symbol, einen Anzeigenamen und eine Beschreibung ein.
  3. Wählen Sie die Rolle: Mitglied oder Systemadministrator für einen Bot, der den Server verwaltet. Vergeben Sie einem Bot nur die Berechtigungen, die er wirklich benötigt.
  4. Aktivieren Sie post:channels, damit er in jedem öffentlichen Kanal posten kann, oder post:all, damit er in jedem Kanal, einschließlich privater Kanäle und Direktnachrichten, posten kann, ohne Mitglied zu sein.
  5. Legen Sie fest, wann sein Standard-Token abläuft, und wählen Sie dann Bot-Konto erstellen.
  6. Kopieren Sie das angezeigte Zugriffstoken. Es wird nicht erneut angezeigt.

Später fügt Neues Token erstellen in der Zeile des Bots ein Token hinzu, und jedes Token kann deaktiviert oder gelöscht werden. Bot-Tokens funktionieren, auch wenn persönliche Zugriffstokens für Personen deaktiviert sind.

Ein Bot kann Server-Attribute tragen (die in Systemkonsole › System-Attribute eingerichteten), die im Formular zum Hinzufügen/Bearbeiten des Bots oder über Attribute bearbeiten … im ⋯-Menü des Bots festgelegt werden. Wer den Bot verwaltet, legt sie fest: sein Besitzer mit der Berechtigung „Bots verwalten“ oder jeder mit der Berechtigung „Bots anderer verwalten“; ein von einem Administrator verwaltetes Attribut erfordert weiterhin einen Systemadministrator. Das Bot-Konto eines KI-Agenten gehört niemandem, daher können nur Personen mit der Berechtigung „Bots anderer verwalten“ oder ein Systemadministrator seine Attribute festlegen.

Über die API:

# create the bot (you become its owner)
curl -X POST https://chat.example.com/api/v4/bots \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"username": "deploy-bot", "display_name": "Deploy", "description": "Posts deployments"}'

# give it a token
curl -X POST https://chat.example.com/api/v4/users/$BOT_USER_ID/tokens \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"description": "deploy pipeline"}'

Von der Kommandozeile aus, angemeldet als Administrator (nicht im lokalen Modus): amctl bot create deploy-bot --display-name Deploy --with-token --expires-in 90d. Weitere Endpunkte: GET /api/v4/bots, PUT /api/v4/bots/{bot_user_id}, POST /api/v4/bots/{bot_user_id}/disable und /enable, sowie POST /api/v4/bots/{bot_user_id}/assign/{user_id}, um den Besitzer zu ändern.

Den Bot Communities und Kanälen hinzufügen

Ein neuer Bot gehört zu keiner Community. Fügen Sie ihn wie eine Person hinzu, über die Mitgliederverwaltung der Community oder über die API:

curl -X POST https://chat.example.com/api/v4/teams/$TEAM_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"team_id": "'$TEAM_ID'", "user_id": "'$BOT_USER_ID'"}'

curl -X POST https://chat.example.com/api/v4/channels/$CHANNEL_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"user_id": "'$BOT_USER_ID'"}'

Ein Bot mit post:channels oder post:all kann posten, ohne Mitglied zu sein, erhält aber nur WebSocket-Ereignisse für die Kanäle, in denen er sich befindet.

Als Bot posten

Verwenden Sie das Token des Bots für jeden API-Aufruf; POST /api/v4/posts ist der häufigste (siehe Hauptressourcen). Um jemandem direkt zu schreiben, öffnen Sie zuerst den Direktnachrichten-Kanal:

# returns the channel; use its "id" as channel_id
curl -X POST https://chat.example.com/api/v4/channels/direct \
  -H "Authorization: Bearer $BOT_TOKEN" -H 'Content-Type: application/json' \
  -d '["'$BOT_USER_ID'", "'$USER_ID'"]'

Um auf das zu reagieren, was Menschen sagen, folgen Sie dem WebSocket mit dem Token des Bots und beantworten Sie die posted-Ereignisse, die Sie interessieren. Ignorieren Sie die eigenen Nachrichten des Bots, um Schleifen zu vermeiden.

Eine Nachricht, die nur eine Person sehen kann (eine ephemere Nachricht), wird mit POST /api/v4/posts/ephemeral und {"user_id", "post": {"channel_id", "message"}} gesendet. Dafür wird die Berechtigung create_post_ephemeral benötigt, die standardmäßig nur Systemadministratoren haben. Integrationen senden ephemere Nachrichten in der Regel als Antwort auf Slash-Befehle und Schaltflächen.

Agenten

Ein Agent ist ein Bot-Konto der Art agent: Benutzer haben "is_agent": true, Bots "kind": "agent", und die Oberfläche zeigt ein AGENT-Tag anstelle von BOT. Agenten werden nur von Systemadministratoren (serverweite Agenten) in Systemkonsole › KI › Modellverbindungen und von Community-Administratoren (die ihrer Community) im KI-Tab der Community-Einstellungen oder über /api/v4/ai/agents erstellt (siehe die API). Ein Bot, der mit POST /bots oder von einer App erstellt wird, ist immer ein einfacher Bot.

Ein integrierter Agent wird vom Server beantwortet, mit einer Modellverbindung. Ein externer Agent ist von Ihnen auszuführen: ein Programm an anderer Stelle (z. B. ein Coding-Agent auf einem Projekt), das sich als der Agent anmeldet und wie eine Person antwortet. Antimatter antwortet nicht für ihn.

Der Status eines integrierten Agenten wird vom Server festgelegt: Online, solange die Modellverbindung antwortet, Abwesend, wenn sie nicht antwortet (Ausfall, Timeout, abgelehnter Schlüssel), und Offline, wenn der Agent deaktiviert ist oder keine nutzbare Verbindung bzw. kein Modell vorhanden ist. Der Status wird überprüft, wenn sich der Agent oder seine Verbindung ändert, wenn eine Verbindung getestet wird, bei jedem Modellaufruf des Agenten und alle 10 Minuten. Niemand kann den Status eines integrierten Agenten festlegen: PUT /users/{id}/status und die Endpunkte für den benutzerdefinierten Status antworten mit 403 (api.status.agent.app_error), auch für Systemadministratoren, und die Plugin-API-Funktionen UpdateUserStatus, SetUserStatusTimedDND, UpdateUserCustomStatus und RemoveUserCustomStatus lehnen dies ebenfalls ab. Der Status eines externen Agenten richtet sich stattdessen nach seiner eigenen Verbindung, und nur sein eigenes Token kann ihn ändern.

Externen Agenten ausführen

  1. Ein Administrator fügt den Agenten in der Systemkonsole › KI › Modellverbindungen (oder im KI-Tab einer Community) hinzu, wählt die Art Externer Agent und legt fest, wer mit ihm kommunizieren darf. Die Seite zeigt anschließend an, wie die Verbindung hergestellt wird.
  2. Weisen Sie ihm ein Token zu: Ein Systemadministrator öffnet Integrationen › Bot-Konten, sucht das Konto des Agenten und wählt Neues Token erstellen, oder ruft die Token-API mit der Benutzer-ID des Agenten auf:
    curl -X POST https://chat.example.com/api/v4/users/$AGENT_USER_ID/tokens \
      -H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
      -d '{"description": "agent"}'
  3. Das Programm ruft die API auf und öffnet das WebSocket mit Authorization: Bearer <token>, liest seine Erwähnungen und Direktnachrichten aus den posted-Ereignissen und antwortet über POST /posts im Thread der Nachricht.
  4. Es zeigt den Benutzern, was es tut, indem es seine Aktivität festlegt:
    curl -X PUT https://chat.example.com/api/v4/ai/agents/$AGENT_USER_ID/activity \
      -H "Authorization: Bearer $AGENT_TOKEN" -H 'Content-Type: application/json' \
      -d '{"state": "working", "text": "Running the tests", "thread_post_id": "'$ROOT_ID'"}'

Die ID des Agenten in diesen Pfaden ist seine Benutzer-ID. Halten Sie das Token geheim: Jeder, der es besitzt, kann als Agent posten.

Aktivität

  • state: idle, thinking, working, waiting (auf jemanden), blocked oder offline. Die Beschäftigungsstatus (thinking, working, waiting, blocked) wechseln nach expires_in_seconds zurück zu idle: standardmäßig nach 10 Minuten, maximal nach 24 Stunden.
  • text: einige Worte zur Aufgabe, eine Zeile mit maximal 200 Zeichen. Die Oberfläche zeigt diesen Text in der Mitgliederliste und auf der Profil-Karte an.
  • thread_post_id: der Thread, in dem der Agent arbeitet, den das Programm lesen können muss. Er wird nur an Personen übermittelt, die ihn lesen dürfen.

Wer kann sehen, dass der Agent seine Aktivitäten lesen kann (GET /ai/agents/{agent_id}/activity oder POST /ai/agents/activity/ids mit einer Liste von IDs) und das agent_activity_changed-WebSocket-Ereignis empfängt, ohne den Thread. Integrierte Agents legen ihre Aktivitäten selbst fest.

Während ein integrierter Agent seine Antwort schreibt, sendet der Server den wachsenden Text in agent_post_stream-Ereignissen an den Kanal: post_id, channel_id, root_id, user_id, message (der bisherige Text) und control (start, text, end, error oder cancel). Ein post_edited-Ereignis enthält die finale Nachricht. Clients, die den Stream ignorieren, sehen die Antwort erst, wenn sie gespeichert ist.

Interaktive Nachrichten: Schaltflächen und Menüs

Jede Nachricht mit Anhängen kann Aktionen enthalten: Schaltflächen und Menüs zur Auswahl. Sie funktionieren in Nachrichten, die über die API, Webhooks und als Antwort auf Slash-Befehle gepostet werden. Wenn jemand eine davon verwendet, ruft Antimatter die URL Ihrer Integration auf.

{
  "channel_id": "…",
  "message": "Deploy **api 2.4.0** to production?",
  "props": {
    "attachments": [{
      "actions": [
        {
          "id": "approve",
          "type": "button",
          "name": "Approve",
          "style": "primary",
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "approve"}}
        },
        {
          "id": "env",
          "type": "select",
          "name": "Pick an environment",
          "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}],
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "env"}}
        }
      ]
    }]
  }
}
  • type: button oder select.
  • id: Buchstaben, Zahlen, Bindestriche und Unterstriche, für jede Aktion der Nachricht unterschiedlich. Wenn Sie sie weglassen, wird sie generiert.
  • style (Schaltflächen): default, primary, success, good, warning, danger oder eine hexadezimale Farbe.
  • options (Menüs) oder data_source: users oder channels, um eine Person oder einen Kanal auszuwählen. default_option wählt einen Wert vor.
  • integration.url: Der Ort, an den der Klick gesendet wird. Eine App (Plugin) kann einen eigenen Pfad verwenden, z. B. /plugins/com.example.deploy/actions. integration.context gehört Ihnen: Er wird mit dem Klick zurückgesendet und ist für Clients unsichtbar.

Die Anfrage, die Ihre Integration erhält

{
  "user_id": "…",
  "user_name": "priya",
  "channel_id": "…",
  "channel_name": "releases",
  "team_id": "…",
  "team_domain": "lumen-labs",
  "post_id": "…",
  "trigger_id": "…",
  "type": "button",
  "context": {"release": "2.4.0", "action": "approve"}
}

Für ein Menü ist type gleich select und context.selected_option enthält den gewählten Wert.

Ihre Antwort

{
  "update": {"message": "Deploy of **api 2.4.0** approved by @priya", "props": {}},
  "ephemeral_text": "Done. The deploy starts in a minute."
}
  • update: Ersetzt den Text und die Eigenschaften der Nachricht, z. B. um die Schaltflächen nach der Verwendung zu entfernen (ein leeres props).
  • ephemeral_text: Eine Nachricht, die nur die Person sieht, die geklickt hat.
  • goto_location: Eine URL, die geöffnet wird.
  • Ein leerer Body ändert nichts.

Der Server wartet so lange, wie es die Zeitüberschreitung der Integrationsanfrage zulässt (standardmäßig 30 Sekunden). Integrations-URLs auf privaten Netzwerkadressen müssen von einem Systemadministrator freigegeben werden, wie bei Webhooks.

Dialoge

Ein Dialog ist ein Formular, das über dem Chat geöffnet wird. Sie können ihn nur als Antwort auf etwas öffnen, das die Person gerade getan hat, z. B. einen Slash-Befehl oder eine Schaltfläche, da dafür die trigger_id dieser Anfrage benötigt wird. Die trigger_id ist so lange gültig, wie die Zeitüberschreitung der Integrationsanfrage.

curl -X POST https://chat.example.com/api/v4/actions/dialogs/open \
  -H 'Content-Type: application/json' \
  -d '{
    "trigger_id": "'$TRIGGER_ID'",
    "url": "https://deploy.example.com/dialog",
    "dialog": {
      "callback_id": "new-release",
      "title": "New release",
      "introduction_text": "Fill in the release details.",
      "submit_label": "Create",
      "notify_on_cancel": false,
      "state": "anything you want back",
      "elements": [
        {"display_name": "Version", "name": "version", "type": "text", "placeholder": "2.4.0"},
        {"display_name": "Notes", "name": "notes", "type": "textarea", "optional": true},
        {"display_name": "Environment", "name": "env", "type": "select",
         "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}]},
        {"display_name": "Owner", "name": "owner", "type": "select", "data_source": "users"},
        {"display_name": "Notify the channel", "name": "notify", "type": "bool", "default": "true"}
      ]
    }
  }'
ElementtypWas es anzeigt
textEin einzeiliges Feld. subtype: text, email, number, password, tel oder url. min_length und max_length begrenzen es.
textareaEin mehrzeiliges Feld.
selectEine Liste: options, oder data_source users, channels, oder dynamic mit einer data_source_url. multiselect erlaubt mehrere Werte.
boolEin Kontrollkästchen.
radioEine Auswahl aus options.
date, datetimeEin Datum oder ein Datum und eine Uhrzeit.
action_buttonEine Schaltfläche, die action_button_url unabhängig vom Absenden des Dialogs aufruft. Ihr help_text wird darunter angezeigt.
collapsibleEine ausklappbare Gruppe von Elementen. Mit sub_type: "grid" werden die untergeordneten Container als Tabelle statt als Stapel angeordnet: Jeder Container ist eine Zeile, und seine eigenen Elemente sind die Zellen dieser Zeile.

Jedes Element akzeptiert display_name, name, help_text, placeholder, default und optional.

submit_buttons im Dialog benennt ein statisches select-Element: Dessen Optionen werden zu den Absenden-Schaltflächen des Dialogs, eine pro Option, anstelle einer einzelnen Absenden-Schaltfläche, und das select-Element selbst wird nicht angezeigt. size ("small", "medium" oder "large"; "small", wenn nicht angegeben) fordert einen breiteren Dialog an. refresh_on_return (erfordert source_url) ruft den Dialog von source_url erneut ab, sobald ein darüber geöffneter Dialog geschlossen wird, damit er die Änderungen anzeigen kann. Ein nicht erkannter size oder sub_type verhindert nicht das Öffnen des Dialogs: Es wird auf den Standardwert zurückgefallen, und der Server protokolliert dies nur.

Wenn die Person absendet, sendet Antimatter eine POST-Anfrage an die url des Dialogs:

{
  "type": "dialog_submission",
  "callback_id": "new-release",
  "state": "anything you want back",
  "user_id": "…",
  "channel_id": "…",
  "team_id": "…",
  "submission": {"version": "2.4.0", "notes": "", "env": "staging", "owner": "…", "notify": true},
  "cancelled": false
}

Antworten Sie mit einem leeren Body, um den Dialog zu schließen, oder lassen Sie ihn offen und zeigen Sie, was falsch ist:

{"errors": {"version": "This version already exists."}}

{"error": "…"} zeigt eine Nachricht für das gesamte Formular an. Mit notify_on_cancel sendet das Schließen des Dialogs "cancelled": true. Dialoge funktionieren in Apps auf die gleiche Weise: Die OpenInteractiveDialog-Methode der Plugin-API akzeptiert dieselbe Anfrage.