synops/docs/infra/robusthet.md
vegard 4d7852f466 Spesifiser robusthet: fallback-kjede, bot-nedetid, function calling
Nytt infra-dokument for robusthet og fallback:
- LLM fallback-kjede via LiteLLM (Claude → GPT-4 → lokal modell)
- Automatisk nedetid-melding til brukere ved bot-feil
- Function calling: ekstern API-bot dispatcher CLI-verktøy via
  portvokteren (structured output → generisk dispatch)
- Tilgangskontroll for bot-actions per brukerrolle
- Onboarding som statisk dispatch (null LLM-kostnad)
- PG som eneste reelle SPOF, mitigering via backup+snapshot

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

148 lines
4.7 KiB
Markdown

# 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: Portvokteren → lokal native (systemd)
Lag 4: CLI-verktøy (synops-*) → per-kall, isolert
Lag 5: PostgreSQL → lokal Docker, SPOF
```
## Deteksjon
### Bot-nedetid
Portvokteren overvåker `synops-respond` sin exit-kode. Ved feil:
```
@bot (ingen respons på 30 sek)
→ Portvokteren 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
Portvokteren eksponerer `/health` som sjekker:
- PG-tilkobling
- STDB-tilkobling
- LiteLLM-tilgjengelighet
- Disk-status
Systemd restarter portvokteren 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 portvokteren eller synops-respond.
## Ekstern API-bot og CLI-verktøy
En LLM via API har ikke shell-tilgang. Den trenger det heller
ikke — portvokteren er mellomleddet.
### Function calling / tool use
```
Bruker: "@bot sjekk om RSS-feeden oppdaterte seg"
→ portvokteren → synops-respond → LLM API
LLM svarer med structured output:
{
"response": "Jeg sjekker RSS-feeden for deg.",
"actions": [
{ "tool": "synops-rss",
"args": { "collection_id": "abc123" } }
]
}
Portvokteren:
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. Portvokteren *gjør*
det. Navnekonvensjonen (`synops-{tool}`) betyr at portvokteren
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`.
Portvokteren 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 |
| Portvokteren nede | Systemd healthcheck → restart | CLI fungerer for Claude Code | Web-brukere venter, terminal funker |
| PG nede | Connection refused | Alt stopper | Eneste reelle SPOF |
| STDB nede | Reconnect-loop | PG-fallback for lesing, skriving bufres | Sanntid 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)
- STDB kan gjenoppbygges fra PG
- `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. Portvokteren gjenkjenner mønsteret og serverer
onboarding-noden direkte:
```rust
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` — portvokter-rollen
- `docs/concepts/arbeidstavlen.md`@bot-konvensjonen
- `docs/concepts/selvdokumenterende_system.md` — onboarding-node