synops/docs/infra/robusthet.md
vegard fd0b75ee13 Orkestrering: tre nivåer (script/fritekst/drøm) + rename portvokter→vaktmester
Orkestrering restrukturert med deklarativt script som primærnivå:
- Nivå 1: eksakte CLI-kall med {event.*}-variabler, ingen AI
- Nivå 2: fritekst tolket av bot med function calling
- Nivå 3: drømmemodus — bruker skriver fritt, mangler→work_items
- Auto-eskalering: script→bot ved uventet feil

Rename portvokter→vaktmester i alle docs — bedre navn for en
tjeneste som gjør ting, ikke bare sjekker legitimasjon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:59:29 +00:00

4.6 KiB

Robusthet og fallback

Lagmodell

Lag 1: LLM-leverandør (Claude API, OpenAI, etc.)  → utenfor vår kontroll
Lag 2: LiteLLM (AI Gateway)                        → lokal Docker
Lag 3: Vaktmesteren                                 → lokal native (systemd)
Lag 4: CLI-verktøy (synops-*)                       → per-kall, isolert
Lag 5: PostgreSQL                                   → lokal Docker, SPOF

Deteksjon

Bot-nedetid

Vaktmesteren overvåker synops-respond sin exit-kode. Ved feil:

@bot (ingen respons på 30 sek)
  → Vaktmesteren sender automatisk i chatten:
    "⚠ Boten er midlertidig utilgjengelig.
     Meldingen din er lagret og blir besvart
     når tjenesten er tilbake."
  → Oppretter work_item i innboks: "Bot-nedetid" + tagged "bug"
  → Logger i ai_usage_log med error-status

Brukeren vet at meldingen er mottatt. Når boten er tilbake, kan den prosessere ubesvarte meldinger.

Healthcheck

Vaktmesteren eksponerer /health som sjekker:

  • PG-tilkobling
  • LiteLLM-tilgjengelighet
  • Disk-status

Systemd restarter vaktmesteren ved gjentatte feil.

LLM fallback-kjede

LiteLLM håndterer modell-fallback. @bot fungerer uansett hvilken modell som svarer:

synops-respond → LiteLLM
                   ├── Claude (primær)
                   ├── GPT-4 (fallback 1)
                   ├── Gemini (fallback 2)
                   └── Lokal modell (fallback 3, alltid oppe)

Brukeren merker kanskje kvalitetsforskjell, men tjenesten er oppe. Fallback-kjeden konfigureres i LiteLLM — ingen endring i vaktmesteren eller synops-respond.

Ekstern API-bot og CLI-verktøy

En LLM via API har ikke shell-tilgang. Den trenger det heller ikke — vaktmesteren er mellomleddet.

Function calling / tool use

Bruker: "@bot sjekk om RSS-feeden oppdaterte seg"
  → vaktmesteren → synops-respond → LLM API

LLM svarer med structured output:
  {
    "response": "Jeg sjekker RSS-feeden for deg.",
    "actions": [
      { "tool": "synops-rss",
        "args": { "collection_id": "abc123" } }
    ]
  }

Vaktmesteren:
  1. Poster chat-svaret i samtalen
  2. Spawner: synops-rss --payload-json '{"collection_id":"abc123"}'
  3. Poster resultatet som oppfølgingsmelding

LLM-en beskriver hva som skal gjøres. Vaktmesteren gjør det. Navnekonvensjonen (synops-{tool}) betyr at vaktmesteren kan dispatche uten hardkodet mapping — samme generiske dispatch som jobbkøen (se docs/retninger/unix_filosofi.md).

Tilgangskontroll for actions

Ikke alle brukere skal kunne trigge alle verktøy via @bot. Vaktmesteren sjekker:

  1. Brukerens rolle i konteksten (owner/admin/member/reader)
  2. Verktøyets tilgangsnivå (fra cli_tool-nodens metadata)
  3. Rate limiting per bruker

En reader kan spørre @bot om informasjon, men ikke trigge synops-render eller synops-audio.

Fallback per situasjon

Situasjon Deteksjon Fallback Brukeropplevelse
Claude API nede LiteLLM timeout Neste modell i kjeden Svarer, kanskje litt dårligere
Alle LLM-er nede synops-respond exit != 0 Statisk "utilgjengelig" + work_item Vet at meldingen er mottatt
Vaktmesteren nede Systemd healthcheck → restart CLI fungerer for Claude Code Web-brukere venter, terminal funker
PG nede Connection refused Alt stopper Eneste reelle SPOF
WebSocket nede Vaktmesteren restarter Frontend rekobler automatisk Sanntid midlertidig borte, data trygt

PG som eneste SPOF

PostgreSQL er den eneste komponenten der nedetid stopper alt. Men det er også den mest stabile — PG krasjer sjelden, og gjenoppbygging fra backup er veldokumentert (se docs/setup/produksjon.md).

Mitigering:

  • Automatisk PG-dump (se oppgave 12.2)
  • synops-snapshot sikrer at docs-fallback finnes i repo
  • CAS-filer er uavhengig av PG (filsystem)

Onboarding som statisk dispatch

Første @bot i en ny brukers velkomst-chat trenger ikke LLM-roundtrip. Vaktmesteren gjenkjenner mønsteret og serverer onboarding-noden direkte:

if is_welcome_chat && is_first_bot_mention {
    return serve_static_node(ONBOARDING_NODE_UUID);
}

Null latency, null AI-kostnad, fungerer selv om alle LLM-er er nede. Onboarding-teksten er en vanlig node — oppdaterbar uten redeploy.

Etter første melding fungerer chatten normalt med LLM.

Bygger på

  • docs/infra/ai_gateway.md — LiteLLM fallback-kjeder
  • docs/retninger/unix_filosofi.md — generisk dispatch
  • docs/retninger/maskinrommet.md — vaktmester-rollen
  • docs/concepts/arbeidstavlen.md — @bot-konvensjonen
  • docs/concepts/selvdokumenterende_system.md — onboarding-node