# StyloFlow: Begränsade fuzzysignaler -drivna arbetsflöden

<!--category-- Architecture, AI, Workflows, C#, Signals, RAG -->
<datetime class="hidden">2026-01-11T14:00</datetime>

Jag byggde StyloFlow eftersom jag fortsatte skriva [samma mönster om och om igen](https://www.mostlylucid.net/blog/reduced-rag): komponenter som reagerar på vad som hände innan, släpper ut självförtroende poäng, och ibland måste eskalera till mer dyrare analyser. De existerande arbetsflödemotorerna ville att jag skulle tänka i termer av DAG eller statmaskiner. Jag ville tänka i signaler.

> NOTA: StyloFlow är inte än en färdig produkt; eftersom jag bygger lucidRAG och StyloBot IM SK2 jag lägger till förlorade egenskaper och polerar API: t på både StyloBllow och efemeral . DetMska4 är fortfarande i aktiv utvecklingMske5 men du kan pröva det och ge feedbackMsko6 Jag kommer att uppdatera det här senare Msek7 SignalSink-grejerna till exempel kommer att ändras för efemerala vMsku8 till att vara Mska9 bara läsbart')

**StyloFlow är en signaldriven orkestrationsbibliotek som matchar [hur jag tänker](https://www.mostlylucid.net/blog/thinking-in-systems) om[ AI-rör](https://www.mostlylucid.net/blog/tencommandments):** komponenter deklarerar vad de producerar och vad de behöver

Det här är infrastrukturen som ger energi till **[*klar*RAG](https://www.mostlylucid.net/blog/lucidrag-multi-document-rag-web-app)** - ett graf RAG-verktyg som kombinerar [DocSummarizer](/blog/building-a-document-summarizer-with-rag) (dokument [DataSummarizer](/blog/datasummarizer-how-it-works) (strukturerade data ), och [ImageSummarizer](/blog/constrained-fuzzy-image-intelligence) (, bilder, ), till en förenade fråga, -, en upphöjningssystem med kunskapsgrafvisualisering. [Stylobot](https://www.stylobot.net) ( ett avancerat robotskyddssystem ) och implementerar [Reduzerad RAG](/blog/reduced-rag) mönster.

![lucidRAG-gränssnitt](lucidrag_proto.png?width=500)

**källa:** [GitHub - StyloFlow](https://github.com/scottgal/styloflow)

[TOC]

---


## Vad är detta?

**StyloFlow är en fungerande prototyp** APIn och formen kommer att utvecklas när jag bygger lucidRAG och Stylobot, men de här beskrivna sekvenserna och mönsterna är punktsignaler : som första signal, classfakter, , självförtroende,- driven branching, , och eskalation som ett strukturellt mönst,

Detta är ett nytt DSL- eller arbetsflödesspråk. **avrättelsesemantik** byggt runt signalern, ,, självförtroende, ,, och begränsad skalning. ., Idag kör den i en process med begränsad samspel, M SK4, imorgon delar den ut spår mellan maskiner samtidigt som signalerna är den stabila gränsen.

---


## Problemet med traditionella arbetsflöden

Här är vad de flesta arbetsflödesmotorer ser ut som

```csharp
// ❌ Traditional: Hardcoded dependencies
public async Task ProcessDocumentAsync(string path)
{
    var text = await ExtractTextAsync(path);
    var chunks = await ChunkTextAsync(text);
    var embeddings = await GenerateEmbeddingsAsync(chunks);
    var entities = await ExtractEntitiesAsync(chunks);
    await StoreEverythingAsync(embeddings, entities);
}
```

Detta fungerar tills:

- Du vill hoppa över enhetens extraktion för enkla frågor
- Du behöver köra extraktion och embedding parallellt.
- Man vill utvecklas till ett bättre modell baserat på självförtroende.
- Du behöver lägga till en ny processfas utan att röra vid den existerande koden

Du får antingen:

1. **Rigida ledningar** som inte kan anpassa sig
2. **Massiva om/else** träd för vägledning
3. **Gudklassar** som vet allt

## Fonden: Spädrig uträttelse

StyloFlow bygger på [mestlucid.ephemeral](/blog/ephemeral-execution-library) - en bibliotek för begränsad , spårbar async exécution

Vinnig sammanfattning av vad ephemeral innebär:

```csharp
// Bounded concurrent processing with full visibility
var coordinator = new EphemeralWorkCoordinator<DocumentJob>(
    async (job, operation, ct) => {
        await ProcessAsync(job, ct);
        operation.Signal("document.processed");
    },
    new EphemeralOptions { MaxConcurrency = 4 });

// Enqueue work
await coordinator.EnqueueAsync(new DocumentJob(filePath));

// Full observability
Console.WriteLine($"Active: {coordinator.ActiveCount}");
Console.WriteLine($"Completed: {coordinator.TotalCompleted}");
```

**Nyckliga fördelar med ephemeral:**

- Avgränsad samtida ( inga uteglömda minnen )
- [LRU utfånganing](/blog/learning-lrus-when-capacity-makes-systems-better) av gamla operationer
- Signalpublicering för cross-- komponentkoordination
- Operation pinning för att förhindra för tidigt utfångande

För mer information [Ogen och Don't Bort glöm](/blog/fire-and-dont-quite-forget-ephemeral-execution).

---


## Vad denna modell gör möjligt

Detta orkesteringsmodell förlänger ephemeral med:

1. **YAML-driven komponent manifester** - Deklarerande konfiguration
2. **Trigger baserade på Signal-** - Komponenter körs när signaler dyker upp
3. **Koordination** - Prioritet-baserad exécution med samtida banor
4. **Escalationsmönster** - Vänta dyr analys tills det behövs
5. **Entitetskontrakt** - Typ
6. **Budjetstyre** - Symbolgränser , kostnadsgränser

Här är nyckeln till den arkitektoniska förändringen.

```mermaid
graph TD
    subgraph Traditional["❌ Traditional: Hardcoded"]
        T1[Component A] -->|calls| T2[Component B]
        T2 -->|calls| T3[Component C]
        T3 -->|calls| T4[Component D]
    end

    subgraph StyloFlow["✅ StyloFlow: Signal-Driven"]
        S1[Component A]
        S2[Component B]
        S3[Component C]
        S4[Component D]
        SS[Signal Sink]

        S1 -.emits.-> SS
        S2 -.emits.-> SS
        S3 -.emits.-> SS
        SS -.triggers.-> S2
        SS -.triggers.-> S3
        SS -.triggers.-> S4
    end

    style T1 stroke:#ff6b6b
    style T2 stroke:#ff6b6b
    style T3 stroke:#ff6b6b
    style T4 stroke:#ff6b6b
    style S1 stroke:#51cf66
    style S2 stroke:#51cf66
    style S3 stroke:#51cf66
    style S4 stroke:#51cf66
    style SS stroke:#339af0
```

Komponenter ropar aldrig på varandra . De släpper ut signaler och reagerar på signalern.

---


## Kernkoncept : Signaler och ägande

**Signaler är fakta om vad som hände**, inte kommandor eller händelser . De ' är förändringslösa M SK3 är nummertagna i tid, , och bär på självförtroende värden MSC5 Varje atom äger sina signaler Mska6 de Mske7 är externt förändringsiva M Ska8 Inget annat kan modifiera den listan

```csharp
public record Signal
{
    public required string Key { get; init; }           // "document.chunked"
    public object? Value { get; init; }                 // Optional payload
    public double Confidence { get; init; } = 1.0;      // 0.0 to 1.0
    public required string Source { get; init; }        // Which component
    public DateTime Timestamp { get; init; }
    public Dictionary<string, object>? Metadata { get; init; }
}
```

**Kritisk arkitektonisk punkt: SignalSink är en uthärdlig historisk syn på saker och ting**

**Signalsink** förmedlar en sökbar bild över alla operationer på alla koordinatorer som delar den. signaler över hela koordinatorns livscykel | - | när en operation flyttar bort från sin koordinator

```csharp
// Create a shared signal sink (no parameters, signals persist)
var sink = new SignalSink();

// Coordinators manage operation lifetime, NOT signal lifetime
var coordinator = new EphemeralWorkCoordinator<string>(
    ProcessAsync,
    new EphemeralOptions
    {
        MaxConcurrency = 8,
        MaxTrackedOperations = 100,         // Operations evict after this
        MaxOperationLifetime = TimeSpan.FromMinutes(5),  // Or after this time
        Signals = sink                      // Share the persistent view
    });

// Operations emit via their emitter
public async Task ProcessAsync(string docId, SignalEmitter emitter, CancellationToken ct)
{
    // Store actual data externally (cache, database, blob storage)
    await cache.SetAsync($"doc-{docId}", documentData);

    // Signal carries a REFERENCE, not the data
    emitter.Emit("document.chunked", key: docId); // Key references external data
}

// SignalSink is readonly - it cannot alter signals
// Signals persist until their operation evicts from the coordinator
```

**SignalSink ger två koordineringsmönster:**

**1. Push**

```csharp
// Subscribe to the sink for push notifications
sink.Subscribe(signal => {
    if (signal.Is("document.chunked"))
    {
        // React immediately - signal includes OperationId
        Console.WriteLine($"Op {signal.OperationId} chunked doc at {signal.Timestamp}");
    }
});

// Returns IDisposable for cleanup
using var subscription = sink.Subscribe(HandleSignal);
```

**2. Gå tillväga-baserade Fråg**

```csharp
// Get all signals for a specific operation
var opSignals = sink.GetOpSignals(operationId);

// Detect if any operation has emitted a signal
if (sink.Detect("embeddings.generated"))
{
    // At least one operation has generated embeddings
}

// Sense all signals matching a condition
var recentErrors = sink.Sense(s =>
    s.Signal.StartsWith("error.") &&
    s.Timestamp > DateTimeOffset.UtcNow.AddMinutes(-5)
);

// Get operation summary from its signal history
var summary = sink.GetOp(operationId);
Console.WriteLine($"Operation ran for {summary?.Duration}");
```

**Varför är detta viktigt:**

- **Readonly se** - SignalSink kan inte ändra signaler ; den erbjuder bara query-utgång
- **Signaler förblir kvar** - Signaler är kvar under bevakning tills deras operation avlägsnar koordinatorn
- **Signaler är koordination, inte transport** - Signaler bär nycklar /referencer till externa data, inte själva datan
- **Koordinatorns självständighet** - Flera koordinatorer kan dela med sig av en anslutning ; signalernas historia omfattar alla
- **Thread-säkra** - Slucka - fria svar för query-operationer
- **Att både trycka och dra** - Abonnerande () för reaktiva , Bemärkelse M SK3 Detektor
- **Operationskorrelation** - Varje signal inkluderar OperationId för att spåra över koordinatorer
- **Pattern matchning** - Frågan efter exakt matchning , prefix

**Nyckeldesignprincipen:** Speichera stora data (documenter, bilderM SK2 vektorer ) i kassor eller databaserMSC4 Signaler bär bara referensramar som `"cache://doc-123"` eller operativa nyckeln.

Till exempel koordinering:

```csharp
// Operation emits signal via ISignalEmitter interface
public async Task ProcessAsync(Item item, ISignalEmitter emitter, CancellationToken ct)
{
    // Emit to the sink
    emitter.Emit("processing.started");

    await DoWorkAsync(item, ct);

    emitter.Emit("processing.completed");
}

// Wave checks if it should run by querying sink
public bool ShouldRun(string path, AnalysisContext ctx)
{
    // Pull pattern: query the sink via context
    return ctx.Detect("document.chunked");
}

// UI subscribes to sink for reactive updates
sink.Subscribe(signal => {
    if (signal.Signal.StartsWith("document."))
    {
        // Push pattern: react immediately
        UpdateProgressUI(signal);
    }
});
```

**Escalation sker på två nivåer**

1. **I en koordinator** -vågor kontrollerar signalförtroende och kör villkorlig dyr analys
2. **Mellan koordinatorer** - EscalatorAtomstrålar signaler från en snabb koordinator → dyr koordinator baserat på signalkriterien

```csharp
// Pattern 1: Intra-coordinator escalation (wave checks signals)
public bool ShouldRun(string path, AnalysisContext ctx)
{
    var quality = ctx.GetSignal("quality.score");
    return quality?.Confidence < 0.7; // Only run if quality is low
}

// Pattern 2: Inter-coordinator escalation (atom routes to another coordinator)
// Option A: Explicit escalation signal
typed.Raise("escalate.to.expensive", payload, key: "doc-123");

// Option B: EscalatorAtom examines signals and decides
new EscalatorAtomOptions<T> {
    ShouldEscalate = evt => evt.Payload.Confidence < 0.7
}
```

Flera koordinatorer funkar oberoende av varandra . EscalatorAtom tittar på signaler från en koordinator och förflyttar arbetet till en annan när det behövs.

För teorin bakom detta, ,, se [Begränsat Fuzzy Kontexttdragning](/blog/constrained-fuzzy-context-dragging).

### Signaler bär referensramar , Nej Data

**Kritiskt** Signaler är koordineringshändelser , inte dataöverföring. stora data | ( | dokument | , | bilder |, | inbäddar | ) | borde finnas i ett externt lager

```csharp
// ❌ BAD: Carrying data in signals (memory pressure, boxing)
var imageBytes = await ProcessImageAsync(input);
emitter.Emit("image.processed", metadata: new { Data = imageBytes });

// ✅ GOOD: Store externally, signal the reference
var imageBytes = await ProcessImageAsync(input);
var cacheKey = $"processed/{docId}";
await cache.SetAsync(cacheKey, imageBytes);
emitter.Emit("image.processed", key: cacheKey);

// Later: Retrieve when needed
if (sink.Detect("image.processed"))
{
    var signals = sink.GetOpSignals(operationId);
    var imageKey = signals.FirstOrDefault(s => s.Signal == "image.processed")?.Key;
    if (imageKey != null)
    {
        var bytes = await cache.GetAsync<byte[]>(imageKey);
    }
}
```

**De bästa metoderna:**

- Använd kaser (in-memory eller fördeladeM SK2 för efemerala data
- Använd databaser för hållbara data
- Använd blob-skivor för stora filer
- Signal URIs: `"cache://key"`, `"blob://container/file"`, `"db://table/id"`
- Håll signalerna i lättvikt - bara nyckeln , självförtroende poängen

---


## Kernkoncept : Komponentmanifester

**Manifest deklarerar kontrakt. (, vad får mig att göra det , ",, vad jag utsläpper, ,, vad det kostar"** separat från implementering. Den här separationen existerar så att man kan förstå arbetsflödet utan att läsa koden , och ändra exécutionsorten utan att kompilera

```yaml
name: BotDetector
priority: 10              # Lower runs first
enabled: true

# What kind of component is this?
taxonomy:
  kind: analyzer          # sensor|analyzer|proposer|gatekeeper
  determinism: probabilistic
  persistence: ephemeral

# When should this run?
triggers:
  requires:
    - signal: http.request.received
      condition: exists

# What does it produce?
emits:
  on_complete:
    - key: bot.detected
      confidence_range: [0.0, 1.0]

  conditional:
    - key: bot.escalation.needed
      when: confidence < 0.7

# Resource limits
lane:
  name: fast              # fast|normal|slow|llm
  max_concurrency: 8

budget:
  max_duration: 100ms

# Configuration values
defaults:
  confidence:
    bot_detected: 0.6
  timing:
    timeout_ms: 100
```

**Möjligheter:**

1. **Runtime-konfiguration** - ändra prioritering utan att kompilera
2. **Omgivning överrider** - Överrider via appsettings.json
3. **Klara kontrakt** - Se vilka signaler som utlöser vad
4. **Själva dokumentering** - Manifestet är specifikationen

### Visual Workflow Builder

Medan du kan skriva YAML-manifester av hand., StyloFlow innehåller en visuell arbetsflödesbyggare som låter dig designa signal.

![StyloFlow Workflow Builder](styloflow_ui.png?width=800)

Interfejsen erbjuder:

- **Drag- -- och - komponenter** ur taksonomen (sensorer , analyser M SK2 förespråkare
- **Signaldragglackande** - Koppla utgångar till ingångar visuellt
- **Liv manifest föreställning** - Se skapade YAML medan du bygger
- **Triggervisualisering** - Se vilka signaler som utlöser vilka komponenter
- **Längsläggning** - Drag komponenter in i snabba spurr
- **Verklig validation** - Ta tag i oäkta signalreferenser omedelbart

Detta gör det enkelt att experimentera med olika arbetsflödes former utan att skriva YAML på hand.

---


## Kernkoncept: Weller

Ett våg är en komponerande analyssstadium. **Den här gränssnittet existerar för att göra " skulle vi kunna köra ?" som ett första beslut**, inte ett implementeringsdetail begravt i villkorlig logik .

```csharp
public interface IContentAnalysisWave
{
    string Name { get; }
    int Priority { get; }               // Higher runs first
    bool Enabled { get; set; }

    // Quick filter - avoid expensive work
    bool ShouldRun(string contentPath, AnalysisContext context);

    // Do the analysis
    Task<IEnumerable<Signal>> AnalyzeAsync(
        string contentPath,
        AnalysisContext context,
        CancellationToken ct);
}
```

**Enkel våg exempel:**

```csharp
public class FileTypeWave : IContentAnalysisWave
{
    public string Name => "FileType";
    public int Priority => 100;
    public bool Enabled { get; set; } = true;

    public bool ShouldRun(string path, AnalysisContext ctx)
    {
        // Skip if we already know the type
        return ctx.GetSignal("file.type") == null;
    }

    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string path,
        AnalysisContext ctx,
        CancellationToken ct)
    {
        var extension = Path.GetExtension(path);
        var mimeType = GetMimeType(extension);

        return new[]
        {
            new Signal
            {
                Key = "file.type",
                Value = mimeType,
                Confidence = 1.0,
                Source = Name
            }
        };
    }
}
```

**Koordination av vågor**

Den `WaveCoordinator` kör vågor i prioritära ordning:

```csharp
var coordinator = new WaveCoordinator(waves, profile);
var context = new AnalysisContext();

var results = await coordinator.ExecuteAsync(filePath, context, ct);

// All signals from all waves
foreach (var signal in context.GetAllSignals())
{
    Console.WriteLine($"{signal.Key}: {signal.Value}");
}
```

**Konkurenserande vägar**

Rör vågor på vägar med olika samtida gränser:

| Gadan | syfte | Konkurens |
|------|---------|-------------|
| `fast` | Vinniga kontroller |  | IP-uppsök |, | File type |
| `normal` | Standardbearbetande |  | Parsering
| `io` | IM SK1O bunden (filer läser , API-sändningar) M| | | 32 |
| `llm` | dyra LLM-sändningar

Detta förhindrar dyra operationer från att blockera billiga

---


## Arkitektur: Hur det passar ihop

Här är den kompletta bilden.

```mermaid
graph TB
    subgraph Input["Input Layer"]
        REQ[HTTP Request]
        FILE[File Upload]
        JOB[Background Job]
    end

    subgraph Ephemeral["Ephemeral Layer"]
        COORD[Work Coordinator]
        OPS[Operations<br/>own signals]
        SINK[SignalSink<br/>read-only view]
    end

    subgraph StyloFlow["StyloFlow Layer"]
        MAN[Manifests]
        WAVE[Wave Coordinator]
        ATOMS[Atoms<br/>own signals]
    end

    subgraph Execution["Execution"]
        FAST[Fast Lane]
        NORM[Normal Lane]
        LLM[LLM Lane]
    end

    subgraph Output["Output"]
        RES[Results]
        ESCAL[Escalation]
        STORE[Persistence]
    end

    REQ --> COORD
    FILE --> COORD
    JOB --> COORD

    COORD --> OPS
    SINK -.queries.-> OPS

    WAVE -.reads.-> SINK
    MAN -.configures.-> WAVE
    WAVE --> ATOMS

    ATOMS --> FAST
    ATOMS --> NORM
    ATOMS --> LLM

    SINK -.queries.-> FAST
    SINK -.queries.-> NORM
    SINK -.queries.-> LLM

    SINK -.read for.-> RES
    SINK -.read for.-> ESCAL
    SINK -.read for.-> STORE

    style COORD stroke:#339af0
    style SINK stroke:#339af0
    style WAVE stroke:#51cf66
    style ATOMS stroke:#51cf66
```

**Flow:**

1. Input kommer: ( Http-ansökande , file , job
2. Ephemeral koordinator skapar operation ( som ägs en tom signallista )
3. Operationen lägger till signaler i dess egen lista
4. Bandkoordinator READS signaler via SignalSink-uppfattning för att kontrollera utlösande tillstånd
5. vågor vars utlösare matchar körs i prioritära ordning inom samtida banor
6. Varje våg lägger till signaler i sin aktivitet
7. Bandkoordinator fortsätter att läsa signaler för att hitta nytillfredsställda utlösande
8. Slutliga utgångsfragen SignalSink för att läsa signaler och bedöma handlingar

**Eigenschaftsmodell:** Varje operation/ ägs sina signaler, atomen . SignalSink ger en läsning, - bara syn över alla operationer, . Signaler kan upphöjas, | ( | kopieras, M SK5 | eller ekaderas, ♫ ( | bevaras när utskjutts, ♪ ♪ ), | men listan som ägs är externt oänderbar, ♪

**Den nuvarande Ausführungsmodellen:** Enkela operationer med LRU-utskjutning

**Framstående Ausführungsmodell:** Distribuerade banor över maskiner, SignalSink frågar fjärran operationer , atomer utförs på olika värden. **Signaler förblir den stabila gränsen** -, de , ', är redan serialiserade, ,, stängstimmade och självbevarade. -, består av ., ägandes modellen ändrar inte på ' eller .."

Implementeringen i processen validerar semantiken.

---


## Använd fall: lucidRAG Dokumentbehandling

Låt oss se hur [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) använder StyloFlow:

**Etappe 1: Initiell upptäckt**

```csharp
public class FileTypeDetectorWave : IContentAnalysisWave
{
    public int Priority => 100;  // Run first

    public async Task<IEnumerable<Signal>> AnalyzeAsync(...)
    {
        var extension = Path.GetExtension(path);

        return new[]
        {
            new Signal
            {
                Key = "file.extension",
                Value = extension,
                Source = "FileTypeDetector"
            }
        };
    }
}
```

**Etappen 2: Förstärkning ( aktiverad av filen.upplängningM SK3**

```csharp
// In manifest:
// triggers:
//   requires:
//     - signal: file.extension
//       condition: in
//       value: [".pdf", ".docx", ".md"]

public class ChunkingWave : ConfiguredComponentBase, IContentAnalysisWave
{
    public int Priority => 80;

    public async Task<IEnumerable<Signal>> AnalyzeAsync(...)
    {
        var chunks = await ChunkDocumentAsync(path);

        ctx.SetCached("chunks", chunks);  // Share with other waves

        return new[]
        {
            new Signal
            {
                Key = "document.chunked",
                Value = chunks.Count,
                Source = Name
            }
        };
    }
}
```

**Etappe 3: Embedding ( trigerade av dokumentet. instängdaM SK3**

```csharp
public class EmbeddingWave : ConfiguredComponentBase, IContentAnalysisWave
{
    public int Priority => 60;

    public bool ShouldRun(string path, AnalysisContext ctx)
    {
        // Only run if chunking succeeded
        return ctx.GetSignal("document.chunked") != null;
    }

    public async Task<IEnumerable<Signal>> AnalyzeAsync(...)
    {
        var chunks = ctx.GetCached<List<Chunk>>("chunks");
        var embeddings = await GenerateEmbeddingsAsync(chunks);

        ctx.SetCached("embeddings", embeddings);

        return new[]
        {
            new Signal
            {
                Key = "embeddings.generated",
                Value = embeddings.Count,
                Source = Name
            }
        };
    }
}
```

**Etappe 4: Enhetens extraktion ♫ ( ♫ likvärdig med inbäddning ♫**

```csharp
public class EntityExtractionWave : ConfiguredComponentBase, IContentAnalysisWave
{
    public int Priority => 60;  // Same as embedding - runs in parallel

    public async Task<IEnumerable<Signal>> AnalyzeAsync(...)
    {
        var chunks = ctx.GetCached<List<Chunk>>("chunks");

        // Use deterministic IDF scoring, not LLM per chunk
        // (See Reduced RAG pattern)
        var entities = await ExtractEntitiesAsync(chunks);

        return new[]
        {
            new Signal
            {
                Key = "entities.extracted",
                Value = entities.Count,
                Confidence = CalculateConfidence(entities),
                Source = Name
            }
        };
    }
}
```

**Etappe 5: Jaktkontroll**

```csharp
public class QualityCheckWave : ConfiguredComponentBase, IContentAnalysisWave
{
    public int Priority => 40;  // After embedding + entities

    public async Task<IEnumerable<Signal>> AnalyzeAsync(...)
    {
        var embeddingSignal = ctx.GetSignal("embeddings.generated");
        var entitySignal = ctx.GetSignal("entities.extracted");

        var embeddingCount = (int)embeddingSignal.Value;
        var entityConfidence = entitySignal.Confidence;

        var quality = CalculateQuality(embeddingCount, entityConfidence);

        var signals = new List<Signal>
        {
            new Signal
            {
                Key = "quality.score",
                Value = quality,
                Source = Name
            }
        };

        // Trigger escalation if quality is poor
        if (quality < GetParam<double>("quality_threshold", 0.7))
        {
            signals.Add(new Signal
            {
                Key = "escalation.needed",
                Value = "low_quality_document",
                Source = Name
            });
        }

        return signals;
    }
}
```

**Möjligheterna med den här metoden**

1. **Parallellt utförande** - Embedding och entite extraktion körs samtidigt
2. **Bedingande granskning** - Kvalitekontroll bestämmer om eskalering behövs
3. **Samlat sammanhang** - Waves får tillgång till chunks utan att skicka dem explicit
4. **Lika att sträcka ut** - Lägg till en ny våg utan att ändra de som redan finns
5. **Observerbara** - Varje steg emiterar signaler som du kan övervaka

Det här är [Reduzerad RAG](/blog/reduced-rag) mönster i aktion: deterministisk extraktion framifrån , LLMs bara för syntesten.

---


## Använd fall: Stylobot Bot Detektor

[Stylobot](https://www.stylobot.net) är ett avancerat Bot-detektorsystem som använder StyloFlow för multi- -detektorn.

---


## Signal-drivna orkestreringsmönster

**Pattern 1: Ventilator**

Ett signal utlöser flera vågor:

```mermaid
graph LR
    S1[document.uploaded] --> W1[ChunkingWave]
    S1 --> W2[MetadataWave]
    S1 --> W3[LanguageDetectionWave]

    W1 -.signal.-> S2[document.chunked]
    W2 -.signal.-> S3[metadata.extracted]
    W3 -.signal.-> S4[language.detected]

    style S1 stroke:#339af0
    style S2 stroke:#339af0
    style S3 stroke:#339af0
    style S4 stroke:#339af0
    style W1 stroke:#51cf66
    style W2 stroke:#51cf66
    style W3 stroke:#51cf66
```

**Pattern 2: Sekvationell beroende**

vågor väntar på tidigare signaler:

```mermaid
graph LR
    W1[ExtractWave] -.signal.-> S1[text.extracted]
    S1 --> W2[ChunkWave]
    W2 -.signal.-> S2[text.chunked]
    S2 --> W3[EmbedWave]
    W3 -.signal.-> S3[embeddings.generated]

    style S1 stroke:#339af0
    style S2 stroke:#339af0
    style S3 stroke:#339af0
    style W1 stroke:#51cf66
    style W2 stroke:#51cf66
    style W3 stroke:#51cf66
```

**Pattern 3: villkorlig böjning**

Olika vågor körs baserat på signaler:

```mermaid
graph TD
    W1[DetectorWave] -.signal.-> S1{confidence}

    S1 -->|< 0.4| W2[RejectWave]
    S1 -->|0.4-0.7| W3[EscalateWave]
    S1 -->|> 0.7| W4[AcceptWave]

    W2 -.signal.-> S2[rejected]
    W3 -.signal.-> S3[escalated]
    W4 -.signal.-> S4[accepted]

    style S1 stroke:#ffd43b
    style S2 stroke:#ff6b6b
    style S3 stroke:#ff922b
    style S4 stroke:#51cf66
    style W1 stroke:#339af0
    style W2 stroke:#ff6b6b
    style W3 stroke:#ff922b
    style W4 stroke:#51cf66
```

**Pattern 4: Aggregation**

Flera signaler aktiverar en våg:

```mermaid
graph LR
    W1[Wave A] -.signal.-> S1[a.complete]
    W2[Wave B] -.signal.-> S2[b.complete]
    W3[Wave C] -.signal.-> S3[c.complete]

    S1 --> T{All Ready?}
    S2 --> T
    S3 --> T

    T -->|Yes| W4[AggregatorWave]
    W4 -.signal.-> S4[aggregation.complete]

    style S1 stroke:#339af0
    style S2 stroke:#339af0
    style S3 stroke:#339af0
    style S4 stroke:#51cf66
    style T stroke:#ffd43b
    style W4 stroke:#51cf66
```

---


## Escalationsmönster

StyloFlow stödjer eskalation på två nivåer:

1. **Internal koordinator**:vågor kontrollerar signalförtroende och kör villkorligt dyra steg
2. **Inter-koordinator**: EscalatorAtomvägssignaler från en snabb koordinator → dyr koordinator

Ett exempel från lucidRAG: Först körs snabb enhetens extraktion. Om kvalitet M SK2 0.7, EscalatorAtom förflyttar dokumentet till en dyr LLM förnyelsekoordinatörMSC4 Detta sparar 20x på kostnaderna genom att undvika dyra LLM-sändningar efter högkvalitetsextraktionerMska7

---


## Minimala form

> Det här är inte en snabb guide, det är det minsta exemplet som visar hur modellen passar ihop.

**Installation:**

```bash
dotnet add package StyloFlow.Complete
```

**Conceptual entry point:**

```csharp
// 1. Define a wave
public class MyAnalysisWave : IContentAnalysisWave
{
    public string Name => "MyAnalysis";
    public int Priority => 50;
    public bool Enabled { get; set; } = true;

    public bool ShouldRun(string path, AnalysisContext ctx) => true;

    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string path,
        AnalysisContext ctx,
        CancellationToken ct)
    {
        // Your analysis logic here
        var result = await AnalyzeAsync(path);

        return new[]
        {
            new Signal
            {
                Key = "my.signal",
                Value = result,
                Confidence = 1.0,
                Source = Name
            }
        };
    }
}

// 2. Register waves
var waves = new List<IContentAnalysisWave>
{
    new MyAnalysisWave(),
    new AnotherWave(),
};

// 3. Create coordinator
var coordinator = new WaveCoordinator(
    waves,
    CoordinatorProfile.Default);

// 4. Execute
var context = new AnalysisContext();
var results = await coordinator.ExecuteAsync(filePath, context);

// 5. Read signals
foreach (var signal in context.GetAllSignals())
{
    Console.WriteLine($"{signal.Key}: {signal.Value} ({signal.Confidence})");
}
```

**Med manifester:**

```csharp
// Load manifests from directory
var loader = new FileSystemManifestLoader("./manifests");
var manifests = await loader.LoadAllAsync();

// Build waves from manifests
var waves = manifests
    .Where(m => m.Enabled)
    .OrderBy(m => m.Priority)
    .Select(m => WaveFactory.Create(m))
    .ToList();

var coordinator = new WaveCoordinator(waves, profile);
```

För kompletta exempel, se [StyloFlow GitHubs arkiv](https://github.com/scottgal/styloflow).

---


## Workflow Discoverability: YAML Manifest

En av StyloFlow's viktigaste egenskaper är **arbetsflödet att upptäcka** - du kan förstå hela pipelinen bara genom att läsa manifesten . Ingen koddykning krävs

### Komplett lucidRAG Dokument Pipeline

Här är den faktiska manifestkatalogstrukturen för lucidRAG

```
manifests/
├── 01-file-type-detector.yaml
├── 02-chunking.yaml
├── 03-embedding.yaml
├── 04-entity-extraction.yaml
├── 05-quality-check.yaml
└── 06-escalation.yaml
```

**01-lêer -typ-detektorMska3yamlM Ska4**

```yaml
name: FileTypeDetector
priority: 100
enabled: true
description: Detects file type from extension

taxonomy:
  kind: sensor
  determinism: deterministic
  persistence: ephemeral

triggers:
  requires:
    - signal: document.uploaded
      condition: exists

emits:
  on_start:
    - file.detection.started
  on_complete:
    - key: file.extension
      type: string
      confidence_range: [1.0, 1.0]
    - key: file.mime_type
      type: string
      confidence_range: [1.0, 1.0]

lane:
  name: fast
  max_concurrency: 16

budget:
  max_duration: 10ms
```

**02-chunking**

```yaml
name: ChunkingWave
priority: 80
enabled: true
description: Splits documents into semantic chunks

taxonomy:
  kind: extractor
  determinism: deterministic
  persistence: ephemeral

input:
  accepts:
    - document.pdf
    - document.docx
    - document.markdown
  required_signals:
    - file.extension

triggers:
  requires:
    - signal: file.extension
      condition: in
      value: [".pdf", ".docx", ".md", ".txt"]

emits:
  on_complete:
    - key: document.chunked
      type: integer
      confidence_range: [1.0, 1.0]
    - key: chunks.cached
      type: boolean

lane:
  name: normal
  max_concurrency: 8

budget:
  max_duration: 30s

defaults:
  chunking:
    max_chunk_size: 512
    overlap: 50
    respect_boundaries: true
```

**03-**

```yaml
name: EmbeddingWave
priority: 60
ires:
    - signal: file.extension
      condition: in
      value: [".pdf", ".docx", ".md", ".txt"]

emits:
  on_complete:
    - key: document.chunked
      type: integer
      confidence_range: [1.0, 1.0]
    - key: chunks.cached
      type: boolean

lane:
  name: normal
  max_concurrency: 8

budget:
  max_duration: 30s

defaults:
  chunking:
    max_chunk_size: 512
    overlap: 50
    respect_boundaries: true
```

**03-**

```yaml
name: EmbeddingWave
priority: 60
enabled: true
description: Generates ONNX embeddings for chunks

taxonomy:
  kind: embedder
  determinism: deterministic
  persistence: cached

input:
  required_signals:
    - document.chunked
    - chunks.cached

triggers:
  requires:
    - signal: document.chunked
      condition: ">"
      value: 0

emits:
  on_complete:
    - key: embeddings.generated
      type: integer
      confidence_range: [1.0, 1.0]

lane:
  name: normal
  max_concurrency: 4

budget:
  max_duration: 2m
  max_cost: 0.0  # Local ONNX model

defaults:
  embedding:
    model: all-MiniLM-L6-v2
    batch_size: 32
```

**04-**

```yaml
name: EntityExtractionWave
priority: 60  # Same as embedding - runs in parallel
enabled: true
description: Extracts entities using IDF scoring

taxonomy:
  kind: extractor
  determinism: deterministic
  persistence: persisted

input:
  required_signals:
    - document.chunked

triggers:
  requires:
    - signal: document.chunked
      condition: ">"
      value: 0

emits:
  on_complete:
    - key: entities.extracted
      type: integer
      confidence_range: [0.0, 1.0]  # Confidence varies

lane:
  name: normal
  max_concurrency: 8

budget:
  max_duration: 1m

defaults:
  entity:
    min_idf_score: 2.5
    min_frequency: 2
    max_entities: 100
```

**05-**

```yaml
name: QualityCheckWave
priority: 40
enabled: true
description: Validates extraction quality

taxonomy:
  kind: gatekeeper
  determinism: deterministic
  persistence: ephemeral

input:
  required_signals:
    - embeddings.generated
    - entities.extracted

triggers:
  requires:
    - signal: embeddings.generated
      condition: ">"
      value: 0
    - signal: entities.extracted
      condition: exists

emits:
  on_complete:
    - key: quality.score
      type: double
      confidence_range: [0.0, 1.0]

  conditional:
    - key: escalation.needed
      when: quality.score < 0.7

lane:
  name: fast
  max_concurrency: 16

defaults:
  quality:
    min_embeddings: 5
    min_entity_confidence: 0.5
    threshold: 0.7
```

**06-**

```yaml
name: EscalationWave
priority: 20
enabled: true
description: Improves low-quality extractions using LLM

taxonomy:
  kind: proposer
  determinism: probabilistic
  persistence: persisted

input:
  required_signals:
    - escalation.needed

triggers:
  requires:
    - signal: escalation.needed
      condition: exists
  skip_when:
    - signal: budget.exhausted

emits:
  on_complete:
    - key: escalation.complete
      type: boolean
    - key: entities.improved
      type: integer
      confidence_range: [0.7, 1.0]

lane:
  name: llm
  max_concurrency: 2  # Expensive

budget:
  max_duration: 30s
  max_tokens: 4000
  max_cost: 0.05

defaults:
  llm:
    model: gpt-4o-mini
    temperature: 0.1
    prompt_template: entity_extraction
```

### Möjligheter med deklarativa manifest

När du tittar på de här plierna, så vet du omedelbart:

1. **Tilrättelse** - Prioritetsnummer
2. **beroenden** - Vad signalerar varje våg behöver köra
3. **Parallelism** - Embedding | (60) | och EntityExtraction |(60) | springer tillsammans
4. **Begränsningar för resurser** - Skillnade banor och samtida banor per våg
5. **villkorlig logik** - Escalation fungerar bara om kvalitet < 0.7
6. **kostnadsgränser** - Escalation har symboler och kostnadsgränser

**Inget kodexlätande krävs.** arbetsflödet är självgående

### Kod-Publikerade atomer

Medan de tidigare exempelna visar fullt deklarerande YAML, vågor kan också vara **kod-baserade atomer** refererat i manifester:

```yaml
name: CustomAnalyzer
priority: 50
enabled: true
description: Custom analysis logic

# Reference a code-based atom implementation
implementation:
  assembly: MyProject.Analyzers
  type: MyProject.Analyzers.CustomAnalyzerWave
  method: AnalyzeAsync

# The manifest still declares the contract
taxonomy:
  kind: analyzer
  determinism: probabilistic

triggers:
  requires:
    - signal: data.ready

emits:
  on_complete:
    - key: analysis.complete
      confidence_range: [0.0, 1.0]

lane:
  name: normal
  max_concurrency: 4

# Configuration values passed to the atom
defaults:
  threshold: 0.75
  max_iterations: 10
```

Implementering av C#

```csharp
public class CustomAnalyzerWave : ConfiguredComponentBase, IContentAnalysisWave
{
    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string path,
        AnalysisContext ctx,
        CancellationToken ct)
    {
        // Access manifest config
        var threshold = GetParam<double>("threshold", 0.75);
        var maxIterations = GetParam<int>("max_iterations", 10);

        // Custom logic here
        var result = await PerformComplexAnalysis(path, threshold, maxIterations);

        return new[]
        {
            new Signal
            {
                Key = "analysis.complete",
                Value = result.Score,
                Confidence = result.Confidence,
                Source = Name
            }
        };
    }
}
```

**Möjligheter:**

- **Manifestet deklarerar kontraktet** - utlösar , signaler , budget , bana
- **Kod ger implementering** - komplex logik
- **Konfiguration strömmar genom** - manifest defaults överrider koddefaults
- **Att testa självständighet** - Testkod utan manifester, validera manifester utan att köra kod

Den här hybrida tillvägagångssätten ger dig deklarativt discovery av arbetsflödet medan du håller komplex logik i underhållbar C#.

### Pipelinevisualisering från manifest

Den manifesterade strukturen gör det obetydligt att skapa visualiseringar:

```mermaid
graph TD
    DOC[document.uploaded] --> FT[FileTypeDetector<br/>Priority: 100<br/>Lane: fast]
    FT --> EXT[file.extension]

    EXT --> CH[ChunkingWave<br/>Priority: 80<br/>Lane: normal]
    CH --> CHUNKED[document.chunked]

    CHUNKED --> EMB[EmbeddingWave<br/>Priority: 60<br/>Lane: normal]
    CHUNKED --> ENT[EntityExtractionWave<br/>Priority: 60<br/>Lane: normal]

    EMB --> EMBGEN[embeddings.generated]
    ENT --> ENTEX[entities.extracted]

    EMBGEN --> QC[QualityCheckWave<br/>Priority: 40<br/>Lane: fast]
    ENTEX --> QC

    QC --> QSCORE[quality.score]
    QC -.conditional.-> ESC_NEED[escalation.needed]

    ESC_NEED -.-> ESC[EscalationWave<br/>Priority: 20<br/>Lane: llm]
    ESC --> ESC_DONE[escalation.complete]

    style DOC stroke:#339af0
    style FT stroke:#51cf66
    style CH stroke:#51cf66
    style EMB stroke:#51cf66
    style ENT stroke:#51cf66
    style QC stroke:#ffd43b
    style ESC stroke:#ff922b
```

Det här diagrammet skapades programmerat från YAML-manifesterna - ingen handtekening.

---


## Förutom: med kod LLMs — StyloFlow Way

En oväntad egenskap av StyloFlow är att den skapar ett system **LLMs kan resonera på ett säkert sätt**.

De flesta försök att använda LLMs för debugging eller orkestering misslyckas eftersom systemet de droppat in i är osynligt.

* Staten är impliterad
* Kontrollflödet är gömt i kod
* Beslut är kodade som biverkningar
* Protokoll är narrativa, inte orsaksmässiga

StyloFlow gör motsatsen **explicita, oföränderliga fakta** om vad som hände

Det gör att kod LLMs verkligen är användbara, inte som actorer, utan som **analytiker**.

### LLMs skäl *om* systemet, inte *inuti* det

I StyloFlow

* Triggerar ប្រតិបត្តិing
* Emiterar signaler
* Mutater tillstånd
* Han äger besluten

Istället, ",", får man ett **Signalsink-bilden** och ställde frågor som:

* " Varför skalade denna våg upp
* " Vilket signal orsakade att den här vägen kördes
* "Var är självförtroendet lägst
* " Vilket uppströmssignal motsäger detta resultat
* " Vad skulle hända om denna tröskel skulle höjas

Ett exempel på inmatning till en kod LLM:

```json
{
  "operation": "doc-123",
  "signals": [
    { "key": "document.chunked", "value": 12, "confidence": 1.0, "source": "ChunkingWave" },
    { "key": "entities.extracted", "value": 4, "confidence": 0.42, "source": "EntityWave" },
    { "key": "quality.score", "value": 0.39, "source": "QualityCheckWave" },
    { "key": "escalation.needed", "source": "QualityCheckWave" }
  ]
}
```

Det är inte en logström **tänkande substans**.

En kod LLM kan nu:

* Förklaring av orsakssambandet ("försämring utlöst på grund av kvalitet
* Identifiera svaga länkar (" enhetens extraktionsförtroende dominerar misslyckanden ")
* Suggest för dämpningar ("driv en annan extraktor innan du skalar upp
* Föreställ Konfigurationsförändringar (" lägre enheten min - IDF för PDFs")

Allt utan att bli tillit till *göra* vad som helst.

### Debugging blir inspektion , inte återskapande

Den traditionella "LLM-debuggen " försöker spela om världen

> "" Här är koden och några loger "".

StyloFlow-debugging är enklare:

> " Här är det exakta tillståndet som systemet observerat

Eftersom signaler är oförändliga och ägande,

LLMs skäl till fakta du redan litar på.

### Varför blir detta inte till agentteater?

Detta fungerar bara på grund av strikta gränser:

* LLM kan **analysera** signaler
* Deterministisk kod **handlingar** på signaler
* Bara manifesterar och koder ändrar beteende

Det finns ingen återkopplingsloop där LLM " avfärdar " nästa steg | | . | Maximmundo | МSK3 | föreslår förklaringar eller konfigurationsförstånd som kan tillämpas senare på en mänsklig ♫ ( ♫ eller deterministisk policy ♫

Att asymmetry är avsiktligt.

### En sida- ---effekt, :- -futurellt själv- --- -avpassning utan självstyre

När signaler, ,, självförtroende och resultat är uppenbara, *kan* senare:

* Minehistoriska signalspår
* Bedöm vilka escalationer som hjälpte till
* Avstängda tröskeln
* Förstärk eller sänka vågor mellan banor

Inget av det kräver att en LLM kör systemet.

LLM blir en **diagnostisk lins**, inte en kontrollplattaM SK1

### Varför är detta viktigt?

StyloFlow gör inte bara att sannolikhetssystem är säkra

Det gör dem **läsbar** — till människor , till tester M SK2 och till LLMs ♫ — ♫ utan att ge upp kontroll

Det är skillnaden mellan

* "LLMs som driver din system
* och "LLMs förstå systemet

Bara en av dessa skalor

---


## Nyckliga egenskaper

**1. Deklarerande sammansättning**

Komponenter deklarerar sina kontrakt. ( triggar, , signaler, M SK2 budget, ),, inte deras beroenden. ♫ . ♫ Systemet räknar ut vad som utförs, ♫ МSK5 ♫ Det här är ingen egenskap, ♪ ' ♫ det är - ♫ ♫ vad som händer när man först skapar signaler,

**2. Observerbart standardmässigt**

Varje handling är en signal.

**3. Adaptiv utführung**

Tillförtroende poäng driver branchning utan explicit vägledningslogik. Springa över dyra steg när det är onötigt , upphöja när du inte är säker M SK2 avbryta tidigt på hög nivå - tillförtrode misslyckanden

**4. Testbarhet utan att mocka ramverk**

Mocksignaler, inte komponenter :

```csharp
var context = new AnalysisContext();
context.AddSignal(new Signal
{
    Key = "document.chunked",
    Value = 10,
    Confidence = 1.0,
    Source = "Test"
});

var wave = new EmbeddingWave();
var results = await wave.AnalyzeAsync(path, context, ct);

Assert.Single(results);
Assert.Equal("embeddings.generated", results.First().Key);
```

**5. Tillväxt komplexitet**

Börja enkelt:

```csharp
var coordinator = new EphemeralWorkCoordinator<Job>(ProcessAsync);
```

Lägg till signaler när det behövs:

```csharp
new EphemeralOptions { Signals = signalSink }
```

Lägg till vågor för multi

```csharp
var waveCoordinator = new WaveCoordinator(waves, profile);
```

Lägg till manifester för deklarativ config:

```yaml
name: MyWave
triggers: [...]
emits: [...]
```

---


## Komplett Pipeline: lucidRAG Dokument Ingestion

Här är den kompletta versionen [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) Pipeline at a glance (se de detaljerade kodexexamterna i sectionen """, "Use Case, : "", och "Ljudrig RAG Document Processing," " "" och ):.

1. **ladda upp** → `document.uploaded` signal
2. **FileTypeWave** detekterar PDF/DOCXM SK1Markdown → `file.extension` signal
3. **Extraktionsvåg** drar text och struktur → `text.extracted` signal
4. **Månningvåg** delar sig semantiskt → `document.chunked` signal
5. **EmbeddingWave** genererar vektorer (parallel) → `embeddings.generated` signal
6. **EntityWave** extraherar enheter (parallelM SK1 → `entities.extracted` signal
7. **Jaktvåg** kontrollerar komplettitet → `quality.score` signal
8. **Escalationvåg** (förbestämd om kvalitet `escalation.complete` signal
9. **StorageWave** fortsätter till Qdrant + PostgreSQL → `storage.complete` signal

Interfejsen Abonnerar SignalSink för reala framsteguppdateringar (push-mönster

```csharp
// Subscribe to sink for push notifications
signalSink.Subscribe(signal => {
    if (signal.Key.StartsWith("document."))
    {
        await _hub.Clients.User(userId)
            .SendAsync("DocumentProgress", new
            {
                stage = signal.Key,
                progress = CalculateProgress(signal),
                operationId = signal.OperationId
            });
    }
});
```

Eller använda pull pattern , om du föredrar att rösta

```csharp
// Query SignalSink for document progress (pull pattern)
var documentSignals = signalSink.GetSignals()
    .Where(s => s.Key.StartsWith("document.") &&
                s.Timestamp > lastCheck);

foreach (var signal in documentSignals)
{
    UpdateProgressUI(signal);
}
```

**Nyckelpunkt:** Du Abonnerar SINK: n ( som tittar på alla atomer ), inte på enskilda operationar M SK2 Atomernas egna signaler ; som låter dig trycka MSC4 Abonnera МSK5 och dra

Det här är hur [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) bearbetar dokument, data, , och bilder genom en enificerad signal, driven pipeline, [DocSummarizer](/blog/building-a-document-summarizer-with-rag), [DataSummarizer](/blog/datasummarizer-how-it-works), och [ImageSummarizer](/blog/constrained-fuzzy-image-intelligence) under en orkesterlag.

---


## Komplett Pipeline: Stylobot Bot Detektor

Här är den kompletta versionen [Stylobot](https://www.stylobot.net) Pipeline at a glance (se detaljerad kod i "Escalation: From Fast to Thorough

1. **IpReputationWave** kontrollerar IP mot kända botlisten (< 10ms) | `bot.detected` -signal med självförtroende
2. **beteendeanalysvåg** (förbedingt om 0.4 ♫ ♫ < tillit ♫ `bot.detected` signal
3. **LlmBotanalysvåg** ( villkorlig om det fortfarande är tvetydigt ) använder LLM för konversationsanalys `bot.detected` signal

Den viktigaste vinsten, :, escalation baserat på självförtroende.

```csharp
// ❌ Traditional: Every request gets expensive analysis
var reputation = await CheckIpAsync(ip);
var behavior = await AnalyzeBehaviorAsync(session);  // Even if IP is known bad
var llmScore = await LlmAnalysisAsync(conversation);  // Always expensive

// ✅ StyloFlow: Waves run based on confidence signals
// BehaviorAnalysis only runs if confidence is ambiguous (0.4-0.7)
// LLM analysis only runs if still unsure after behavior check
```

**Tilldelning av kostnaderna:** IP-kontrollkostnader $0 och kör 100% av tiden. Behaviorell analys kör ♫ 30% ♫ ♫ **$0.0001** i jämförelse med naivt "LLM allt " på **$0.002** (20x sparar

---


## jämförelse med andra Workflow-motorer

| Funktionen | StyloFlow ♫ ♫ | ♫ Temporal ♫
|---------|-----------|----------|---------|----------------|
| **Koordinering** | Signal -driven ♫ ♫ | ♫ RPC ♫
| **Deklarativt** |  ✅ YAML-manifester
| **Bedingande** | ✅ Signaltrigger | | | ✅ | villkoren || | МSK5 | böjning | | | ✅ | valval ||
| **Eskalation** | ✅ byggt- i SSK3 | | ❌ | Handbook | | SSK6 | handbook
| **Observerbarhet** | ✅ Signalspårning | | | МSK3 | Historien av arbetsflödet
| **Budjetkontroll** | ♫ ✅ ♫ Token ♫
| **Lokalt utförande** | ✅ Iprocessen | - | | 3 | 4 | Benötigt kluster || | МSK6 | Befordrar kluster
| **Konkurenssbanor** | ✅ Fast/NormalM SK3LLM ♫ ♫ | ♫

**Där den här modellen passar naturligt**

- AI/ML-rörsledningar med uppbyggnad (billigt → dyrt
- Dokumentbehandling med villkorliga steg
- Bot-detektor med multi-steganalys
- RAG-system med hybridsökning + generation
- Alla arbetsflöden där komponenter reagerar på förtroendevärderingar

**Där det inte fungerar**

- Enkela sequentiella jobb (en tidiga koordinator är tillräckligt
- Fortskridna, fördelade arbetsflöden över datacenter (Temporal löser detta)
- lång tid-drivande arbetsflöden med mänskligt godkännande
- Workflowversioner med schema migration (Temporal)

---


## Var den här modellen leder

> De är naturliga förlängningar av modellen, inte åtaganden att implementera den specifikt.

När semantiken stabiliseras genom utveckling av lucidRAG och Stylobot, så blir dessa mönster livskraftiga.

**1. Utlärning från signaler**

Träg vilka eskalationsvägar som fungerar bäst:

```csharp
// Did the LLM escalation improve accuracy?
// Learn to skip it if behavioral analysis is sufficient
```

**2. kostnadsoptimering**

Automatisk körning baserat på tidigare resultat:

```csharp
// If a "slow" wave completes quickly, promote to "normal"
```

**3. Signaluppspelning**

Debug genom att spela upp signalsekvenser igen:

```csharp
var replay = SignalReplay.FromFile("trace.jsonl");
await coordinator.ReplayAsync(replay);
```

**4. Multi-**

Distribuera banor över maskiner samtidigt som signalerna är centraliserade.

---


## Varför signaler är viktiga

Kerninsikten är den här: **i AI-system, ,, har varje komponent självförtroende**.

Traditionella arbetsflöden förutsätter framgång

- **Förtroende poäng** - Hur säker är vi på det?
- **Bedingligt utförande** - Gå över dyra steg om du är självsäker
- **Eskalation** - Försök hårdare när du inte är säker
- **Aggregation** - Kombinera flera signaler

Signaler ger detta naturligt:

```csharp
// Multiple detectors vote
var signals = context.GetSignals("bot.detected");

// Aggregate by confidence
var verdict = signals
    .OrderByDescending(s => s.Confidence)
    .First();

// Or majority vote
var isBot = signals
    .Count(s => (bool)s.Value) > signals.Count() / 2;

// Or weighted average
var score = signals
    .Sum(s => (bool)s.Value ? s.Confidence : -s.Confidence)
    / signals.Count();
```

Det är därför StyloFlow fungerar bra för [Reduzerad RAG](/blog/reduced-rag) - varje extraktionsstadium producerar en självförtroende poäng , och syntetiseringen sker bara när självför tro är tillräckligt hög

---


## sammanfattning

**Ausführungsmodellen:**

- Signaler som första fakta i klass - (, inte händelser eller meddelanden
- Tilltrovärdighet drivkraftskontrollflöde
- Rörtor koordinerar genom aktivatorer, inte direkt anslutningar
- Ständer tvinga resursers gränser
- byggt på [mestlucid.ephemeral](/blog/ephemeral-execution-library)

**Varför är signaler viktiga:**

1. **Stabila fördelningsgränser** - Serialiserad , timestampedd, självgåendeM SK3inklusiv
2. **Deklarerande sammansättning** - Manifest definierar kontrakt
3. **Adaptiv ruttering** - Confidence gör eskalering utan att ha hårdkoderade ramverk
4. **Enkel observabilitet** - Varje handling är redan en signal
5. **Klara ägande** - Atomernas egna signaler

**Arbetsimplementeringar:**

- [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) - Cross -modell dokument Q&A med villkorlig väsenutvinning
- [Stylobot](https://www.stylobot.net) - Bot-detektorn med självförtroende-driven escalation IP | | → | beteendet
- [Reduzerad RAG](/blog/reduced-rag) - Deterministisk extraktion

**Related articles:**

- [Den tidiga avrättelsebiblioteket](/blog/ephemeral-execution-library) - grunden
- [Reduzerad RAG](/blog/reduced-rag) - Varför är deterministisk extraktion viktig
- [LRU och kapacitet](/blog/learning-lrus-when-capacity-makes-systems-better) - minne-gränsade fönster
- [Begränsat Fuzzy Kontexttdragning](/blog/constrained-fuzzy-context-dragging) - Teorin

**källkod:** [GitHub - StyloFlow](https://github.com/scottgal/styloflow)

---


## Kerninsikten

Traditionella arbetsflödesmotorer ber dig att **vad händer sedan?**. Den här modellen ber komponenterna att deklarera **vad de producerar** och **vad de behöver**, så låter signalerna koordinera utdraget

Nyckelns förändring: **signaler avkopplar , förtroende vägledningar, banaer skyddar**.

Det här handlar inte om att välja StyloFlow över Temporal eller Airflow, utan att - löser olika problem.

Om du bygger AI, /, ML, rör där?

- Förtroende är viktigt ( inte bara framgång
- Eskalation är strukturell ( inte en särskild fall )
- Komponenter borde inte tala om varandra
- Upplevbarheten bör vara inhärdlig ( inte bostad på )

"...", då passar den här tolkningssemantiken kanske till vad du tror

Den [tidiga bibliotek](/blog/ephemeral-execution-library) är den stabila grunden.

För frågor eller feedback [GitHubs arkiv](https://github.com/scottgal/styloflow).