---
audience: engineers
summary: "End-to-end ScaiCore example \u2014 a multi-stage content generation and\
  \ review pipeline using the pipeline operators."
title: 'Example: content pipeline'
path: reference/language/examples/content-pipeline
status: published
---

A multi-stage content creation system with composable transformers,
quality gates, multi-LLM orchestration, and publishing integration.

```scaicore
// ============================================================================
// content-pipeline/main.scaicore
// ============================================================================

@core ContentPipeline {
    version = "1.0.0"
    description = "Multi-stage content creation, review, and publishing"

    @plugins {
        scaidrive = scailabs/scaidrive@1.0
        scaicms = scailabs/scaicms@1.0
        image_gen = scailabs/image-gen@1.0
        plagiarism = scailabs/plagiarism-check@1.0
        seo_analyzer = scailabs/seo-tools@1.0
        analytics = scailabs/analytics@1.0
    }

    @llm {
        drafter = {
            model = "scailabs/poolnoodle-omni"
            temperature = 0.9
            role = "creator"
            system_context = """
                You are a creative writer. Be original, engaging,
                and don't self-censor during drafting. Take risks.
            """
        }
        critic = {
            model = "scailabs/poolnoodle-omni"
            temperature = 0.2
            role = "reviewer"
            system_context = """
                You are a demanding editor. Find weaknesses,
                unclear arguments, missed opportunities. Be specific.
            """
        }
        refiner = {
            model = "scailabs/poolnoodle-omni"
            temperature = 0.5
            role = "refiner"
            system_context = """
                You improve content based on feedback while
                preserving the original voice and intent.
            """
        }
        polisher = {
            model = "scailabs/poolnoodle-omni"
            temperature = 0.2
            role = "finalizer"
            system_context = """
                You are a copy editor. Grammar, flow, consistency.
                Make minimal changes for maximum impact.
            """
        }
        utility = {
            model = "scailabs/poolnoodle-mini"
            temperature = 0.3
            role = "utility"
            use_when = "metadata, tagging, simple transforms"
        }
    }

    @memory {
        style_guides: map[string, StyleGuide]
        past_performance: array[PerformanceRecord]
        editorial_feedback: array[EditorialFeedback]
        audience_insights: array[AudienceInsight]
    }

    // Read-only reference data — brand guidelines, tone templates
    @reference {
        brand_guidelines: map[string, BrandGuideline]
        tone_templates: map[string, ToneTemplate]
        seo_keyword_lists: map[string, array[string]]
    }

    @config {
        @param default_quality_threshold: float = 0.8 @hot_reload {
            description = "Minimum quality score to pass"
        }

        @param max_refinement_iterations: int = 3 @hot_reload @runtime_configurable {
            description = "Maximum refinement loop iterations"
        }
    }

    @triggers {
        @api create_content {
            flow = create_content
        }
        @webhook cms_request {
            flow = create_content
            path = "/webhooks/scaicms"
        }
    }
}


// ============================================================================
// Types
// ============================================================================

@types {
    type Brief = {
        content_type: string,
        brand: string?,
        output_format: enum[markdown, html, plaintext],
        target_audience: string?,
        tone: string?,
        constraints: BriefConstraints?,
        deadline: datetime?,
        publish_config: PublishConfig?,
        requester: Person
    }

    type BriefConstraints = {
        max_words: int?,
        min_words: int?,
        required_topics: array[string]?,
        forbidden_topics: array[string]?
    }

    type PublishConfig = {
        platform: string,
        schedule: datetime?,
        auto_publish: bool
    }

    type Person = {
        id: string,
        name: string,
        email: email?,
        role: string?
    }

    type Content = {
        id: uuid,
        body: string,
        format: enum[markdown, html, plaintext],
        metadata: Metadata,
        version: int,
        lineage: array[ContentVersion],
        score: QualityScore?
    }

    type Metadata = {
        title: string?,
        summary: string?,
        tags: array[string],
        seo: SEOData?,
        target_audience: string?,
        tone: string?,
        word_count: int
    }

    type SEOData = {
        meta_title: string,
        meta_description: string,
        keywords: array[string],
        readability_score: float
    }

    type ContentVersion = {
        version: int,
        transformer: string,
        timestamp: datetime,
        diff_from_previous: string?
    }

    type QualityScore = {
        overall: float,
        dimensions: {
            clarity: float,
            engagement: float,
            accuracy: float,
            originality: float,
            seo: float,
            brand_alignment: float
        },
        issues: array[Issue],
        passed: bool
    }

    type Issue = {
        severity: enum[blocker, major, minor, suggestion],
        category: string,
        location: string?,
        description: string,
        suggestion: string?
    }

    type Review = {
        strengths: array[string],
        weaknesses: array[Weakness],
        structural_feedback: string,
        voice_consistency: float,
        recommendation: enum[accept, revise, rewrite]
    }

    type Weakness = {
        issue: string,
        location: string?,
        severity: enum[blocker, major, minor],
        suggestion: string
    }

    type QualityStandards = {
        threshold: float,
        weights: map[string, float],
        criteria: Criteria
    }

    type Criteria = {
        clarity: { weight: float, min_score: float? },
        engagement: { weight: float, min_score: float? },
        accuracy: { weight: float, min_score: float? },
        originality: { weight: float, min_score: float? },
        brand_alignment: { weight: float, min_score: float? }
    }

    type StyleGuide = {
        brand: string,
        voice: string,
        dos: array[string],
        donts: array[string],
        examples: array[string]
    }

    type PerformanceRecord = {
        content_id: uuid,
        published_at: datetime,
        engagement_score: float,
        topics: array[string]
    }

    type EditorialFeedback = {
        pattern: string,
        correction: string,
        frequency: int
    }

    type AudienceInsight = {
        topic: string,
        engagement: float,
        audience_segment: string
    }
}


// ============================================================================
// Composed Pipelines
// ============================================================================

@pipeline BlogPostPipeline = {
    Draft
    |> EnrichMetadata
    |~> RefineLoop(BlogStandards), until = quality_passes, max = 3
    |> Polish
    |> FinalQualityGate(BlogStandards)
}

@pipeline SocialMediaPipeline = {
    Draft
    |> RefineLoop(SocialStandards), until = quality_passes, max = 2
    |*> [
        FormatForPlatform("twitter"),
        FormatForPlatform("linkedin"),
        FormatForPlatform("instagram")
    ], merge = PackageMultiPlatform
}

@pipeline EmailNewsletterPipeline = {
    Draft
    |> EnrichMetadata
    |> Critique
    |> Refine
    |> Polish
    |> FormatEmail
}


// ============================================================================
// Main Flow
// ============================================================================

@flow create_content(brief: Brief): Content {
    @budget {
        max_duration = 120s
        on_exceeded = "warn"
    }

    @rigid {
        validated_brief = validate(brief, Brief.schema)
        standards = QualityStandards.for(brief.content_type, brief.brand)

        // Load brand guidelines from reference data
        brand_guide = brief.brand ? reference.brand_guidelines.get(brief.brand) : null
    }

    // Execute the appropriate pipeline
    content = match brief.content_type {
        "blog_post" => BlogPostPipeline(validated_brief)
        "social_media" => SocialMediaPipeline(validated_brief)
        "email_newsletter" => EmailNewsletterPipeline(validated_brief)
        _ => BlogPostPipeline(validated_brief)
    }

    // Handle final result
    match content.score.passed {
        true => @call publish_content(content, brief.publish_config)
        false => @call human_review_gate(content, brief)
    }

    // Emit for analytics and learning
    emit content_created {
        content_type = brief.content_type
        brand = brief.brand
        quality_score = content.score.overall
        passed = content.score.passed
        pipeline_duration_ms = execution.usage.wall_clock_ms
        created_at = now()
    }

    return content
}


// ============================================================================
// Transformers
// ============================================================================

@transformer Draft(brief: Brief): Content {
    llm = drafter

    result = @flexible {
        goal = "Create initial draft from brief"
        input = brief
        context = memory.style_guides.get(brief.brand)
        output = {
            body: string,
            metadata: {
                title: string,
                summary: string,
                suggested_tags: array[string]
            }
        }
        guidance = """
            Write freely. Focus on the core message.
            Match the tone specified in the brief.
            Don't worry about perfection — that comes later.
        """
    }

    return Content.new({
        body = result.body,
        metadata = result.metadata,
        format = brief.output_format,
        version = 1,
        lineage = [{ version = 1, transformer = "Draft", timestamp = now() }]
    })
}


@transformer Critique(content: Content, criteria: Criteria): Review {
    llm = critic

    result = @flexible {
        goal = "Critically review content for quality and improvement opportunities"
        input = { content: content, criteria: criteria }
        context = memory.editorial_feedback
        output = Review
    }

    return result
}


@transformer Refine(content: Content, review: Review): Content {
    llm = refiner

    result = @flexible {
        goal = "Improve content based on critique feedback"
        input = { content: content, review: review }
        output = {
            body: string,
            changes_made: array[string],
            issues_addressed: array[string],
            issues_declined: array[{ issue: string, reason: string }]?
        }
        guidance = """
            Address all blocker and major issues.
            Preserve the original voice and key messages.
            Document what you changed and why.
        """
    }

    return content.evolve({
        body = result.body,
        version = content.version + 1,
        lineage = content.lineage.append({
            version = content.version + 1,
            transformer = "Refine",
            timestamp = now(),
            diff_from_previous = diff(content.body, result.body)
        })
    })
}


@transformer Polish(content: Content): Content {
    llm = polisher

    result = @flexible {
        goal = "Final polish and copy edit"
        input = content
        output = {
            body: string,
            corrections: array[{
                original: string,
                corrected: string,
                reason: string
            }]
        }
        guidance = """
            Fix grammar, punctuation, flow.
            Ensure consistency in style and terminology.
            Minimal changes — don't rewrite.
        """
    }

    return content.evolve({
        body = result.body,
        version = content.version + 1,
        lineage = content.lineage.append({
            version = content.version + 1,
            transformer = "Polish",
            timestamp = now()
        })
    })
}


@transformer EnrichMetadata(content: Content): Content {
    @parallel {
        seo = @flexible {
            goal = "Generate SEO metadata"
            llm = utility
            input = content
            output = SEOData
        }

        tags = @flexible {
            goal = "Generate relevant tags"
            llm = utility
            input = content
            output = { tags: array[string] }
        }

        summary = @flexible {
            goal = "Generate concise summary"
            llm = utility
            input = content
            output = { summary: string }
            constraints = { prefer = ["under 150 words"] }
        }
    }

    return content.evolve({
        metadata = content.metadata.merge({
            seo = seo,
            tags = tags.tags,
            summary = summary.summary
        })
    })
}


// ============================================================================
// Evaluators
// ============================================================================

@evaluator AssessQuality(content: Content, standards: QualityStandards): QualityScore {
    @parallel {
        llm_assessment = @flexible {
            goal = "Assess content quality against criteria"
            llm = critic
            input = { content: content, standards: standards }
            output = {
                clarity: float,
                engagement: float,
                accuracy_signals: float,
                originality: float,
                brand_alignment: float,
                issues: array[Issue]
            }
        }

        plagiarism_result = plagiarism.check(content.body)
        seo_result = seo_analyzer.analyze(content)
    }

    @rigid {
        score = QualityScore.compute({
            llm = llm_assessment,
            plagiarism = plagiarism_result,
            seo = seo_result,
            weights = standards.weights
        })

        score.passed = score.overall >= standards.threshold
            && plagiarism_result.score < 0.15
            && !score.issues.any(i => i.severity == :blocker)
    }

    return score
}


// ============================================================================
// Refinement Loop
// ============================================================================

@flow RefineLoop(content: Content, standards: QualityStandards): Content {
    review = Critique(content, standards.criteria)

    if review.recommendation == :rewrite {
        // Too broken to refine — start over with feedback
        return Draft(content.original_brief.with_feedback(review))
    }

    refined = Refine(content, review)
    score = AssessQuality(refined, standards)

    return refined.evolve({ score = score })
}


// ============================================================================
// Human Review Gate
// ============================================================================

@flow human_review_gate(content: Content, brief: Brief): Content {
    review_decision = @checkpoint {
        type = "review"
        assignee = "editorial-team"
        timeout = 24h
        on_timeout = "escalate"

        present = {
            content = content,
            quality_score = content.score,
            lineage = content.lineage,
            brief = brief
        }

        options = ["approve", "request_changes", "reject"]
    }

    match review_decision.decision {
        "approve" => return content
        "request_changes" => {
            // Refine based on human feedback
            refined = Refine(content, review_decision.feedback)
            score = AssessQuality(refined, QualityStandards.for(brief.content_type, brief.brand))
            return refined.evolve({ score = score })
        }
        "reject" => {
            log.info("Content rejected by editorial: ${review_decision.notes}")
            return content.evolve({ status = :rejected })
        }
    }
}


// ============================================================================
// Publishing
// ============================================================================

@flow publish_content(content: Content, publish_config: PublishConfig?) {
    if publish_config == null {
        return
    }

    @rigid {
        scaicms.publish(
            content = content,
            platform = publish_config.platform,
            schedule = publish_config.schedule
        )

        scaidrive.store(
            file = content.body,
            path = "/content/published/${now().format('YYYY-MM')}/${content.id}.${content.format}",
            metadata = content.metadata
        )
    }
}


// ============================================================================
// Tests
// ============================================================================

@test flow test_draft_creates_content {
    description = "Verifies Draft transformer produces valid Content"

    @given {
        brief = {
            content_type = "blog_post",
            brand = "tech-blog",
            output_format = :markdown,
            target_audience = "developers",
            tone = "informative but casual",
            requester = { id = "user-1", name = "Marcel" }
        }

        @mock llm:drafter {
            response = {
                body: "# AI in 2026\n\nThe landscape has changed dramatically...",
                metadata: {
                    title: "AI in 2026: What's Changed",
                    summary: "A look at the evolving AI landscape",
                    suggested_tags: ["ai", "technology", "2026"]
                }
            }
        }
    }

    @when {
        content = Draft(brief)
    }

    @then {
        assert content.body.length > 0
        assert content.version == 1
        assert content.lineage.length == 1
        assert content.lineage[0].transformer == "Draft"
        assert content.metadata.title == "AI in 2026: What's Changed"
    }
}

@test flow test_quality_gate_blocks_low_quality {
    description = "Content below quality threshold gets flagged"

    @given {
        content = Content.new({
            body = "This is mediocre content.",
            format = :markdown,
            version = 1
        })

        standards = { threshold = 0.8, weights = { clarity: 0.3, engagement: 0.3, originality: 0.4 } }

        @mock llm:critic {
            response = { clarity: 0.5, engagement: 0.4, originality: 0.3, issues: [] }
        }

        @mock plugin:plagiarism { check = { score: 0.02 } }
        @mock plugin:seo_analyzer { analyze = { score: 0.6 } }
    }

    @when {
        score = AssessQuality(content, standards)
    }

    @then {
        assert score.passed == false
        assert score.overall < 0.8
    }
}
```