Nytt prinsipp: enhver orkestrering skal bli et deklarativt script. Hvis det ikke er mulig, lag bedre verktøy eller stram opp spec. AI som permanent feilhåndtering er et tegn på at noe er galt. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
383 lines
12 KiB
Markdown
383 lines
12 KiB
Markdown
# Konsept: Orkestrering
|
||
**Filsti:** `docs/concepts/orkestrering.md`
|
||
|
||
## 1. Konsept
|
||
|
||
Orkestreringer er noder som *gjør* ting. De er oppskrifter —
|
||
sekvenser av CLI-verktøy som utføres automatisk når en trigger
|
||
aktiveres. Tre nivåer: deklarativt script (ingen AI),
|
||
fritekst med AI-tolkning, og full drømmemodus.
|
||
|
||
## 2. Hvorfor
|
||
|
||
Synops har mange automatiseringer hardkodet i vaktmesteren:
|
||
podcast-pipeline, AI-beriking, publisering. De er usynlige,
|
||
uendrelige og umulige å tilpasse for brukere.
|
||
|
||
Orkestreringer gjør automatisering til førsteklasses graf-
|
||
primitiver — synlige, redigerbare, delbare, versjonerbare.
|
||
|
||
## 3. Nodemodell
|
||
|
||
```
|
||
node_kind: 'orchestration'
|
||
title: "Podcast: opptak → publisering"
|
||
content: <script eller fritekst>
|
||
metadata: {
|
||
"trigger": {
|
||
"event": "communication.ended",
|
||
"conditions": {
|
||
"has_trait": "podcast",
|
||
"has_media": "audio"
|
||
}
|
||
},
|
||
"executor": "script" | "bot" | "dream",
|
||
"intelligence": 2,
|
||
"effort": 2
|
||
}
|
||
```
|
||
|
||
### Tre typer noder som gjør
|
||
|
||
| node_kind | Ikon | Aktivering | Eksempel |
|
||
|-----------|------|------------|----------|
|
||
| `cli_tool` | 🔧 | Kalles av andre | synops-transcribe |
|
||
| `ai_preset` | 🔧 | Kalles av AI-verktøy | "Rens tekst"-prompt |
|
||
| `orchestration` | ⚡ | **Trigger-drevet, utfører seg selv** | Podcast-pipeline |
|
||
|
||
⚡ signaliserer: "denne noden gjør noe av seg selv."
|
||
|
||
## 4. Tre utførelsesnivåer
|
||
|
||
### Nivå 1: Deklarativt script (ingen AI)
|
||
|
||
Eksakte CLI-kall med variabler fra trigger-konteksten.
|
||
Vaktmesteren parser og eksekverer direkte — ingen LLM.
|
||
|
||
```
|
||
NÅR innspilling.avsluttet
|
||
HVIS samling.har_trait("podcast")
|
||
|
||
1. synops-transcribe --cas-hash {event.cas_hash} --model large
|
||
VED_FEIL: synops-transcribe --cas-hash {event.cas_hash} --model medium
|
||
2. synops-summarize --communication-id {event.communication_id}
|
||
3. synops-rss --collection-id {event.collection_id}
|
||
|
||
VED_FEIL: work_item "Podcast-pipeline feilet" --tag bug
|
||
```
|
||
|
||
**Grammatikk:**
|
||
|
||
```
|
||
TRIGGER NÅR <event> [HVIS <betingelse>]
|
||
STEP <N>. <tool> <args...>
|
||
FALLBACK VED_FEIL: <tool> <args...> | work_item <title> [--tag <tag>]
|
||
VARIABLE {event.<felt>} — substitueres fra trigger-konteksten
|
||
```
|
||
|
||
Enkelt nok til å parse med en liten Rust-parser i vaktmesteren.
|
||
Deterministisk, gratis, raskt. **De fleste produksjons-
|
||
orkestreringer vil være på dette nivået.**
|
||
|
||
### Nivå 2: Fritekst med AI-tolkning
|
||
|
||
Naturlig språk som boten tolker og utfører steg for steg
|
||
med function calling. For orkestreringer der stegene ikke
|
||
er helt forutsigbare.
|
||
|
||
```
|
||
Når en innspilling i en samling med podcast-trait avsluttes:
|
||
|
||
1. Transkriber lydfilen med stor modell
|
||
2. Generer oppsummering
|
||
3. Foreslå kapitler basert på transkripsjonen
|
||
4. Generer show notes
|
||
5. Oppdater RSS-feed
|
||
|
||
Hvis transkribering feiler, prøv igjen med medium modell.
|
||
Hvis RSS feiler, opprett en oppgave.
|
||
```
|
||
|
||
Boten mapper "transkriber lydfilen" → `synops-transcribe`,
|
||
"oppsummer" → `synops-summarize`, osv. Krever LLM-kall
|
||
per kjøring (Haiku er nok for de fleste).
|
||
|
||
### Nivå 3: Drømmemodus
|
||
|
||
Brukeren skriver hva de *ønsker*, uten å vite hvilke verktøy
|
||
som finnes. Boten prøver, og mangler som oppdages blir
|
||
feature requests.
|
||
|
||
```
|
||
Gjør episoden klar for publisering. Lag en lydfil med
|
||
sammendrag og send den til alle deltakere.
|
||
```
|
||
|
||
Boten sjekker tilgjengelige verktøy, gjør det den kan,
|
||
og oppretter work_items for det som mangler.
|
||
|
||
### Naturlig progresjon
|
||
|
||
```
|
||
Drømmemodus → Bruker beskriver ønsket resultat
|
||
↓ AI foreslår
|
||
Fritekst → Bruker justerer steg i naturlig språk
|
||
↓ AI foreslår kompilering etter N kjøringer
|
||
Script → Deklarative CLI-kall, ingen AI
|
||
↓ manuelt
|
||
Kode → Eget CLI-verktøy (synops-<verb>)
|
||
```
|
||
|
||
Hvert nivå kan fryses til nivået under. AI foreslår
|
||
kompilering, bruker godkjenner. Scriptet kan alltid
|
||
redigeres manuelt.
|
||
|
||
## 5. Strukturert trigger
|
||
|
||
Triggeren er alltid strukturert — vaktmesteren evaluerer
|
||
den effektivt uten LLM, uavhengig av utførelsesnivå:
|
||
|
||
```jsonc
|
||
{
|
||
"trigger": {
|
||
"event": "communication.ended",
|
||
"conditions": {
|
||
"has_trait": "podcast",
|
||
"has_media": "audio"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Kjente trigger-events
|
||
|
||
| Event | Beskrivelse |
|
||
|-------|-------------|
|
||
| `node.created` | Ny node opprettet |
|
||
| `edge.created` | Ny edge opprettet |
|
||
| `communication.ended` | Samtale/innspilling avsluttet |
|
||
| `node.published` | Node publisert (belongs_to med slot) |
|
||
| `scheduled.due` | Planlagt tidspunkt nådd |
|
||
| `manual` | Bruker trykker "Kjør" |
|
||
|
||
### Betingelser
|
||
|
||
Filtrerer triggeren ytterligere:
|
||
- `has_trait` — noden/samlingen har denne traiten
|
||
- `has_media` — noden har media-edge av denne typen
|
||
- `has_tag` — noden har tagged-edge med denne verdien
|
||
- `node_kind` — noden er av denne typen
|
||
|
||
## 6. Utførelse
|
||
|
||
### Script-modus (nivå 1)
|
||
|
||
```
|
||
Trigger aktiveres
|
||
→ Vaktmesteren finner matchende orchestration-node
|
||
→ Parser scriptet
|
||
→ Substituerer {event.*}-variabler fra trigger-kontekst
|
||
→ Utfører steg sekvensielt via generisk dispatch
|
||
(synops-{tool} --payload-json)
|
||
→ Ved feil: kjør VED_FEIL-steg eller opprett work_item
|
||
→ Logger i orchestration_log
|
||
```
|
||
|
||
Ingen LLM. Deterministisk. Raskt.
|
||
|
||
### Bot-modus (nivå 2)
|
||
|
||
```
|
||
Trigger aktiveres
|
||
→ Vaktmesteren finner matchende orchestration-node
|
||
→ Sender til bot med function calling:
|
||
- Trigger-kontekst (hvilken node, hvilken event)
|
||
- Instruksjonene fra orchestration.content
|
||
- Tilgjengelige verktøy (cli_tool-noder)
|
||
→ Boten utfører steg for steg
|
||
→ Logger hvert steg i orchestration_log
|
||
→ Ved feil: resonnerer og prøver alternativ
|
||
```
|
||
|
||
### Drømmemodus (nivå 3)
|
||
|
||
Som bot-modus, men med høyere intelligens (Sonnet+) og
|
||
instruks om å opprette work_items for manglende verktøy.
|
||
|
||
### Auto-eskalering
|
||
|
||
Script-modus faller tilbake til bot-modus ved uventet feil:
|
||
|
||
```
|
||
Script kjører steg 2
|
||
→ synops-summarize returnerer exit 1
|
||
→ VED_FEIL er definert → prøv alternativ
|
||
→ Alternativ feiler også
|
||
→ Eskalér til bot-modus for dette steget
|
||
→ Boten resonnerer om feilen og prøver å løse det
|
||
```
|
||
|
||
## 7. Koblinger mellom orkestreringer
|
||
|
||
Orkestreringer er noder med edges:
|
||
|
||
```
|
||
"Podcast: opptak → publisering"
|
||
──triggers──→ "Varsle redaksjonen om ny episode"
|
||
──triggers──→ "Post til sosiale medier"
|
||
```
|
||
|
||
Output fra én orkestrering kan trigge neste via `triggers`-edge.
|
||
Kaskade via edges, ikke hardkodet.
|
||
|
||
## 8. Brukergrensesnitt
|
||
|
||
```
|
||
┌─ Podcastorkestrering ⚡ ──────────────────┐
|
||
│ │
|
||
│ Trigger: [Innspilling avsluttet ▼] │
|
||
│ Betingelse: [Samling har podcast-trait ▼] │
|
||
│ Modus: [Script ▼] │
|
||
│ │
|
||
│ ┌─────────────────────────────────────┐ │
|
||
│ │ NÅR innspilling.avsluttet │ │
|
||
│ │ HVIS samling.har_trait("podcast") │ │
|
||
│ │ │ │
|
||
│ │ 1. synops-transcribe │ │
|
||
│ │ --cas-hash {event.cas_hash} │ │
|
||
│ │ --model large │ │
|
||
│ │ VED_FEIL: ... --model medium │ │
|
||
│ │ 2. synops-summarize │ │
|
||
│ │ --communication-id {event.id} │ │
|
||
│ │ 3. synops-rss │ │
|
||
│ │ --collection-id {event.coll_id} │ │
|
||
│ └─────────────────────────────────────┘ │
|
||
│ │
|
||
│ [▶ Test kjøring] [↑ Konverter til AI] │
|
||
│ │
|
||
│ Status: Aktiv Kjørt: 47 ganger │
|
||
│ Sist: 2026-03-18 12:30 (OK) │
|
||
│ │
|
||
│ ℹ Tilgjengelig: synops-transcribe, │
|
||
│ synops-rss, synops-render... │
|
||
│ (12 verktøy) │
|
||
└───────────────────────────────────────────┘
|
||
```
|
||
|
||
Modusvelger: Script / Fritekst / Drømmemodus.
|
||
"Test kjøring" utfører med dry-run.
|
||
"Konverter til AI" løfter scriptet til fritekst-modus.
|
||
|
||
## 9. Edge-modell
|
||
|
||
| Edge | Source → Target | Betydning |
|
||
|------|----------------|-----------|
|
||
| `belongs_to` | orchestration → collection | Tilhører denne samlingen |
|
||
| `observes` | orchestration → any node | Overvåker denne noden for trigger-events |
|
||
| `triggers` | orchestration → orchestration | Kaskade-kobling |
|
||
| `uses` | orchestration → cli_tool | Bruker dette verktøyet |
|
||
| `mentions` | orchestration → any | Refererer til denne noden |
|
||
|
||
### `observes`-edge: eksplisitt kobling
|
||
|
||
Orkestreringen peker på det den observerer:
|
||
|
||
```
|
||
"Auto-clip URL-er" (orchestration)
|
||
──observes──→ #Redaksjonen (communication)
|
||
──observes──→ #Research (communication)
|
||
```
|
||
|
||
Legg til `observes`-edge → aktivert for den noden.
|
||
Fjern edge → deaktivert. Opprettet via drag-and-drop
|
||
(se `docs/retninger/interaksjonsmodell.md`).
|
||
|
||
### Implisitt vs eksplisitt
|
||
|
||
- **`observes`-edge:** Eksplisitt. "Denne orkestreringen overvåker
|
||
denne noden."
|
||
- **Trigger-betingelser:** Implisitt. "Overvåk alt som matcher."
|
||
- `observes` overtrumfer: fjernet `observes`-edge betyr "ikke her",
|
||
selv om betingelsene matcher. Brukeren har kontroll.
|
||
|
||
## 10. Drømmemodus: brukeren skriver hva de vil
|
||
|
||
Brukeren begrenses ikke til kjente verktøy. De skriver fritt
|
||
— boten prøver, og mangler som oppdages blir feature requests.
|
||
|
||
```
|
||
Bruker skriver: "Lag en lydfil med sammendrag og send til deltakerne"
|
||
|
||
Boten sjekker:
|
||
✓ synops-summarize finnes → oppsummerer
|
||
✗ synops-tts finnes ikke → kan ikke lage lyd
|
||
|
||
Boten svarer:
|
||
"Jeg oppsummerte møtet, men Synops har ikke tekst-til-tale
|
||
ennå. Jeg oppretter en forespørsel?"
|
||
|
||
→ work_item i innboks:
|
||
title: "TTS for møteoppsummeringer"
|
||
tagged: "feature"
|
||
source_material → orkestreringsnoden
|
||
```
|
||
|
||
Systemet lærer hva brukerne vil ha fra det som ikke lykkes.
|
||
|
||
## 11. Prinsipp: målet er alltid script
|
||
|
||
Enhver orkestrering har som mål å bli et deklarativt script.
|
||
AI-nivåene (fritekst, drøm) er **verktøy for å komme dit**,
|
||
ikke permanente driftsmoduser.
|
||
|
||
Hvis en orkestrering ikke kan uttrykkes som script, betyr det
|
||
én av to ting:
|
||
|
||
1. **Verktøyet mangler.** Lag et nytt CLI-verktøy som dekker
|
||
det manglende steget. Da kan scriptet uttrykke det.
|
||
2. **Logikken er for vag.** Stram opp instruksjonene til de er
|
||
presise nok for et script. Hvis det ikke er mulig, er
|
||
orkestreringen kanskje ikke moden nok for automatisering.
|
||
|
||
AI som permanent feilhåndtering i en orkestrering er et tegn
|
||
på at noe er galt — enten med verktøyet eller med spesifikasjonen.
|
||
Det skal fikses, ikke kompenseres.
|
||
|
||
```
|
||
Drømmemodus → "Hva vil vi oppnå?"
|
||
Fritekst → "Hvordan gjør vi det?"
|
||
Script → "Nøyaktig dette."
|
||
↓
|
||
Hvis script ikke er mulig:
|
||
→ Mangler verktøy? → Lag synops-<verb>
|
||
→ For vagt? → Stram opp spec
|
||
→ Umulig? → Ikke automatiser dette
|
||
```
|
||
|
||
## 12. Avgrensning
|
||
|
||
- Orkestreringer er **ikke** en generell workflow-engine.
|
||
De er oppskrifter — deklarative eller AI-tolkede.
|
||
- Deklarativt script er primær for produksjon. AI er for
|
||
oppretting, feilhåndtering og drømmemodus.
|
||
- Triggere evalueres av vaktmesteren, utførelse av
|
||
vaktmesteren (script) eller bot (fritekst/drøm).
|
||
- Brukeren begrenses aldri til kjente verktøy. Manglende
|
||
funksjonalitet fanges opp som feature requests.
|
||
|
||
## 13. Komponenter
|
||
|
||
| Feature | Rolle |
|
||
|---------|-------|
|
||
| Vaktmesteren | Evaluerer triggere, parser/utfører scripts, dispatcher til bot |
|
||
| @bot | Tolker fritekst-instruksjoner, utfører med function calling |
|
||
| CLI-verktøy | Gjør det faktiske arbeidet |
|
||
| Arbeidstavlen | Work items opprettes ved feil |
|
||
| Responskvalitet | Intelligence/effort per orkestrering |
|
||
|
||
## 14. Bygger på
|
||
- `docs/retninger/unix_filosofi.md` — CLI-verktøy som byggeklosser
|
||
- `docs/retninger/interaksjonsmodell.md` — drag-and-drop for observes-edge
|
||
- `docs/concepts/arbeidstavlen.md` — @bot, work items ved feil
|
||
- `docs/infra/robusthet.md` — function calling, fallback
|
||
- `docs/features/responskvalitet.md` — intelligence/effort-nivåer
|