Chatbro
Leverandører
Seksjon med tittelen «Leverandører»| Leverandør | Protokollverdi | Transport | Områdetype |
|---|---|---|---|
| Slack | slack |
Socket Mode (utgående WSS) | slack |
Slack er den eneste leverandøren. ChatProvider er en enum med én verdi, og cc_server registrerer én plugin. Skjemaet, hvert oppslag og hver unik indeks er nøklet på provider, så id-er krysser aldri leverandører, og å legge til en er en endring bare på serversiden.
Én app på leverandørsiden per arbeidsområde × leverandør.
Chatkommandoer
Seksjon med tittelen «Chatkommandoer»Kommandonavnet er per app (cc som standard, altså /cc). En admin kan gi det nytt navn; broen bruker da det den sist ble kalt med.
| Kommando | Effekt |
|---|---|
/cc help (eller /cc uten verb) |
Lister opp hva boten kan gjøre |
/cc link <code> |
Løser inn en engangskode og knytter avsenderens chatidentitet |
/cc ticket <title> |
Oppretter en lokal sak rapportert av det knyttede medlemmet |
/cc ticket <title> | <description> |
Samme, med alt etter den første | som beskrivelse |
| Ukjent verb | Rapporterer det ukjente verbet pluss hjelpeteksten |
Måter å nå en agent på:
| Handling | Oppførsel |
|---|---|
@bot … i en kanal |
Åpner en Slack-tråd og et tilhørende Control Center-område; agenten svarer i Slack-tråden |
| Svar i en broet Slack-tråd | Fortsetter i samme Control Center-område — ingen omtale trengs |
| Vanlig melding i en kanal | Ignoreres (ikke adressert til boten og ikke i en broet Slack-tråd) |
| Direktemelding til boten | Ett Control Center-område per direktemeldingssamtale; setter en tittel på Slack-tråden og en «is thinking…»-status mens agenten arbeider |
Legitimasjonsfelt (Slack)
Seksjon med tittelen «Legitimasjonsfelt (Slack)»Erklært av leverandørens deskriptor, som er det som genererer kobledialogen og validerer innsendingen.
| Felt-id | Etikett | Påkrevd | Prefiks | Hvor den ligger |
|---|---|---|---|---|
botToken |
OAuth-token for botbrukeren | Ja | xoxb- |
OAuth & Permissions |
appToken |
App-nivå-token | Ja | xapp- |
Basic Information → App-Level Tokens, scope connections:write |
configRefreshToken |
Fornyelsestoken for appkonfigurasjon | Nei | xoxe |
App configuration tokens på api.slack.com/apps |
configRefreshToken er legitimasjonen for appadministrasjon: uten den virker tilkoblingen, men boten kan ikke opprettes eller redigeres fra Control Center. Den roterer ved hver bruk, og den roterte verdien lagres umiddelbart.
Verdier trimmes, udeklarerte nøkler forkastes, og et prefiksmismatch avvises med samme setning på klienten og serveren. Påkrevde felt må finnes ved hver tilkobling; et valgfritt felt som står tomt, beholder det som allerede er lagret.
Krav til Slack-appen
Seksjon med tittelen «Krav til Slack-appen»Scope for bottoken:
app_mentions:readassistant:writechannels:historychat:writecommandsgroups:historyim:historyusers:readusers:read.emailHendelsesabonnementer for boten:
app_home_openedapp_mentionmessage.channelsmessage.groupsmessage.imStrukturinnstillinger Control Center tvinger gjennom når den oppretter eller redigerer appen: Socket Mode aktivert, ingen request-URL, Messages-fanen aktivert og skrivbar, boten always_online, de påkrevde scope-ene og hendelsene slått sammen med det appen allerede har (aldri trukket fra) og én skråstrekkommando som bærer beskrivelsen File a ticket or link your Control Center account — markøren som identifiserer Control Centers egen kommando i et eksportert manifest.
Tilkoblingstilstander
Seksjon med tittelen «Tilkoblingstilstander»| Tilstand | Protokollverdi | Betydning |
|---|---|---|
| Ikke tilkoblet | disconnected |
Ingen legitimasjon lagret for dette arbeidsområdet × leverandøren |
| Kobler til… | connecting |
Legitimasjon lagret, transporten ringer ut eller ringer på nytt |
| Live | connected |
Transporten er oppe og mottar hendelser |
| Tilkoblingsfeil | error |
Lagret, men feiler; leverandørens egen feil vises ved siden av |
Gjenoppkobling skjer med eksponentiell backoff og jitter, begrenset til 30 sekunder. En leverandørinitiert socketrotasjon kobler til på nytt umiddelbart uten å trappe opp backoffen. En avvist legitimasjon (invalid_auth, not_authed, token_revoked, account_inactive, token_expired, invalid_app_id) eller et manglende scope er terminal: broen slutter å prøve på nytt til ny legitimasjon kommer.
Leverandørkapabiliteter (Slack)
Seksjon med tittelen «Leverandørkapabiliteter (Slack)»Broen er skrevet mot den rikeste flaten og nedgraderes én kapabilitet om gangen.
| Kapabilitet | Slack | Effekt når den mangler |
|---|---|---|
streaming |
ja | Hele svaret legges ut én gang, til slutt |
streamingRequiresThread |
ja | Et svarmål uten trådanpunkt legger ut hele svar |
ephemeralMessages |
ja | Et svar på en skråstrekkommando uten et brukbart svarhåndtak droppes (avvisninger legges alltid ut i tråden) |
threadStatus |
ja | Ingen forbigående «is thinking…»-linje |
threadTitle |
ja | Chattråden beholder standardtittelen |
slashCommands |
ja | Ingen /cc-flate |
taskCards |
ja | Bare tekst — ingen kort over svaret og ingen «View in Control Center»-lenke |
maxMessageLength |
39,000 | Lengre svar avkortes med en henvisning til Control Center |
maxStreamChunkLength |
3,800 | Innføyelser deles ved et avsnitt, en linje eller en ordgrense |
Å annonsere strømming er ikke å love strømming: Slacks krever funksjonen Agents & AI Apps på en betalt plan. En avvisning på kalltidspunktet (streaming_not_supported, feature_not_enabled, paid_only, …) huskes for hele tilkoblingens levetid og vises som streamingAvailable: false. Slacks oppgavekort følger samme kall, så en Slack som avviser kortets visningsmodus, beholder strømmen sin og mister bare kortet, én gang, for hele tilkoblingens levetid.
En strøm må også navngi leseren den er for. Slack krever både en mottakerbruker og teamet deres for å åpne en i en kanal (en direktemelding gjør det ikke) og avviser ellers med missing_recipient_user_id / missing_recipient_team_id — en avvisning per kall, så broen fortsetter å prøve, og turen kommer som ett samlet svar i mellomtiden. Mottakeren er den som spurte, hentet fra den innkommende meldingen (teamet deres, ikke appens, så en Slack Connect-kanal løses riktig opp). For en tur som ingen startet fra chatten — arbeid som er satt i gang i Control Center på en samtale som allerede er broet — er det medlemmet hvis knytning opprettet broen; hvis de siden har fjernet tilknytningen til chatkontoen sin, legges den turen ut i sin helhet i stedet for å strømmes.
Oppgavekort
Seksjon med tittelen «Oppgavekort»Ett gruppert kort per agenttur (task_display_mode: plan), med én rad per steg. Hver rad er en task_update med id + title + status, pluss en engangs-details når tanken er klar. details og output med samme id settes sammen uten skilletegn, så details sendes én gang, og output strømmes aldri. Planens tittel er forespørselen; svaret er en egen, senere innføyelse som bærer en markdown_text-blokk.
| Del | Innhold |
|---|---|
| Planens tittel | Det som ble spurt om |
| Oppsettrad | Working on it…, deretter Cloning …, deretter Starting the agent… — én rad, tittelen byttes ut |
| Tankerad | Thinking…, lagt til når agenten begynner å resonnere; tanken er denne radens details, sendt én gang når resonneringen er ferdig |
| Verktøyrader | Én per verktøy (Bash which swift), unik id så de står side om side |
| Status | Pågår mens raden kjører; fullført når neste rad starter eller turen avsluttes; feil for mislykket, avbrutt og turgrense |
| Oppfordring til handling | View in Control Center som en avsluttende rad når turen er ferdig — fraværende mens arbeidet fortsatt kjører, og fraværende når serveren ikke har noen tilgjengelig offentlig URL |
Det et kort aldri bærer: verktøyutdata, et argument utenfor den tillatelseslisten eller noe som er lest fra databasen. Resonneringsprosa er bare Thinking…-radens detaljer (begrenset til 256 tegn), ikke meldingskroppen. Et kort som ikke ville sagt noe nytt, sendes ikke på nytt. En omtale åpner strømmen umiddelbart så Slack-tråden ikke er stille; en tur som deretter ikke produserte noe tekst i det hele tatt, avslutter det samme kortet med en kort merknad i stedet for å legge ut en andre melding. En ordløs tur i et område som aldri åpnet en strøm (ingen kort, eller strømming allerede avvist), legger likevel ut én melding med det ferdige kortet og merknaden.
Strømmede og utlagte kort er ulike nyttelaster:
| Form | Struktur | Prosa |
|---|---|---|
| Strømmet | plan_update pluss task_update-biter nøklet på id |
Vanlig streng, begrenset til 256 tegn per bit |
| Utlagt | En plan-blokk som omslutter task_card-er nøklet på task_id |
Rik tekst |
Håndtering av feil:
| Situasjon | Oppførsel |
|---|---|
| Leverandøren avviser kortet på en innføyelse | Innføyelsen prøves på nytt umiddelbart uten det; prosaen kommer fortsatt live, og kort droppes for hele tilkoblingens levetid |
| Leverandøren avviser prosaen også | Strømmen lukkes, og svaret legges ut i sin helhet |
| Strømmen brytes etter at deler av svaret er kommet fram | Strømmen lukkes, og ingenting legges ut på nytt |
Se Chatbroer for hvorfor nyttelasten er delt opp slik.
Oppsett, før det finnes en tur
Seksjon med tittelen «Oppsett, før det finnes en tur»Kortet åpnes når en omtale godtas, før kloning og før det første tokenet; turen som følger, overtar samme kort og strøm. Fortellingen etter det kommer fra SpaceProvisioningChanged på domenehendelsesbussen — den samme framdriften skrivebordets provisjoneringsbanner leser fra områderaden.
| Provisjoneringstilstand | Fortelling |
|---|---|
| Omtale godtatt | Working on it… |
Steg repo |
Cloning <repo>… |
Steg prCheckout |
Checking out the pull request in <repo>… |
Steg script |
Running the setup script for <repo>… |
Steg agent |
Setting up <agent>… |
provisioning, ennå ikke noe steg |
Preparing the workspace… |
ready |
Starting the agent… |
| Agenten resonnerer | Thinking… |
failed |
Workspace setup failed — details are in Control Center. |
cancelled |
Workspace setup was stopped — details are in Control Center. |
Oppsettfortellingen krever alle fire vilkårene:
| Vilkår |
|---|
| Leverandøren rendrer kort |
| Strømming er tilgjengelig på denne tilkoblingen |
| Området har en chattforespørsel under behandling |
| Ingen kort rapporterer allerede om en tur der |
Forespørselen forblir under behandling til en tur starter eller oppsettet mislykkes. En ready-hendelse uten et allerede åpent kort er et varmt område og forblir stille, og provisjonering som ingen i chatten venter på — en samtale åpnet i appen, en strandet en som gjenopptas ved oppstart — produserer ikke noe kort i det hele tatt.
/open-siden som sender deg videre
Seksjon med tittelen «/open-siden som sender deg videre»Chatprodukter godtar http(s) i en lenke og ingenting annet, så en oppfordring til handling kan ikke navngi skrivebordsappens URL-skjema direkte.
| Egenskap | Verdi |
|---|---|
| Rute | GET /open/workspaces/<workspaceId>/(spaces|tickets)/<id> |
| Opphav | Utledet fra serverens offentlige URL (ws → http, wss → https); loopback beholdes |
| Svar | En liten no-store HTML-side som navigerer til control-center://workspaces/<workspaceId>/(spaces|tickets)/<id> og viser en manuell knapp |
| Validering | Id-er må samsvare med [A-Za-z0-9_.-]{1,128}; alt annet er en 404 |
| Tilgang | Offentlig og inert — den leser ingen database, så den er ikke et eksistensorakel; appen den åpner, gjør autorisasjonen |
Botprofilfelt
Seksjon med tittelen «Botprofilfelt»| Felt | Grense | Merknader |
|---|---|---|
appName |
1–35 tegn | Standardverdien er Control Center · <workspace name> |
botDisplayName |
1–80 tegn | Standardverdien er control-center |
description |
≤ 140 tegn | |
agentDescription |
≤ 300 tegn | Vises over en direktemelding med boten |
command |
≤ 32 tegn | Normaliseres: ledende skråstreker fjernes, gjøres om til små bokstaver, [^a-z0-9_-] fjernes, tom faller tilbake til cc |
agentEnabled |
— | Hvorvidt direktemelding-/agentopplevelsen eksponeres |
Et tomt felt betyr «la det stå», ikke «tøm det». Grensene er Slacks, som er de strammeste av produktene som er modellert.
Knytningskoder
Seksjon med tittelen «Knytningskoder»| Egenskap | Verdi |
|---|---|
| Lengde | 6 tegn |
| Alfabet | 23456789ABCDEFGHJKLMNPQRSTVWXYZ (ingen 0/O, 1/I, U) |
| Levetid | 15 minutter |
| Bruk | Én |
| Lagring | I minnet — en serveromstart ugyldiggjør utestående koder |
| Omfang | Ett arbeidsområde og én leverandør; å generere en ny kode ugyldiggjør medlemmets forrige |
Innløsning matches uten hensyn til store og små bokstaver. Ukjente, utløpte, fremmede arbeidsområders og feil leverandørs koder feiler alle likt med vilje.
Knytningsmetoder
Seksjon med tittelen «Knytningsmetoder»| Metode | Protokollverdi | Hvordan |
|---|---|---|
| Kode | code |
Medlemmet løste inn /cc link <code> |
| E-post | email |
Leverandørens verifiserte e-post samsvarte med en bruker som allerede er medlem av arbeidsområdet |
RPC-operasjoner
Seksjon med tittelen «RPC-operasjoner»Alle er knyttet til et arbeidsområde. Serveren er tilstandsløs, så hvert kall bærer sin egen workspace_id i args; dispatcheren avviser en arbeidsområdeskoperert operasjon som utelater den, før noen database åpnes. Legitimasjon går bare inn — statuslesinger returnerer den aldri.
| Operasjon | Type | Minste rolle | Handlingsklasser |
|---|---|---|---|
chat.providers |
read | guest |
— |
chat.status |
read | guest |
— |
chat.connect |
mutate | admin |
secretAccess, networkEgress |
chat.disconnect |
destructive | admin |
secretAccess |
chat.listUserLinks |
read | guest |
— |
chat.beginUserLink |
mutate | member |
— |
chat.unlinkUser |
mutate | member for deg selv, admin for alle andre |
— |
chat.createApp |
mutate | admin |
secretAccess, networkEgress |
chat.setupLink |
read | admin |
— |
chat.botProfile |
read | admin |
networkEgress |
chat.updateBotProfile |
mutate | admin |
networkEgress |
Leseoperasjoner arver guest-gulvet fra typen sin; mutasjoner uten et eksplisitt gulv krever member.
chat.setupLink setter sammen en URL for oppretting av leverandørapp fra botprofilen. Den erklærer ingen handlingsklasse fordi den leser ingen hemmelighet og ringer ingenting — bare brukerens egen nettleser gjør kallet.
Én reaktiv spørring fullfører flaten:
| Spørring | Type | Sender ut |
|---|---|---|
chat.watchUserLinks |
watch | Oversikten, sendt på nytt hver gang en knytning opprettes eller fjernes |
Den finnes fordi knytningen skjer på den andre siden: et medlem skriver engangskoden inn i boten, så ingen klientsvar kan bære svaret tilbake. Innstillingenes oversikt og den åpne «Knytt Slack-kontoen min»-dialogen følger begge denne, og dialogen bytter til en bekreftelse i det øyeblikket medlemmets egen knytning lander.
chat.beginUserLink genererer alltid en kode for den som kaller, sin egen identitet. chat.updateBotProfile returnerer en remaining_step bare når et steg gjenstår (typisk en nyinstallering); at den mangler, betyr at endringen er aktiv.
chat.providers returnerer én oppføring per tilbudt leverandør — deskriptoren pluss, når den finnes, tilkoblingsstatusen. Alt innstillingenes grensesnitt rendrer, kommer fra den nyttelasten, og det er derfor å legge til en leverandør er en endring bare på serversiden.
| Hva | Hvor |
|---|---|
| Tilkoblingslegitimasjon | <dataDir>/<workspaceId>/chat_credentials/<provider>.json |
| Halvferdig veiledet oppsett | <dataDir>/<workspaceId>/chat_credentials/<provider>_setup.json |
| Eldre Slack-filer | <dataDir>/<workspaceId>/slack_credentials.json og slack_app_setup.json, leses én gang og migreres på stedet |
Legitimasjon ligger ved siden av arbeidsområdets database, ikke inni den: å slette et arbeidsområde tar chattokenene med seg, og workspace.export eller en sikkerhetskopi kopierer workspace.db — så et arbeidsområde som gis videre til noen andre, bærer ingen levende bottokens. Skrivinger er atomiske (tempfil pluss omdøping) og strammes inn til kun eieren.
Databasetabeller
Seksjon med tittelen «Databasetabeller»Begge ligger i arbeidsområdedatabasen, som bærer en sammenslått v1-baseline — så en lesing på tvers av arbeidsområder kompilerer ikke.
chat_space_links — én ekstern samtale ↔ ett Control Center-område:
| Kolonne | Merknader |
|---|---|
id |
UUID v4 |
workspace_id |
Omfang: arbeidsområde |
provider |
ChatProvider.wire |
external_team_id |
Slack-team T…, tomt for leverandører uten begrepet |
external_channel_id |
Slack-kanal C…, gruppe G…, direktemelding D… |
external_thread_id |
Slack-trådanpunkt, eller null når hele samtalen er ankeret (botens direktemeldinger) |
cc_space_id |
REFERENCES spaces(id) ON DELETE CASCADE |
created_by_user_id, created_at, last_activity_at |
Unik på (workspace_id, provider, external_channel_id, external_thread_id), med en delvis indeks som håndhever det samme for null-tråd-id-er (SQLite behandler NULL-er som distinkte).
chat_user_links — ett eksternt medlem ↔ én Control Center-bruker:
| Kolonne | Merknader |
|---|---|
id |
UUID v4 |
workspace_id |
Omfang: arbeidsområde |
provider |
ChatProvider.wire |
external_team_id, external_user_id |
Slack-medlem U… |
user_id |
Control Center-bruker (global, så ingen fremmednøkkel) |
method |
code eller email |
linked_at |
Unik på (workspace_id, provider, external_team_id, external_user_id) og på (workspace_id, provider, user_id) — entydig tilskrivning i begge retninger, mens én person kan være knyttet hos flere leverandører.
En knytning er identitetsoppslag, ikke en tilgangstildeling: medlemskapet sjekkes på nytt for hver innkommende hendelse, så en knytning til et medlem som siden er fjernet, ender i en avvisning.
Områdetype og meldingsmetadata
Seksjon med tittelen «Områdetype og meldingsmetadata»Et broet område opprettes med leverandørens SpaceKind (slack). Det oppfører seg som et vanlig menneskevendt område — varslet og seksjonert som topic — og isExternalChat er sjekken all oppførsel (speiling, merking, oppbevaring) går gjennom.
Hver melding broen tar inn, bærer et metadata['chat']-stempel:
{ "chat": { "provider": "slack", "teamId": "T024BE7LD", "channelId": "C0G9QF9GW", "threadId": "1700000000.000100", "messageId": "1700000000.000200", "userId": "U024BE7LH", "userLabel": "sam" }}Stemplet er også ekkoveret: den utgående speilingen hopper over enhver melding som bærer det, og det er dette som hindrer en innkommende chatmelding i å bli lagt rett ut igjen.
Reléoppførsel
Seksjon med tittelen «Reléoppførsel»| Oppførsel | Detalj |
|---|---|
| Det som videresendes ut | Bare agentens tekst, pluss oppgavekortets statuslinje. Resonneringsprosa og verktøyutdata blir værende i Control Center |
| Strømmerytme | Begrenset til én tømming per sekund mens en tur kjører; kortet og teksten det forklarer, går i samme kall |
| Meldinger mennesker skriver i Control Center | Speiles til den tilknyttede tråden, med forfatterens visningsnavn som prefiks |
| Tomme turer | Rapporteres som en kort merknad (kjøringen mislyktes, ble avbrutt eller stoppet ved turgrensen) i stedet for stillhet |
| Deduplisering | Nøklet på leverandørens egen hendelses-id; de siste 512 huskes |
| Frontdør-agent | En ny broet samtale vekker arbeidsområdets CEO-agent, ellers den første agenten, ellers ingen |
| Navngiving av områder | #channel · <request> for en Slack-kanaltråd, Slack DM · <request> for en direktemelding, titler begrenset til 48 tegn |
| Feilisolering | Én dårlig hendelse tar aldri ned broen; tilkoblingen fortsetter å betjene hver andre samtale |
- Sett opp Slack-integrasjon
- Koble til Slack-kontoen din
- Tilpass chatboten
- Chatbroer
- Tillatelsesregler for handlingsklassene operasjonene erklærer