OpenSolvex Docs
CortexStacks (IaC)

Tipos de recurso

Los ocho tipos Cortex::* - propiedades, claves naturales de adopción y semántica de cambios de cada uno.

Un stack puede declarar ocho tipos de recurso. Cada uno delega en el mismo gestor que usa el portal, así que el resultado es idéntico a crearlo a mano.

Cómo leer las propiedades

Cada propiedad tiene una semántica de cambio:

  • Declarable — se compara en el diff; cambiarla produce un modify.
  • Inmutable — no se puede modificar en el recurso existente; cambiarla produce un replace (el recurso se recrea).
  • Write-only — entra al sistema pero nunca se puede volver a leer (credenciales). En templates se pasa siempre como !Ref a un parámetro noEcho, nunca como literal.

Adopción por clave natural. Casi todos los tipos tienen una clave natural (única por tenant). Si al desplegar ya existe un recurso con esa clave, el stack lo adopta y lo actualiza en lugar de duplicarlo. Eso hace idempotente re-aplicar un template.


Cortex::ProviderAccount

Una cuenta de un proveedor de LLM (OpenAI, Anthropic…) con su credencial.

CuentaOpenai:
  type: Cortex::ProviderAccount
  properties:
    provider: openai            # inmutable
    label: principal            # inmutable
    apiKey: !Ref OpenaiApiKey   # write-only, obligatorio !Ref a parámetro noEcho
PropiedadSemánticaDescripción
providerinmutableProveedor soportado (openai, anthropic…)
labelinmutableEtiqueta que distingue cuentas del mismo proveedor
apiKeywrite-onlyCredencial; un literal aquí es error de validación

Clave natural: (provider, label). Un update solo puede rotar la credencialprovider o label distintos recrean la cuenta.

Cortex::Model

Un modelo disponible sobre una cuenta de proveedor.

ModeloVentas:
  type: Cortex::Model
  properties:
    accountId: !Ref CuentaOpenai
    modelName: gpt-4o
PropiedadSemánticaDescripción
accountIddeclarable!Ref a un Cortex::ProviderAccount (o id físico pac_…)
modelNamedeclarableNombre del modelo en el proveedor

Clave natural: (accountId, modelName).

Cortex::Secret

Una credencial de negocio (API key de un CRM, token de un servicio) que agentes y tools consumen sin ver el plaintext.

CrmApiKey:
  type: Cortex::Secret
  properties:
    slug: crm-api-key           # inmutable
    description: API key del CRM
    value: !Ref CrmApiKeyValue  # write-only, obligatorio !Ref a parámetro noEcho
PropiedadSemánticaDescripción
sluginmutableIdentificador estable del secreto en el tenant
descriptiondeclarableDescripción legible
valuewrite-onlyEl valor; un literal aquí es error de validación

Clave natural: (slug). Aunque el valor no se puede leer, Cortex detecta que cambió (por huella criptográfica) y lo rota con un modify, sin exponerlo jamás.

Cortex::Skill

Una instrucción reutilizable (documento SKILL.md) que los agentes cargan.

SkillCalificar:
  type: Cortex::Skill
  properties:
    content: |
      ---
      name: calificar-leads
      description: Califica leads entrantes
      ---
      Cuando llegue un lead nuevo...
PropiedadSemánticaDescripción
contentdeclarableEl SKILL.md completo, frontmatter incluido
nameinmutable (derivada)Se extrae del frontmatter; cambiarlo recrea la skill

Clave natural: (name). Las versiones de una skill son append-only: cada cambio de content publica una versión nueva.

Cortex::ToolSource

Una fuente de herramientas externa, vía servidor MCP o especificación OpenAPI.

CrmTools:
  type: Cortex::ToolSource
  properties:
    kind: mcp                       # inmutable: mcp | openapi
    name: crm
    config: { url: https://crm.example.test/mcp }
    secretId: !Ref CrmApiKey        # credencial de la fuente, por secreto
    tools:
      buscar_cliente: { enabled: true, sensitive: false }
PropiedadSemánticaDescripción
kindinmutablemcp u openapi; cambiarlo recrea la fuente
namedeclarableNombre único de la fuente en el tenant
configdeclarable{ url } para MCP; { specUrl } o { spec } para OpenAPI
authdeclarableEsquema de autenticación de la fuente
secretIddeclarable!Ref a un Cortex::Secret con la credencial
toolsdeclarableOverrides por tool descubierta: enabled, sensitive, serverInjected

Clave natural: (name). Las entradas de tools se aplican después del descubrimiento de la fuente; referenciar un nombre de tool que no existe hace fallar el recurso (y dispara rollback). La credencial va siempre por secretId — no hay campo de credencial directa en templates. Por depender de un destino externo, este tipo reintenta hasta 3 veces antes de fallar.

Cortex::Agent

El agente de IA: prompt, modelo y sus asociaciones a skills, tools y secretos.

AgenteVentas:
  type: Cortex::Agent
  properties:
    name: asistente-ventas
    systemPrompt: Eres el asistente de ventas de ACME.
    modelId: !Ref ModeloVentas
    skills: [!Ref SkillCalificar]
    tools:
      - source: !Ref CrmTools
        names: [buscar_cliente]
    secretIds: [!Ref CrmApiKey]
PropiedadSemánticaDescripción
namedeclarableNombre único del agente en el tenant
description, avatardeclarablePresentación
systemPromptdeclarableInstrucciones base
modelIddeclarable!Ref a un Cortex::Model
maxIterations, timezone, localedeclarableComportamiento y localización
skillsdeclarableLista de !Ref a Cortex::Skill; se converge por diff
toolsdeclarableLista de { source: !Ref, names: [...] }; los nombres se resuelven tras el descubrimiento
secretIdsdeclarableAllowlist de secretos accesibles (default-deny, semántica de reemplazo total)

Clave natural: (name). Las asociaciones (skills, tools, secretIds) se convergen por diff: el stack agrega y quita asociaciones hasta igualar lo declarado.

Cortex::RoutingRule

Una regla que enruta tráfico entrante hacia un agente.

ReglaVentas:
  type: Cortex::RoutingRule
  properties:
    priority: 10
    match: { channelType: whatsapp }
    agentId: !Ref AgenteVentas
    enabled: true
PropiedadSemánticaDescripción
prioritydeclarableOrden de evaluación (menor = primero)
matchdeclarableCondiciones de coincidencia
agentIddeclarable!Ref al agente destino
enableddeclarableActiva/inactiva (default true)

Sin clave natural: las reglas no se adoptan. Una regla declarada en el template es propiedad del stack; reglas equivalentes creadas a mano no se fusionan.

Cortex::Hook

Una reacción a eventos del sistema: despachar un agente o llamar un HTTP endpoint.

HookObservador:
  type: Cortex::Hook
  properties:
    name: observador-ventas
    eventType: session.ended
    action: { kind: dispatch_agent, agentId: !Ref AgenteVentas }
PropiedadSemánticaDescripción
namedeclarableNombre único del hook en el tenant
eventTypedeclarableEvento que lo dispara
conditionsdeclarableFiltros adicionales
actiondeclarable{ kind: dispatch_agent, agentId } o { kind: http_call, url, method?, headers?, timeoutMs? }
payloadScope, enabled, priority, agentIddeclarableAlcance del payload y comportamiento

Clave natural: (name). La eliminación de un hook es definitiva (sin papelera).


Template completo de ejemplo

Los ocho tipos conectados — el mismo grafo que usa la suite de pruebas del motor:

template-completo.yaml
version: "2026-07"
description: Agente de ventas completo con CRM
parameters:
  OpenaiApiKey: { type: string, noEcho: true }
  CrmApiKeyValue: { type: string, noEcho: true }
resources:
  CuentaOpenai:
    type: Cortex::ProviderAccount
    properties: { provider: openai, label: principal, apiKey: !Ref OpenaiApiKey }
  ModeloVentas:
    type: Cortex::Model
    properties: { accountId: !Ref CuentaOpenai, modelName: gpt-4o }
  CrmApiKey:
    type: Cortex::Secret
    properties: { slug: crm-api-key, description: API key del CRM, value: !Ref CrmApiKeyValue }
  CrmTools:
    type: Cortex::ToolSource
    properties:
      kind: mcp
      name: crm
      config: { url: https://crm.example.test/mcp }
      secretId: !Ref CrmApiKey
      tools:
        buscar_cliente: { enabled: true, sensitive: false }
  SkillCalificar:
    type: Cortex::Skill
    properties:
      content: |
        ---
        name: calificar-leads
        description: Califica leads entrantes
        ---
        Cuando llegue un lead nuevo, pide presupuesto y plazo antes de derivar.
  AgenteVentas:
    type: Cortex::Agent
    properties:
      name: asistente-ventas
      systemPrompt: Eres el asistente de ventas de ACME.
      modelId: !Ref ModeloVentas
      skills: [!Ref SkillCalificar]
      tools:
        - source: !Ref CrmTools
          names: [buscar_cliente]
      secretIds: [!Ref CrmApiKey]
  HookObservador:
    type: Cortex::Hook
    properties:
      name: observador-ventas
      eventType: session.ended
      action: { kind: dispatch_agent, agentId: !Ref AgenteVentas }
  ReglaVentas:
    type: Cortex::RoutingRule
    properties:
      priority: 10
      match: { channelType: whatsapp }
      agentId: !Ref AgenteVentas
outputs:
  agentId: !GetAtt AgenteVentas.id

En el portal, la galería de Nuevo stack incluye variantes listas de este patrón (agente de ventas con OpenAPI, agente MCP, catálogo de modelos, observabilidad con hooks HTTP).

On this page