synops/docs/concepts/orkestrering.md
vegard 7b601ead1f Orkestrering: målet er alltid script — AI er overgang, ikke driftsmodus
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>
2026-03-18 16:00:37 +00:00

12 KiB
Raw Blame History

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å:

{
  "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