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>
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:
- Brukerens rolle i konteksten (owner/admin/member/reader)
- Verktøyets tilgangsnivå (fra
cli_tool-nodens metadata) - 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-snapshotsikrer 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-kjederdocs/retninger/unix_filosofi.md— generisk dispatchdocs/retninger/maskinrommet.md— vaktmester-rollendocs/concepts/arbeidstavlen.md— @bot-konvensjonendocs/concepts/selvdokumenterende_system.md— onboarding-node