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
!Refa un parámetronoEcho, 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| Propiedad | Semántica | Descripción |
|---|---|---|
provider | inmutable | Proveedor soportado (openai, anthropic…) |
label | inmutable | Etiqueta que distingue cuentas del mismo proveedor |
apiKey | write-only | Credencial; un literal aquí es error de validación |
Clave natural: (provider, label). Un update solo puede rotar la credencial —
provider 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| Propiedad | Semántica | Descripción |
|---|---|---|
accountId | declarable | !Ref a un Cortex::ProviderAccount (o id físico pac_…) |
modelName | declarable | Nombre 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| Propiedad | Semántica | Descripción |
|---|---|---|
slug | inmutable | Identificador estable del secreto en el tenant |
description | declarable | Descripción legible |
value | write-only | El 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...| Propiedad | Semántica | Descripción |
|---|---|---|
content | declarable | El SKILL.md completo, frontmatter incluido |
name | inmutable (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 }| Propiedad | Semántica | Descripción |
|---|---|---|
kind | inmutable | mcp u openapi; cambiarlo recrea la fuente |
name | declarable | Nombre único de la fuente en el tenant |
config | declarable | { url } para MCP; { specUrl } o { spec } para OpenAPI |
auth | declarable | Esquema de autenticación de la fuente |
secretId | declarable | !Ref a un Cortex::Secret con la credencial |
tools | declarable | Overrides 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]| Propiedad | Semántica | Descripción |
|---|---|---|
name | declarable | Nombre único del agente en el tenant |
description, avatar | declarable | Presentación |
systemPrompt | declarable | Instrucciones base |
modelId | declarable | !Ref a un Cortex::Model |
maxIterations, timezone, locale | declarable | Comportamiento y localización |
skills | declarable | Lista de !Ref a Cortex::Skill; se converge por diff |
tools | declarable | Lista de { source: !Ref, names: [...] }; los nombres se resuelven tras el descubrimiento |
secretIds | declarable | Allowlist 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| Propiedad | Semántica | Descripción |
|---|---|---|
priority | declarable | Orden de evaluación (menor = primero) |
match | declarable | Condiciones de coincidencia |
agentId | declarable | !Ref al agente destino |
enabled | declarable | Activa/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 }| Propiedad | Semántica | Descripción |
|---|---|---|
name | declarable | Nombre único del hook en el tenant |
eventType | declarable | Evento que lo dispara |
conditions | declarable | Filtros adicionales |
action | declarable | { kind: dispatch_agent, agentId } o { kind: http_call, url, method?, headers?, timeoutMs? } |
payloadScope, enabled, priority, agentId | declarable | Alcance 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:
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.idEn 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).