---
audience: engineers
summary: 'Configuration blocks inside a @core: @config, @memory, @reference, @constraints,
  @triggers, @llm, @plugins, @instance, @identity.'
title: Core declaration blocks
path: reference/language/core-declaration-blocks
status: published
---

### 5.1 `@plugins`

```scaicore
@plugins {
    crm = company/salesforce@1.0 {
        instance = "production"
        api_version = "v58"
    }
    ocr = scailabs/document-ocr@2.0
    scaidrive = scailabs/scaidrive@1.0
    erp = company/exact-online@3.0
}
```

### 5.2 `@llm` / `@models` — AI Model Declarations

`@models` is the preferred form; `@llm` is accepted for backward compatibility.
Both are identical in behavior. Each entry declares a named model role with
provider, model identifier, and modality configuration.

```scaicore
@models {
    // Text completion / reasoning models
    primary = {
        provider = "scaigrid"           // "scaigrid" | "openai"
        model = "scailabs/poolnoodle-omni"
        temperature = 0.5
        role = "general"
        modalities = [:text, :structured_output, :vision]
        fallback = [
            { provider = "scaigrid", model = "scailabs/poolnoodle-turbo" }
        ]
    }
    fast = {
        provider = "scaigrid"
        model = "scailabs/poolnoodle-mini"
        temperature = 0.3
        role = "utility"
        modalities = [:text, :structured_output]
        use_when = "classification, simple extraction, tagging"
    }
    creative = {
        provider = "scaigrid"
        model = "scailabs/poolnoodle-omni"
        temperature = 0.9
        role = "creator"
        modalities = [:text]
    }
    critic = {
        provider = "scaigrid"
        model = "scailabs/poolnoodle-omni"
        temperature = 0.2
        role = "reviewer"
        modalities = [:text, :structured_output]
    }

    // Non-text modalities
    voice = {
        provider = "scaigrid"
        model = "scai-tts-1"
        role = "voice"
        modalities = [:tts]
    }
    transcriber = {
        provider = "openai"
        model = "whisper-1"
        role = "transcription"
        modalities = [:stt]
    }
    embedder = {
        provider = "scaigrid"
        model = "scai-embed-1"
        role = "embedding"
        modalities = [:embedding]
    }
}
```

When `provider` is omitted, defaults to `"scaigrid"`. When `modalities` is
omitted, defaults to `[:text, :structured_output]`. See Model Provider spec
for the full provider interface and supported modalities.

### 5.3 `@memory`

Persistent state owned exclusively by the instance. For `:entity` Cores,
each entity key gets its own partition. For `:stateless` Cores, memory
is per-Core (one partition, atomic ops). For `:singleton`, one partition.

**No instance can access another instance's memory.**

```scaicore
@memory {
    vendor_aliases: map[string, string]
    categorization_history: array[CategorizationRecord]
    interaction_count: int
}
```

Access via `memory.*` (see §9 Memory API).

### 5.4 `@config`

```scaicore
@config {
    @param api_endpoint: string {
        description = "CRM API endpoint"
        required = true
    }

    @param max_retries: int = 3 @hot_reload {
        description = "Maximum retry attempts"
        validation = value >= 0 && value <= 10
    }

    @param urgency_threshold: float = 0.7 @runtime_configurable {
        description = "Threshold for urgent escalation"
        validation = value >= 0.0 && value <= 1.0
    }

    @param api_key: string @secret {
        description = "CRM API key"
        required = true
    }

    @param keywords: array[string] = ["urgent", "legal"] @hot_reload @runtime_configurable {
        description = "Keywords that trigger escalation"
    }
}
```

### 5.5 `@constraints`

```scaicore
@constraints {
    never = [
        "promise refund > €100 without approval",
        "share customer data with other customers",
        "admit legal liability"
    ]
    always = [
        "log all interactions to CRM",
        "identify customer before discussing account details",
        "respect GDPR data access/deletion requests"
    ]
    prefer = [
        "resolve without escalation when possible",
        "de-escalation over defensiveness"
    ]
}
```

### 5.6 `@conversation_policy`

```scaicore
@conversation_policy {
    routing = {
        match_strategy = "flexible"
        match_on = [sender, session_id, topic_similarity]
        similarity_threshold = 0.8
        no_match = "new_conversation"
    }

    context = {
        always = [customer.profile, customer.tier]
        if_relevant = [customer.billing_status, customer.recent_tickets(30d)]
        on_demand = [customer.full_history]
        max_history_turns = 50
    }

    timeout = {
        idle = 30m
        absolute = 4h
        idle_warning = 25m
        idle_message = "Are you still there?"
    }

    channels = [chat, email, api, internal]
}
```

### 5.7 `@reference` — Read-Only Reference Data

Data injected at deployment time. Available to all instances of a Core.
Immutable at runtime — no instance can write to it. Replaces the need
for shared memory in most cases.

```scaicore
@reference {
    faq: map[string, FAQEntry]                   // loaded from faq.json
    product_catalog: array[Product]              // loaded from catalog.json
    escalation_rules: array[EscalationRule]      // loaded from rules.json
    compliance_templates: map[string, Template]  // loaded from templates/
}
```

Access in flows via `reference.*`:

```scaicore
@flow handle_question(customer_id: string, question: string): Response {
    @rigid {
        // Read-only — same for all instances, fast local reads
        relevant_faq = reference.faq.search(question)
        rules = reference.escalation_rules
    }
}
```

**Key properties:**
- Loaded at Core deployment or activation time
- Source: files in deployment bundle or external URIs
- Refresh: redeployment or host-level refresh signal
- Can be cached in-memory (immutable → no invalidation needed)

### 5.8 `@triggers` — Trigger Declarations

Declares how external events map to flows:

```scaicore
@triggers {
    @webhook invoice_uploaded {
        flow = process_invoice
        method = "POST"
        path = "/webhooks/invoice"
        auth = "hmac"
    }

    @schedule daily_reconcile {
        flow = reconcile_batch
        cron = "0 2 * * *"
        timezone = "Europe/Amsterdam"
    }

    @api process {
        flow = process_invoice
        // Exposed as: POST /cores/{core_id}/flows/process
    }
}
```

Trigger dispatch is a Host responsibility — the runtime declares
triggers, the Host implements the transport (HTTP, cron, etc.).

### 5.9 `@on` — Event Subscriptions

Subscribe to events emitted by other Cores:

```scaicore
@on invoice_processed from core://invoice-processor {
    flow = record_transaction
}

@on payment_received from core://payment-gateway {
    flow = reconcile_payment
}
```

Event types can be declared in `@core_interface` for compile-time
type safety. Events are delivered at-least-once with per-source ordering.

### 5.10 `@internal` — Internal Flow Marker

Marks a flow as not reachable from triggers. Internal flows don't need
the entity key parameter (they're already running within an instance context):

```scaicore
@internal
@flow build_context(): ConversationContext {
    // Called only via @call from other flows within this Core
    // Does not need customer_id parameter even though
    // this Core is :entity(key = "customer_id")
    @rigid {
        return {
            history: memory.interaction_history.last(10),
            preferences: memory.preferences
        }
    }
}
```

---