# Konsept: Orkestrering **Filsti:** `docs/concepts/orkestrering.md` ## 1. Konsept Orkestreringer er noder som *gjør* ting. De er oppskrifter — sekvenser av CLI-verktøy og bot-instruksjoner som utføres automatisk når en trigger aktiveres. Brukeren skriver hva som skal skje i naturlig språk. Boten tolker og utfører. ## 2. Hvorfor Synops har mange automatiseringer hardkodet i portvokteren: 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: "Når en innspilling avsluttes..." metadata: { "trigger": { "event": "communication.ended", "conditions": { "has_trait": "podcast", "has_media": "audio" } }, "executor": "bot", "intelligence": 2, "effort": 2, "compiled": false } ``` ### 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. Fritekst-instruksjoner Stegene i en orkestrering er naturlig språk: ``` Når en innspilling i en samling med podcast-trait avsluttes: 1. Transkriber lydfilen med synops-transcribe (model: large) 2. Generer oppsummering med synops-summarize 3. Foreslå kapitler basert på transkripsjonen 4. Generer show notes 5. Oppdater RSS-feed med synops-rss Hvis transkribering feiler, prøv igjen med model: medium. Hvis RSS feiler, opprett work_item med tag 'bug'. ``` Brukeren skriver hva de vil. Boten tolker instruksjonene og utfører med function calling — kaller CLI-verktøy via portvokteren (se `docs/infra/robusthet.md` § function calling). ### Hvorfor fritekst, ikke DSL? - Ingen DSL å lære for brukeren - Boten resonnerer om feil og edge cases - Feilhåndtering er naturlig ("hvis X feiler, prøv Y") - Endring er å redigere tekst, ikke debugge JSON ## 5. Strukturert trigger Triggeren er den eneste strukturerte delen — portvokteren evaluerer den effektivt uten LLM: ```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 ### Bot-modus (default) ``` Trigger aktiveres → Portvokteren 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 ``` ### Kompilert modus (optimalisert) Når en orkestrering har kjørt mange ganger med samme mønster, kan den kompileres til en direkte pipeline: ```jsonc { "compiled": true, "pipeline": [ { "tool": "synops-transcribe", "args_map": {"cas_hash": "input.cas_hash", "model": "large"} }, { "tool": "synops-summarize", "args_map": {"communication_id": "input.id"} }, { "tool": "synops-rss", "args_map": {"collection_id": "input.collection_id"} } ], "fallback": "bot" } ``` Ingen LLM-kall for standardsteg. Direkte dispatch. Mye raskere, billigere, deterministisk. `fallback: "bot"` betyr: ved feil eller uventet situasjon, fall tilbake til fritekst-instruksjonene. ### Naturlig progresjon ``` 1. Fritekst → Brukere skriver, boten tolker 2. Observér → Boten logger hvilke verktøy/sekvenser som gjentas 3. Foreslå → "Denne har kjørt 50 ganger. Kompilere?" 4. Kompilér → Fast pipeline, ingen LLM for standardsteg 5. DSL (senere) → Kun hvis kompilerte pipelines trenger mer uttrykk ``` DSL-en designes ikke nå — den oppstår fra observerte mønstre. ## 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 ▼] │ │ │ │ Steg: │ │ ┌─────────────────────────────────────┐ │ │ │ Transkriber lydfilen med stor │ │ │ │ modell. Hvis det feiler, bruk │ │ │ │ medium. │ │ │ ├─────────────────────────────────────┤ │ │ │ Oppsummer samtalen. │ │ │ ├─────────────────────────────────────┤ │ │ │ Foreslå kapitler. │ │ │ ├─────────────────────────────────────┤ │ │ │ Oppdater RSS-feed. │ │ │ └─────────────────────────────────────┘ │ │ │ │ [+ Legg til steg] [▶ Test kjøring] │ │ │ │ Status: Aktiv Kjørt: 47 ganger │ │ Sist: 2026-03-18 12:30 (OK) │ └───────────────────────────────────────────┘ ``` Hvert steg er en tekstboks. "Test kjøring" sender til boten med dry-run. Historikk synlig. ## 9. Edge-modell | Edge | Source → Target | Betydning | |------|----------------|-----------| | `belongs_to` | orchestration → collection | Tilhører denne samlingen | | `triggers` | orchestration → orchestration | Kaskade-kobling | | `uses` | orchestration → cli_tool | Bruker dette verktøyet | | `mentions` | orchestration → any | Refererer til denne noden | ## 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. ### Slik fungerer det ``` 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 i chatten: "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 ``` Hver feilet steg som skyldes manglende verktøy er en **feature request** — gratis, kontekstuell, fra faktisk behov. Systemet lærer hva brukerne vil ha fra orkestreringer som ikke lykkes. ### Diskret hint, ikke begrensning I editoren vises tilgjengelige verktøy som hint, men brukeren kan skrive hva som helst: ``` ┌─ Steg 3 ──────────────────────────────────┐ │ Lag en lydfil med oppsummeringen og send │ │ den til alle deltakere │ │ │ │ ℹ Tilgjengelig: synops-tts, synops-rss, │ │ synops-render, synops-transcribe... │ │ (12 verktøy) — men skriv hva du vil │ └────────────────────────────────────────────┘ ``` Brukeren drømmer. Systemet vokser. ## 11. Avgrensning - Orkestreringer er **ikke** en generell workflow-engine. De er oppskrifter som boten følger. - Fritekst-instruksjoner er primær. Kompilering er optimalisering, ikke krav. - Triggere evalueres av portvokteren, utførelse av boten. Klar ansvarsfordeling. - Feilhåndtering er botens ansvar. Ingen retry-DSL. ## 12. Komponenter | Feature | Rolle | |---------|-------| | Portvokteren | Evaluerer triggere, dispatcher til bot | | @bot | Tolker 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 | ## 13. Bygger på - `docs/retninger/unix_filosofi.md` — CLI-verktøy som byggeklosser - `docs/concepts/arbeidstavlen.md` — @bot, work items ved feil - `docs/infra/robusthet.md` — function calling, fallback - `docs/features/responskvalitet.md` — intelligence/effort-nivåer