Saltar al contenido principal
QUÉ DEBE TENER A MANO
  1. Un enlace de invitación al clúster enviado por el administrador de su clúster. Le convierte en propietario de una organización completamente nueva.
  2. Esta guía todo lo que necesita para pasar de ese enlace a una integración funcional.
Enlaces rápidos

Bienvenido a MKA1

MKA1 es una plataforma para crear aplicaciones de IA. Ofrece a su equipo una única puerta de enlace a grandes modelos de lenguaje además de los bloques de construcción de alto nivel que los productos reales necesitan: agentes, conversaciones almacenadas, memoria a largo plazo, recuperación de documentos (RAG), herramientas y servidores MCP, prompts, habilidades, guardrails, voz y evaluaciones. Usted trabaja con MKA1 a través de dos superficies que comparten las mismas cuentas, equipos y recursos:
  • La Consola - un panel web para crear e inspeccionar todo manualmente: ejecutar prompts en el Playground, guardar agentes, indexar archivos, generar claves API, gestionar su organización y sus equipos. La consola vive en la dirección de su clúster (por ejemplo platform.mka1.com).
  • La API y los SDK - las mismas capacidades sobre HTTPS, llamadas desde su propio código mediante el SDK de TypeScript, Python o C#, la CLI mka1 o curl a secas. Así es como su aplicación habla con MKA1 en producción.
Esta guía recorre todo el camino en orden. Los pasos 1–7 le llevan desde el enlace de invitación hasta su primera solicitud exitosa; las secciones posteriores recorren cada bloque de construcción con ejemplos listos para copiar y pegar.

Antes de empezar

Solo necesita dos cosas para comenzar, y ya tiene ambas:
  1. Un enlace de invitación al clúster. Su administrador creó una invitación en el clúster y le envió el enlace. Al abrirlo, se convierte en propietario de una nueva organización dentro de ese clúster.
  2. Esta guía. Le lleva desde la invitación hasta una integración funcional con el SDK.
No hay nada que instalar de antemano. La consola se ejecuta en su navegador, y solo instala un SDK cuando esté listo para escribir código. El camino siguiente toma unos 15 minutos:
Configuración en 15 minutos
  • Paso 1 Acepte su invitación al clúster y cree su organización.
  • Paso 2 Oriéntese en la consola.
  • Paso 3 Invite a compañeros y cree un equipo (las claves API viven en los equipos).
  • Paso 4 Cree una clave API.
  • Paso 5 Instale un SDK.
  • Paso 6 Autentique sus solicitudes.
  • Paso 7 Realice su primera solicitud.

Paso 1 · Acepte su invitación al clúster

Abra el enlace de invitación al clúster que le envió su administrador. Lleva un token de un solo uso y le deja en la página Set up your organization. Una invitación al clúster es una invitación de propietario - al aceptarla se crea una nueva organización y usted queda como propietario.

Haga esto

  1. Abra el enlace de invitación. La página valida el token y muestra una insignia de Owner invite (y una fecha de caducidad, si se configuró una). Si dice que la invitación no está disponible, el token de invitación ha caducado o ha sido revocado. Pida a su administrador un enlace nuevo.
  2. Nombre su organización. Escriba un nombre como Acme Inc. Se genera automáticamente un slug de URL del espacio de trabajo (p. ej. acme-inc); expanda Customize si desea editarlo. Solo minúsculas, números y guiones.
  3. Elija cómo iniciar sesión. Cree una cuenta con correo y contraseña, o continúe con Google. Si la invitación estaba vinculada a su dirección de correo, esa dirección aparece precargada y bloqueada.
  4. Verifique su correo. Si se registró con contraseña, MKA1 le envía un correo de verificación. Haga clic en el enlace para confirmar; después entra directamente en su nueva organización.
  5. Ya está dentro. Aterriza en la consola como propietario de su organización, listo para invitar a compañeros y crear claves.
Ahora usted es el propietario de la organizaciónEl propietario tiene control total. Uso, miembros, equipos y configuración. Todos los demás que incorpore serán administradores o miembros (se cubre en el Paso 3). Si ya había iniciado sesión en MKA1 con un correo distinto al de la invitación, cierre sesión primero: las invitaciones están vinculadas a una dirección específica.

Paso 2 · Recorra la consola

Tómese un minuto para orientarse. La barra lateral izquierda agrupa cada superficie en Access, LLM, Agents y Admin. Esto es para qué sirve cada sección. Usará varias de ellas en los pasos siguientes. Configuración de organizaciones en la consola de MKA1

Access

SecciónQué hace ahí
API KeysCree y gestione las claves de autenticación que usa su código (Paso 4).
OrganizationsGestione miembros, roles, equipos e invitaciones pendientes.
TeamsCree equipos y gestione su membresía. Cada clave API está limitada a un equipo.
Service AccountsCree identidades no humanas para producción y adjúntelas a equipos.

LLM

SecciónQué hace ahí
PlaygroundChatee con modelos de forma interactiva. Transmita respuestas en tiempo real. Configure herramientas, habilidades y guardrails, con un panel de ajustes avanzados.
ModelsExplore los modelos disponibles a través de la puerta de enlace, agrupados por modalidad, con detalles del registro para administradores.
ResponsesCree respuestas individuales e inspeccione el historial almacenado, la salida, las llamadas a herramientas y el uso de tokens.
EvalsConstruya suites de evaluación y lance ejecuciones duraderas para medir y comparar la calidad de los modelos.
ConversationsCree e inspeccione el estado de conversaciones almacenadas, con búsqueda por metadatos.
Text to speechSintetice voz a partir de texto e inspeccione el historial de generación.
Speech to textTranscriba audio a texto e inspeccione el historial de transcripciones.
PromptsCree, versione y revierta plantillas de prompts reutilizables con {{variables}}.
GuardrailsConfigure políticas de palabras prohibidas, inyección de prompts y filtraciones, y luego pruébelas.
FilesSuba, inspeccione y elimine archivos usados por flujos de trabajo LLM.
Vector StoresCree almacenes, adjunte archivos y busque fragmentos de documentos indexados para recuperación (RAG).
FeedbackRegistre y actualice retroalimentación humana sobre la salida del modelo; consulte registros o exporte una instantánea en parquet.
SkillsSuba, versione y gestione habilidades reutilizables, cada una empaquetada tras un manifiesto SKILL.md.
MCP ServersRegistre definiciones de servidores MCP que los agentes guardados pueden adjuntar como herramientas; los secretos permanecen en Credentials.
CredentialsGuarde los secretos que sus servidores MCP e integraciones necesitan, separados de sus definiciones.

Agents

SecciónQué hace ahí
QuickstartPonga en marcha un agente guardado rápidamente - elija un modelo, escriba instrucciones, adjunte herramientas y ejecútelo.
AgentsCree y ejecute agentes guardados que agrupan un modelo, instrucciones, herramientas y metadatos.
SessionsRastree y depure ejecuciones de agentes. Reproduzca la transcripción y recorra los eventos sin procesar.
Memory StoresExplore las memorias en markdown que los agentes leen y escriben entre ejecuciones.

Admin

SecciónQué hace ahí
AuditRevise solicitudes de auditoría de la puerta de enlace, construya casos y exporte respuestas (los administradores del clúster ven todas las organizaciones; los administradores de organización ven la actividad de su org).
AlertsRegistre endpoints de webhook que se disparan cuando fallan las respuestas, con alcance de clúster, organización o equipo.
Model RegistryAñada y configure los modelos personalizados disponibles en el registro de su organización.
PricingMantenga el libro de precios de modelos: moneda del clúster, precios por modelo y anulaciones por organización (solo administradores del clúster).
BudgetsCree presupuestos de gasto de la org con umbrales de alerta/bloqueo y estado de gasto en vivo (los presupuestos de claves API los gestiona el administrador del clúster).
UsageRevise el uso de tokens, solicitudes y almacenamiento del org y equipo activos.
Fine-tuningLance y supervise ejecuciones de fine-tuning y checkpoints (próximamente).
ServingDespliegue modelos en el clúster: despliegues con escalado y reversión, registros de modelos, imágenes, trabajos de fine-tuning, aceleradores y secretos (administradores).

Paso 3 · Invite a su equipo y organice el acceso

Página de detalle de equipo en Access → Teams El acceso a MKA1 se organiza como una jerarquía simple: organización → equipos → miembros, con roles que controlan lo que cada persona puede hacer y cuentas de servicio que representan a los llamadores no humanos.

La organización y su propietario

Cuando acepta la invitación al clúster, se convierte en propietario de su organización. El propietario tiene control total: métricas de uso, miembros, equipos y configuración. Todos los demás que incorpore son administradores o miembros:
RolQué puede hacer
PropietarioControl total de la organización - uso, miembros y configuración.
AdministradorGestiona miembros, equipos y claves API en toda la organización.
MiembroAccede a los modelos, archivos y claves API de su equipo.

Equipos

Dentro de una organización usted crea equipos, y los miembros pertenecen a uno o más de ellos. Los equipos son donde realmente viven el trabajo y el acceso: las claves API, los agentes y otros recursos están limitados a un solo equipo. Una clave generada en un equipo concede acceso únicamente a los recursos de ese equipo. Sacar a alguien (o a una cuenta de servicio) de un equipo revoca el acceso que venía con él, y las claves ligadas a ese equipo dejan de funcionar. Esto convierte a los equipos en la frontera natural para separar proyectos, entornos o unidades de negocio. Gestiónelos en Access → Teams, donde puede crear un equipo y gestionar su lista plana de miembros.

Invitar a compañeros

Diálogo de invitar personas con selección de rol y equipos Para añadir a una persona, envíele una invitación a la organización por correo. Puede hacerlo navegando a Access → Organizations y haciendo clic en Invite people en la esquina superior derecha. Comparta el enlace generado que abre la página Accept invite, que muestra la organización, quién le invitó, el rol que recibirá y cuándo caduca la invitación. Lo que hacen para aceptar depende de su estado:
  • Sin cuenta todavía (Este es el escenario más probable) - se registran (correo/contraseña o Google) con el correo invitado, lo verifican y vuelven a la invitación para terminar de unirse.
  • Ya con sesión iniciada con el correo invitado - un clic en Accept & join los añade a la organización.
  • Con sesión iniciada con otro correo - se les pide cambiar primero a la cuenta invitada, ya que las invitaciones están vinculadas a una dirección específica.
Las invitaciones pueden caducar o ser revocadas, así que envíe un enlace nuevo si alguien informa de uno muerto.

Cuentas de servicio para producción

Para sistemas de producción, ejecutores de CI, servicios backend y trabajos programados, use una cuenta de servicio en lugar de las credenciales de una persona. Una cuenta de servicio es una identidad máquina no humana que usted adjunta a uno o más equipos, y para la que genera claves API. Puede crear una navegando a Access → Service accounts y haciendo clic en New service account en la esquina superior derecha. Como las claves heredan el alcance del equipo, separar una cuenta de servicio de un equipo (o eliminarla) detiene inmediatamente todas las claves generadas para ella en ese equipo, dándole un interruptor de apagado limpio para las credenciales de producción.

Paso 4 · Cree una clave API

Formulario de nueva clave API con pasos de identidad, vinculación de alcance y permisos Una clave API es la credencial que su código envía en cada solicitud. En la consola, abra Access → API Keys y haga clic en Create API key. El formulario recorre cuatro pasos.

1 · Identidad

Nombre la clave (p. ej. Production gateway) y elija el principal como el que actúa: My user (usa su rol de org y el equipo seleccionado) o una Service account (una identidad no humana dedicada. Las cuentas de servicio se recomiendan para casos de uso en producción).

2 · Vinculación de alcance

Elija la organización y el equipo a los que pertenece la clave. Una clave solo puede ver recursos dentro de ese único equipo en esa única org — así que elija el equipo cuyos modelos, archivos y agentes debe alcanzar esta clave. (Si aún no tiene equipo, cree uno primero en Access → Teams; las claves deben estar limitadas a un equipo.)

3 · Permisos (scopes)

Elija qué recursos puede leer y escribir la clave. Los scopes se comprueban en cada solicitud. Use un preajuste para avanzar rápido y luego afine:
  • Standard - los scopes de lectura/escritura cotidianos para crear apps (respuestas, conversaciones, archivos, almacenes vectoriales, prompts, agentes y más).
  • Read-only - todos los scopes read: y nada más.
  • All - todos los scopes, incluidos los exclusivos de administrador. Disponible solo para propietarios y administradores de la org.
Algunos scopes son solo de administrador (fine-tuning, registro de modelos, guardrails, búsqueda, lotes, sandbox, autorización de grano fino) y aparecen solo si usted es propietario o administrador. Conceda el conjunto más estrecho que la clave realmente necesite.

4 · Limitación de tasa (opcional)

Opcionalmente limite la clave a un número máximo de solicitudes por minuto, hora o día. La puerta de enlace lo aplica y devuelve 429 Too Many Requests antes de que la solicitud llegue a un modelo, así que las llamadas por encima del límite no cuestan nada.
Copie el secreto ahora — se muestra una sola vezCuando hace clic en Create key, el secreto completo se revela una única vez. Cópielo inmediatamente y guárdelo en un lugar seguro (un gestor de secretos o su .env). Si lo pierde, no puede volver a verlo. Regenere la clave para obtener un secreto nuevo. Trátelo como una contraseña: nunca lo suba al control de versiones ni lo exponga en código de navegador.

Paso 5 · Instale un SDK

MKA1 ofrece SDK para TypeScript, Python y C#, además de una CLI mka1 independiente. Cada cliente se autentica con su clave API como token Bearer y apunta a la puerta de enlace de la API. La puerta de enlace alojada por defecto es https://apigw.mka1.com.
Clústeres privadosEn un despliegue privado, sustituya https://apigw.mka1.com por el host de la puerta de enlace de su propio clúster en todo lo que sigue. Páselo como la opción serverURL / server_url / serverUrl del SDK, o configúrelo una vez para la CLI. Su administrador puede decirle la URL de la puerta de enlace (es la contraparte de API de su dirección de consola).

TypeScript - @meetkai/mka1

El SDK de TypeScript se instala desde el registro de paquetes npm:
npm add @meetkai/mka1
import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({ bearerAuth: 'Bearer YOUR_API_KEY' });

Python - meetkai-mka1

Requiere Python 3.10 o más reciente:
pip install meetkai-mka1
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

C# - MeetKai.MKA1

using MeetKai.MKA1;

var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

CLI - mka1

Los binarios precompilados se sirven desde downloads.mka1.com. En macOS (Apple silicon):
curl -fsSL https://downloads.mka1.com/darwin/mka1_darwin_arm64-latest.tar.gz \
  | tar -xz -C /usr/local/bin mka1
mka1 version
Cambie arm64 por x86_64 en Intel; los paquetes .deb/.rpm y un .zip para Windows están enlazados desde la guía de la CLI. Luego configure su clave y ejecute cualquier comando:
export MKA1_BEARER_AUTH="Bearer YOUR_API_KEY"
mka1 llm models list
Para una configuración persistente que guarda los secretos en el llavero de su SO, vea autenticar la CLI.

Paso 6 · Autentique sus solicitudes

Cada solicitud lleva su clave API como token bearer en el encabezado Authorization. Para apps multiusuario del lado del servidor también envía X-On-Behalf-Of para identificar para cuál de sus usuarios finales es la solicitud.
Authorization: Bearer YOUR_API_KEY

Cuándo enviar X-On-Behalf-Of

Establezca X-On-Behalf-Of con un identificador estable de su propio sistema (p. ej. user_123) siempre que su servidor actúe para un usuario final específico. Esto mantiene las solicitudes, archivos, memoria y uso de ese usuario correctamente atribuidos. Use un ID que no cambie. Nunca use un correo ni un nombre visible.
  • Solo Authorization - su propio flujo de trabajo backend, no ligado a ningún usuario final.
  • Authorization + X-On-Behalf-Of - su servidor actuando para uno de sus usuarios finales; el uso y los recursos quedan asociados a él.
import type { ResponseObject } from '@meetkai/mka1/models/components';

const result = await mka1.llm.responses.create({
  xOnBehalfOf: 'user_123',
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Resuma este ticket de soporte.',
  },
}) as ResponseObject;
console.log(result.outputText);
response = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Resuma este ticket de soporte.",
    x_on_behalf_of="user_123",
)

Emita tokens de corta duración (opcional)

Cuando un servicio descendente o un cliente de navegador necesita llamar a MKA1 sin poseer su clave API, intercambie la clave por un JWT de corta duración mediante POST /api/v1/authentication/api-keys/exchange-token, y luego use ese JWT como token bearer. Vea la guía de autenticación y el análisis en profundidad.
curl -X POST https://apigw.mka1.com/api/v1/authentication/api-keys/exchange-token \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{ "audience": "https://your-app.example.com", "externalUserId": "user_123" }'
# → { "token": "<jwt>" } — luego envíe Authorization: Bearer <jwt>
const jwt = await mka1.auth.apiKeys.exchangeToken({
  requestBody: {
    audience: 'https://your-app.example.com',
    externalUserId: 'user_123',
  },
});

// jwt.token es el JWT de corta duración — úselo como bearer
const asEndUser = new SDK({ bearerAuth: `Bearer ${jwt.token}` });
jwt = sdk.auth.api_keys.exchange_token(body={
    "audience": "https://your-app.example.com",
    "external_user_id": "user_123",
})

# jwt.token es el JWT de corta duración — úselo como bearer
as_end_user = SDK(bearer_auth=f"Bearer {jwt.token}")

Paso 7 · Realice su primera solicitud

Con una clave en mano, genere su primera respuesta. Usar model: 'auto' permite que la puerta de enlace elija el modelo adecuado para la solicitud. Una respuesta completada en la consola con entrada, razonamiento y salida
mka1 llm responses create \
  --model meetkai:functionary-es-mini \
  --input '"¿Cuál es la capital de Francia?"' \
  -H 'X-On-Behalf-Of: <end-user-id>'
import { SDK } from '@meetkai/mka1';
import type { ResponseObject } from '@meetkai/mka1/models/components';

const mka1 = new SDK({ bearerAuth: 'Bearer YOUR_API_KEY' });

const result = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: '¿Cuál es la capital de Francia?',
  },
}) as ResponseObject;
console.log(result.outputText);
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

res = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="¿Cuál es la capital de Francia?",
)
curl https://apigw.mka1.com/api/v1/llm/responses \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{ "model": "meetkai:functionary-es-mini", "input": "¿Cuál es la capital de Francia?" }'
Ese es el camino completo desde cero. Tiene una organización, un equipo, una clave API, un SDK y una solicitud funcionando. El resto de esta guía recorre los bloques de construcción que ensamblará en aplicaciones reales.

Construya con la plataforma

Todo lo que sigue puede llamarse con la clave API que acaba de crear. Cada sección se apoya en las guías oficiales de docs.mka1.com. Siga los enlaces incorporados para la referencia completa.

Generar respuestas (la llamada principal)

Playground con el panel de ajustes avanzados abierto El recurso Responses es cómo genera texto con MKA1. Pase una cadena simple en input para un prompt de un solo turno; el resultado incluye el texto generado en output_text. Use auto_routing: true para que la puerta de enlace elija el modelo adecuado por usted.

Llamada básica

import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({
  bearerAuth: `Bearer ${YOUR_API_KEY}`,
});

const result = await mka1.llm.responses.create({
  xOnBehalfOf: '<end-user-id>',
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Escriba un resumen de una frase de la API de MKA1.',
  },
});
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

res = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Escriba un resumen de una frase de la API de MKA1.",
    http_headers={"X-On-Behalf-Of": "<end-user-id>"},
)
Pase X-On-Behalf-Of cuando actúe para un usuario final; omítalo en caso contrario.

Qué hace auto_routing

auto_routing es un indicador de solicitud opcional, separado del alias de modelo auto. Cuando establece auto_routing: true, la puerta de enlace puntúa la complejidad de la solicitud y la enruta al mejor hermano cuantizado, MoE o denso dentro de la familia de modelos que usted solicitó. Nunca cambia a un modelo no relacionado, y recurre al modelo que pidió si esa familia no tiene un hermano compatible. La puntuación es aditiva. Sube con la longitud del prompt, muchas herramientas o herramientas de alta agencia (p. ej. code_interpreter, mcp), tool_choice: 'required', salida estructurada, un max_output_tokens grande, contexto multivuelta y señales de razonamiento complejo en el texto (debug, refactor, plan, incident, code); baja con prompts cortos y tareas simples reconocidas (traducir, resumir, clasificar, extraer). El total elige el nivel. Puntuaciones altas enrutan a dense, medias a moe, bajas a quantized. Se establece un reasoning.effort acorde (desde minimal hasta xhigh) a menos que usted mismo haya fijado el esfuerzo. Así, un breve “resuma esto” se enruta a quantized con esfuerzo minimal, mientras que un largo informe de incidente se enruta a dense con esfuerzo high (o xhigh). Siempre que el enrutamiento se ejecuta, los metadatos de la respuesta registran routed_model - la variante realmente usada. Añada auto_routing_debug: true para obtener también un campo de metadatos auto_routing_debug: una cadena JSON compacta con el modelo solicitado y el enrutado, el nivel elegido, el esfuerzo de razonamiento, la puntuación y las razones detrás de la decisión. Se registra incluso cuando no hay variante hermana disponible, así que es útil para validar el comportamiento del despliegue. Deje este campo desactivado para el tráfico normal de producción.

Transmita texto a medida que se genera

Establezca stream: true para recibir eventos enviados por el servidor en lugar de esperar la respuesta completa. Úselo para renderizar salida parcial a medida que llega.
import { CreateAcceptEnum } from '@meetkai/mka1/sdk/responses';
import { EventStream } from '@meetkai/mka1/lib/event-streams';

const stream = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Escriba tres viñetas de notas de versión para nuestra actualización de docs.',
    stream: true,
  },
}, { acceptHeaderOverride: CreateAcceptEnum.textEventStream });

if (stream instanceof EventStream) {
  for await (const event of stream) {
    if (event.data.type === 'response.output_text.delta') {
      process.stdout.write(event.data.delta);
    }
  }
}
stream = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Escriba tres viñetas de notas de versión para nuestra actualización de docs.",
    stream=True,
)

for event in stream:
    if event.data.type == "response.output_text.delta":
        print(event.data.delta, end="", flush=True)

Entrada multimodal (imagen + texto)

La API de Responses acepta texto, imágenes, audio y archivos en una sola solicitud. Use un arreglo input estructurado de elementos de mensaje, donde content es un arreglo que mezcla input_text e input_image (imagen por URL, URI de datos base64 o un file_id subido).
const result = await mka1.llm.responses.create({
  xOnBehalfOf: '<end-user-id>',
  responsesCreateRequest: {
    model: 'openai:gpt-4.1', // con visión — 'auto' descarta imágenes hoy
    input: [
      {
        type: 'message',
        role: 'user',
        content: [
          { type: 'input_text', text: 'Describa lo que ve en esta imagen.' },
          {
            type: 'input_image',
            imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg',
          },
        ],
      },
    ],
  },
});
res = sdk.llm.responses.create(
    model="openai:gpt-4.1",  # con visión — 'auto' descarta imágenes hoy
    input=[
        {
            "type": "message",
            "role": "user",
            "content": [
                {"type": "input_text", "text": "Describa lo que ve en esta imagen."},
                {
                    "type": "input_image",
                    "image_url": "https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg",
                },
            ],
        },
    ],
    x_on_behalf_of="<end-user-id>",
)

Respuestas en segundo plano

Para trabajo de larga duración, establezca background: true (con stream: false) para obtener de inmediato una respuesta en cola, y luego recupere el resultado más tarde sondeando con mka1.llm.responses.get(...) o mediante streaming. Vea la guía de respuestas en segundo plano.
import type { ResponseObject } from '@meetkai/mka1/models/components';

const queued = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Escriba una historia del fax en dos frases.',
    background: true,
    stream: false,
  },
}) as ResponseObject;

// queued.status === 'queued'

let response = queued;
while (response.status === 'queued' || response.status === 'in_progress') {
  await new Promise((r) => setTimeout(r, 2000));
  response = await mka1.llm.responses.get({ responseId: queued.id }) as ResponseObject;
}
console.log(response.outputText);
import time

queued = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Escriba una historia del fax en dos frases.",
    background=True,
    stream=False,
)  # queued.status == "queued"

response = queued
while response.status in ("queued", "in_progress"):
    time.sleep(2)
    response = sdk.llm.responses.get(response_id=queued.id)

print(response.output_text)

Webhooks en lugar de sondeo

En lugar de sondear, pase webhook_url (y opcionalmente webhook_secret) al crear una respuesta en segundo plano. La puerta de enlace envía por POST cada cambio de estado a su endpoint — response.queued, response.in_progress, response.completed, response.failed, response.incomplete, response.cancelled — como { event, resource_id, created_at, data }, donde data es el objeto de evento completo. Con un secreto configurado, cada entrega lleva X-Webhook-Signature: sha256=<hex>, un HMAC-SHA256 del cuerpo JSON sin procesar — verifíquelo antes de confiar en la carga útil. La entrega nunca bloquea la respuesta: tres intentos con retroceso exponencial y un tiempo límite de 10 segundos. El endpoint debe ser accesible públicamente — las direcciones privadas y localhost se rechazan. La puerta de enlace requiere que webhook_secret tenga al menos 16 caracteres.
const queued = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Resuma este informe de 80 páginas…',
    background: true,
    stream: false,
    webhookUrl: 'https://your-app.example.com/hooks/mka1',
    webhookSecret: process.env.MKA1_WEBHOOK_SECRET,
  },
}) as ResponseObject;
import os

queued = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Resuma este informe de 80 páginas…",
    background=True,
    stream=False,
    webhook_url="https://your-app.example.com/hooks/mka1",
    webhook_secret=os.environ["MKA1_WEBHOOK_SECRET"],
)
Para su lado receptor:
import crypto from 'node:crypto';

// En su manejador de webhook — verifique X-Webhook-Signature contra el cuerpo sin procesar de la solicitud
function isValidSignature(rawBody: string, signatureHeader: string, secret: string) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}

Conversaciones y memoria

Detalle de conversación con elementos y metadatos MKA1 le ofrece dos formas complementarias de mantener el contexto entre turnos: conversaciones con estado (historial guardado para una sesión, en el servidor) y el almacén de memoria a largo plazo (la herramienta history, persistente entre sesiones y con alcance por usuario final).

Conversaciones con estado

Una conversación es un contenedor del lado del servidor que la puerta de enlace usa para mantener el estado entre solicitudes de Responses, de modo que nunca reenvíe el historial completo. Cree una y luego pase su ID en cada respuesta de seguimiento.
import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({ bearerAuth: `Bearer ${YOUR_API_KEY}` });

// 1. Cree una conversación (metadatos opcionales para su propio enrutamiento)
const conv = await mka1.llm.conversations.create({
  xOnBehalfOf: '<end-user-id>',
  createConversationRequest: {
    metadata: { session_id: 'web-42', channel: 'support' },
  },
});

// 2. (Opcional) escriba historial explícitamente antes de llamar a Responses
await mka1.llm.conversations.createItems({
  conversationId: conv.id,
  xOnBehalfOf: '<end-user-id>',
  createItemsRequest: {
    items: [
      { type: 'message', role: 'user', content: 'Resuma el último ticket de soporte.' },
    ],
  },
});

// 3. Continúe el flujo — adjunte la conversación para que el modelo tenga historial
const result = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    conversation: conv.id,
    input: 'Convierta ese resumen en una respuesta lista para el cliente.',
  },
});
# 1. Cree una conversación (metadatos opcionales para su propio enrutamiento)
conv = sdk.llm.conversations.create(
    metadata={"session_id": "web-42", "channel": "support"},
    x_on_behalf_of="<end-user-id>",
)

# 2. (Opcional) escriba historial explícitamente antes de llamar a Responses
sdk.llm.conversations.create_items(
    conversation_id=conv.id,
    items=[
        {"type": "message", "role": "user", "content": "Resuma el último ticket de soporte."},
    ],
    x_on_behalf_of="<end-user-id>",
)

# 3. Continúe el flujo — adjunte la conversación para que el modelo tenga historial
result = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    conversation=conv.id,
    input="Convierta ese resumen en una respuesta lista para el cliente.",
)
Pase conversation en cada solicitud; la puerta de enlace mantiene el hilo por usted. Use una conversación cuando quiera un contenedor reutilizable e inspeccionable para muchos turnos y la capacidad de listar, obtener o eliminar elementos después. Use previous_response_id en su lugar cuando solo necesite bifurcar desde una única respuesta anterior.

Almacén de memoria a largo plazo

La herramienta history da al modelo memoria que persiste entre sesiones. Añada { type: 'history' } a tools y establezca store: true; cada par solicitud/respuesta se indexa en segundo plano y se busca semánticamente (embeddings vectoriales) cuando el modelo decide que necesita recordar algo. La memoria está aislada por usuario final mediante el encabezado X-On-Behalf-Of.
// Sesión 1: guarde un dato
await mka1.llm.responses.create({
  xOnBehalfOf: 'user-123',
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Recuerda esto: mi color favorito es azul.',
    tools: [{ type: 'history' }],
    store: true,
  },
});

// Sesión 2 (minutos o días después — la indexación tarda ~1–2 min): recupérelo
const recalled = await mka1.llm.responses.create({
  xOnBehalfOf: 'user-123',
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: '¿Cuál es mi color favorito?',
    tools: [{ type: 'history' }],
    store: true,
  },
});
// → "Tu color favorito es azul."
# Sesión 1: guarde un dato
sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="Recuerda esto: mi color favorito es azul.",
    tools=[{"type": "history"}],
    store=True,
    x_on_behalf_of="user-123",
)

# Sesión 2 (minutos o días después — la indexación tarda ~1–2 min): recupérelo
recalled = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    input="¿Cuál es mi color favorito?",
    tools=[{"type": "history"}],
    store=True,
    x_on_behalf_of="user-123",
)
Regla general: las conversaciones mantienen coherente una sesión; la herramienta history lleva preferencias, decisiones y contexto hacia adelante a través de muchas sesiones para el mismo usuario.

Archivos, almacenes vectoriales y recuperación (RAG)

Un almacén vectorial con archivos adjuntos en indexación MKA1 divide la recuperación en dos recursos: Files contiene sus documentos subidos, y Vector Stores indexa esos archivos para que pueda ejecutar búsqueda semántica sobre los fragmentos resultantes. Este es el patrón estándar para asistentes respaldados por documentos y respuestas fundamentadas. La indexación es automática. Usted sube, adjunta y busca; MKA1 se encarga del troceado y los embeddings. Todos los fragmentos siguientes usan el SDK de MKA1 para TypeScript o Python. Inicialice el cliente una vez:
import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({ bearerAuth: 'Bearer <mka1-api-key>' });
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer <mka1-api-key>")

1. Suba un archivo

Suba el documento una vez. La respuesta devuelve un objeto de archivo cuyo id se parece a file_1783478060914_iemq10dh5h — páselo a los almacenes vectoriales en el siguiente paso.
const file = Bun.file('./support-manual.pdf');

const result = await mka1.llm.files.upload({
  xOnBehalfOf: '<end-user-id>',
  requestBody: { file, purpose: 'assistants' },
});
// result.id → p. ej. file_1783478060914_iemq10dh5h
with open("support-manual.pdf", "rb") as fh:
    result = sdk.llm.files.upload(
        file={"file_name": "support-manual.pdf", "content": fh.read()},
        purpose="assistants",
        x_on_behalf_of="<end-user-id>",
    )
# result.id → p. ej. file_1783481291595_r19s7ueog7o

2. Cree un almacén vectorial y adjunte archivos

Cree un almacén vectorial, pasando uno o más ID de archivos subidos en fileIds. El almacén devuelve un ID como vs_1783478061269_mptf5b93t0q. Los archivos adjuntos se indexan automáticamente.
const vectorStore = await mka1.llm.vectorStores.create({
  xOnBehalfOf: '<end-user-id>',
  createVectorStoreRequest: {
    name: 'Base de conocimiento de soporte',
    description: 'Manuales de soporte y documentos del centro de ayuda indexados',
    fileIds: [result.id],
    expiresAfter: { anchor: 'last_active_at', days: 30 },
  },
});
vector_store = sdk.llm.vector_stores.create(
    name="Base de conocimiento de soporte",
    description="Manuales de soporte y documentos del centro de ayuda indexados",
    file_ids=[result.id],
    expires_after={"anchor": "last_active_at", "days": 30},
    x_on_behalf_of="<end-user-id>",
)
Para añadir más archivos después sin recrear el almacén, use createFile:
const second = await mka1.llm.files.upload({
  xOnBehalfOf: '<end-user-id>',
  requestBody: { file: Bun.file('./help-center-faq.pdf'), purpose: 'assistants' },
});

const vsFile = await mka1.llm.vectorStores.createFile({
  vectorStoreId: vectorStore.id,
  xOnBehalfOf: '<end-user-id>',
  createVectorStoreFileRequest: {
    fileId: second.id,
    attributes: { category: 'faq', version: '2.0' },
  },
});
with open("help-center-faq.pdf", "rb") as fh:
    second = sdk.llm.files.upload(
        file={"file_name": "help-center-faq.pdf", "content": fh.read()},
        purpose="assistants",
        x_on_behalf_of="<end-user-id>",
    )

vs_file = sdk.llm.vector_stores.create_file(
    vector_store_id=vector_store.id,
    file_id=second.id,
    attributes={"category": "faq", "version": "2.0"},
    x_on_behalf_of="<end-user-id>",
)
Un archivo de almacén vectorial puede reportar status: "in_progress" mientras se ejecuta la indexación, así que espere a que el procesamiento termine antes de confiar en los resultados de búsqueda.

3. Busque fragmentos relevantes en el almacén

Ejecute una búsqueda semántica para recuperar los fragmentos más relevantes para la pregunta de un usuario. La respuesta devuelve coincidencias clasificadas con file_id, filename, datos de puntuación y el contenido del fragmento. Alimente ese texto a su propia lógica de aplicación o a una solicitud de Responses.
const results = await mka1.llm.vectorStores.search({
  vectorStoreId: vectorStore.id,
  xOnBehalfOf: '<end-user-id>',
  searchVectorStoreRequest: {
    query: '¿Cómo restablezco mi contraseña?',
    maxNumResults: 5,
  },
});
results = sdk.llm.vector_stores.search(
    vector_store_id=vector_store.id,
    query="¿Cómo restablezco mi contraseña?",
    max_num_results=5,
    x_on_behalf_of="<end-user-id>",
)

Extra: extracción estructurada

Cuando necesita JSON tipado de un documento en lugar de fragmentos de texto libre, use el recurso Extract. Para trabajo puntual, llame a extract con un JSON Schema en línea — pasado como cadena JSON — y el archivo a leer. Para trabajos repetidos, guarde el esquema una vez con createSchema (aquí el esquema es un objeto simple) y ejecútelo contra muchos archivos con extractWithSchema, referenciando el id del esquema devuelto bajo data.id. Nombre un modelo explícitamente en cada llamada de extracción. Una respuesta exitosa devuelve success, un objeto data con los campos extraídos y metadata sobre la ejecución.
const schema = {
  type: 'object',
  properties: {
    document_title: { type: 'string' },
    reset_link_expiry_minutes: { type: 'number' },
    support_email: { type: 'string' },
  },
  required: ['document_title'],
};

// Extracción puntual — aquí el esquema es una cadena JSON
const res = await mka1.llm.extract.extract({
  requestBody: {
    model: 'openai:gpt-4.1', // 'auto' actualmente devuelve 500 en este endpoint
    prompt: 'Extraiga el título del documento, la caducidad del enlace de restablecimiento y el correo de soporte.',
    schema: JSON.stringify(schema),
    file: Bun.file('./support-manual.txt'),
  },
});
// → { success, data: {…}, metadata: {…} }
import json

schema = {
    "type": "object",
    "properties": {
        "document_title": {"type": "string"},
        "reset_link_expiry_minutes": {"type": "number"},
        "support_email": {"type": "string"},
    },
    "required": ["document_title"],
}

# Extracción puntual — aquí el esquema es una cadena JSON
with open("support-manual.txt", "rb") as fh:
    res = sdk.llm.extract.extract(
        model="openai:gpt-4.1",  # 'auto' actualmente devuelve 500 en este endpoint
        prompt="Extraiga el título del documento, la caducidad del enlace de restablecimiento y el correo de soporte.",
        schema=json.dumps(schema),
        file={"file_name": "support-manual.txt", "content": fh.read()},
    )
# res.success, res.data, res.metadata
// Plantilla reutilizable — aquí el esquema es un objeto; el id llega bajo data.id
const created = await mka1.llm.extract.createSchema({
  extractionSchema: {
    name: 'support-manual',
    description: 'Extraer datos del manual de soporte',
    schema,
  },
});

const out = await mka1.llm.extract.extractWithSchema({
  schemaId: created.data.id,
  requestBody: {
    model: 'openai:gpt-4.1',
    prompt: 'Extraiga los campos.',
    file: Bun.file('./support-manual.txt'),
  },
});
# Plantilla reutilizable — aquí el esquema es un dict; el id llega bajo data.id
created = sdk.llm.extract.create_schema(
    name="support-manual",
    description="Extraer datos del manual de soporte",
    schema=schema,
)

out = sdk.llm.extract.extract_with_schema(
    schema_id=created.data.id,
    model="openai:gpt-4.1",
    prompt="Extraiga los campos.",
    file={"file_name": "support-manual.txt", "content": open("support-manual.txt", "rb").read()},
)

Agentes, herramientas y MCP

Ejecutar un agente guardado desde la consola Un agente guardado es un objeto de agente reutilizable que almacena su propio comportamiento para que no reconstruya una solicitud de Responses cada vez. Cada agente persiste un modelo, instrucciones y una configuración de herramientas (tools, tool_choice, parallel_tool_calls, max_tool_calls, text, reasoning). Cuando lo ejecuta, el servicio combina su entrada por ejecución con la configuración guardada y la reenvía a la API de Responses a través de mkllm-gateway. Cada ejecución persiste la entrada más el resultado de Responses del upstream, así que también obtiene historial de ejecuciones gratis. Los agentes reciben un id estable como agt_....

Cree un agente

Cree un agente una vez con los SDK de MKA1 para Python, TypeScript o C#, incluyendo una herramienta integrada web_search para que las ejecuciones puedan incorporar información externa actual:
import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({ bearerAuth: 'Bearer YOUR_API_KEY' });

const agent = await mka1.agents.createAgent({
  createAgentRequest: {
    name: 'release-research-agent',
    description: 'Busca información actual de versiones antes de responder.',
    model: 'meetkai:functionary-es-mini',
    instructions: 'Use la búsqueda web cuando la pregunta dependa de información externa actual.',
    tools: [{ type: 'web_search', searchContextSize: 'medium' }],
    metadata: { team: 'docs' },
  },
});
console.log(agent.id);
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

agent = sdk.agents.create_agent(
    name="release-research-agent",
    description="Busca información actual de versiones antes de responder.",
    model="meetkai:functionary-es-mini",
    instructions="Use la búsqueda web cuando la pregunta dependa de información externa actual.",
    tools=[{"type": "web_search", "search_context_size": "medium"}],
    metadata={"team": "docs"},
)

print(agent.id)
El arreglo tools completo (tal como se envía por HTTPS) configura la herramienta integrada:
"tools": [
  { "type": "web_search", "search_context_size": "medium" }
],
"tool_choice": "auto",
"parallel_tool_calls": true

Ejecute un agente

Ejecute enviando solo la entrada por ejecución. La ejecución persiste status, el gateway_response almacenado y gateway_response_id de la llamada upstream. Si la ejecución usó web_search, el gateway_response persistido incluye las entradas de llamadas a herramientas.
const run = await mka1.agentRuns.createAgentRun({
  agentId: agent.id,
  createAgentRunRequest: {
    input: '¿Cuál es la versión estable actual de Bun? Use la búsqueda web antes de responder.',
    metadata: { request_source: 'docs' },
  },
});

console.log(run.gatewayResponseId);
console.log(run.status);
run = sdk.agent_runs.create_agent_run(
    agent_id="agt_123",
    input="¿Cuál es la versión estable actual de Bun? Use la búsqueda web antes de responder.",
    metadata={"request_source": "docs"},
)

print(run.gateway_response_id)
print(run.status)
Use sdk.agents.list_agents(...) / sdk.agent_runs.list_agent_runs(agent_id=...) para inspeccionar agentes guardados y ejecuciones anteriores.
const agents = await mka1.agents.listAgents({});
const runs = await mka1.agentRuns.listAgentRuns({ agentId: agent.id });
agents = sdk.agents.list_agents()
runs = sdk.agent_runs.list_agent_runs(agent_id="agt_123")

Historial de versiones y reversión

Cada cambio confirmado en un agente guardado — crear, actualizar, revertir — añade una versión inmutable, así que el historial de configuración de un agente siempre es inspeccionable. Revertir no reescribe el historial: añade una nueva versión restaurada desde la de destino.
// Actualice el agente — esto confirma la versión 2
await mka1.agents.updateAgent({
  agentId: agent.id,
  updateAgentRequest: { instructions: 'Responda con detalle exhaustivo.' },
});

// Inspeccione el historial
const versions = await mka1.agentVersions.listAgentVersions({ agentId: agent.id });
// versions.data → [ { version: 2, isCurrent: true, … }, { version: 1, … } ]

// Obtenga una versión completa
const v2 = await mka1.agentVersions.getAgentVersion({ agentId: agent.id, version: 2 });

// Revierta a v1 — añade v3 con restoredFromVersion: 1
await mka1.agentVersions.rollbackAgentVersion({ agentId: agent.id, version: 1 });
sdk.agents.update_agent(agent_id=agent.id, instructions="Responda con detalle exhaustivo.")

versions = sdk.agent_versions.list_agent_versions(agent_id=agent.id)
# versions.data → [AgentVersion(version=2, is_current=True, …), AgentVersion(version=1, …)]

v2 = sdk.agent_versions.get_agent_version(agent_id=agent.id, version=2)

sdk.agent_versions.rollback_agent_version(agent_id=agent.id, version=1)
# el historial ahora es v3 (actual, restored_from_version=1), v2, v1

Adjunte un servidor de herramientas MCP

Más allá de las herramientas integradas, puede permitir que el modelo llame a herramientas de un servidor MCP externo añadiendo una entrada mcp a tools. Establezca require_approval en "never" para ejecutar de inmediato, o "always" para pausar y pedir aprobación del usuario final. Limite las herramientas invocables con allowed_tools; pase credenciales upstream en headers (se enmascaran en las respuestas almacenadas).
import type { ResponseObject } from '@meetkai/mka1/models/components';

const response = await mka1.llm.responses.create({
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    instructions: 'Use las herramientas de Linear cuando el usuario pregunte sobre tareas, errores o proyectos.',
    input: 'Liste mi issue de Linear más reciente asignado a mí.',
    tools: [
      {
        type: 'mcp',
        serverLabel: 'Linear MCP',
        serverUrl: 'https://mcp.linear.app/mcp',
        allowedTools: ['issues.list'],
        headers: { Authorization: `Bearer ${process.env.LINEAR_API_KEY}` },
        requireApproval: 'never',
      },
    ],
  },
}) as ResponseObject;

console.log(response.outputText);
import os

response = sdk.llm.responses.create(
    model="meetkai:functionary-es-mini",
    instructions="Use las herramientas de Linear cuando el usuario pregunte sobre tareas, errores o proyectos.",
    input="Liste mi issue de Linear más reciente asignado a mí.",
    tools=[
        {
            "type": "mcp",
            "server_label": "Linear MCP",
            "server_url": "https://mcp.linear.app/mcp",
            "allowed_tools": ["issues.list"],
            "headers": {"Authorization": f"Bearer {os.environ['LINEAR_API_KEY']}"},
            "require_approval": "never",
        },
    ],
)

print(response.output_text)
El modelo llama a la herramienta MCP permitida y devuelve el mensaje final en una sola solicitud. Con require_approval: "always", cree la respuesta en modo de segundo plano, sondéela y maneje el elemento mcp_approval_request devolviendo un mcp_approval_response.

Prompts, habilidades y guardrails

Una plantilla de prompt versionada en el repositorio de prompts MKA1 separa el qué de una llamada LLM (sus prompts), las capacidades que agrupa para ella (habilidades) y la gobernanza que mantiene el uso seguro y con rendición de cuentas (guardrails, limitación de tasa y auditoría).

Repositorio de prompts

La API de Prompts almacena, versiona y renderiza plantillas de prompts de forma centralizada. Cada cambio de plantilla crea una versión inmutable, así que obtiene un historial de cambios completo y puede revertir a cualquier versión anterior en cualquier momento. Una reversión no es destructiva y solo cambia la versión activa. Las plantillas usan marcadores {{variable}} que se renderizan del lado del servidor cuando recupera un prompt, permitiéndole reutilizar una plantilla en distintos contextos. Los prompts están aislados por clave API.
import { SDK } from '@meetkai/mka1';

const mka1 = new SDK({ bearerAuth: `Bearer ${YOUR_API_KEY}` });

const prompt = await mka1.llm.prompts.create({
  createPromptRequest: {
    name: 'greeting',
    template: '¡Hola, {{name}}! Bienvenido a {{company}}.',
  },
});

const rendered = await mka1.llm.prompts.get({
  id: prompt.id,
  variables: JSON.stringify({ name: 'Alice', company: 'Acme' }),
});
console.log(rendered.renderedTemplate); // "¡Hola, Alice! Bienvenido a Acme."
import json

prompt = sdk.llm.prompts.create(
    name="greeting",
    template="¡Hola, {{name}}! Bienvenido a {{company}}.",
)

rendered = sdk.llm.prompts.get(
    id=prompt.id,
    variables=json.dumps({"name": "Alice", "company": "Acme"}),
)
print(rendered.rendered_template)  # "¡Hola, Alice! Bienvenido a Acme."

Habilidades

Las habilidades son paquetes de capacidades reutilizables y versionados que usted sube a la puerta de enlace. Cada habilidad empaqueta el comportamiento de herramientas tras un manifiesto SKILL.md. El nombre y la descripción de la habilidad se leen directamente de ese manifiesto. Puede subir un conjunto de archivos único o un paquete completo, gestionar versiones (cada habilidad rastrea una versión por defecto y la más reciente) y revisar cada archivo antes de crearla. Gestione las habilidades en el panel bajo Skills, o mediante la API de Skills.

Guardrails, limitación de tasa y auditoría de uso

Estas tres funciones de gobernanza mantienen el tráfico delegado y multiusuario controlado y con rendición de cuentas:
  • Limitación de tasa - Cada clave API puede llevar una cuota sobre una ventana configurable — por minuto, hora o día. Cuando una clave supera su límite, la puerta de enlace devuelve 429 Too Many Requests antes de que la solicitud llegue al modelo, así que no se consumen tokens ni se factura uso. Maneje los 429 con reintentos de retroceso exponencial.
  • Auditoría de uso - Revise el uso de tokens, solicitudes y almacenamiento por org y equipo en Admin → Usage, filtrable por usuario (miembros de la org). Para informes por usuario final, consulte la API de uso con su filtro external_user_ids — la identidad X-On-Behalf-Of. Cada respuesta también devuelve un X-Request-ID que puede guardar como clave de correlación.
  • Guardrails - Las decisiones de política se registran en el mismo flujo de auditoría: resultados como policy_violation o throttled y valores de policy_action de warn, block o escalate fluyen a la página de Guardrails, dándole un camino consistente desde un informe de uso hasta la acción exacta que fue permitida, advertida, bloqueada o escalada.
Fuentes: repositorios de prompts, limitación de tasa, auditoría de uso y habilidades.

Habla y voz

Detalle de generación de texto a voz con salida de audio MKA1 expone la voz basada en archivos a través del recurso llm.speech del SDK. Use speak para texto a voz y transcribe para voz a texto. Para conversaciones bidireccionales en tiempo real, use el modo de voz avanzado en su lugar. El modo de voz avanzado se cubre por separado.

Texto a voz

speak devuelve un archivo WAV completo. El cuerpo de la respuesta es audio binario, y los encabezados de respuesta incluyen X-Language-Code.
import { SDK } from '@meetkai/mka1';
import { writeFileSync } from 'node:fs';

const mka1 = new SDK({ bearerAuth: 'Bearer <mka1-api-key>' });

const { headers, result } = await mka1.llm.speech.speak({
  textToSpeechRequest: {
    text: 'Welcome to the MKA1 API speech guide.',
    language: 'en',
  },
});
// headers['x-language-code'] → ['en']

const chunks = [];
for await (const chunk of result) chunks.push(chunk);
writeFileSync('speech.wav', Buffer.concat(chunks));
res = sdk.llm.speech.speak(
    text="Welcome to the MKA1 API speech guide.",
    language="en",
)
# res.headers["x-language-code"] → ["en"]; res.result transmite los bytes WAV

with open("speech.wav", "wb") as fh:
    fh.write(res.result.read())
Para reproducción de baja latencia que comienza antes de que el archivo completo esté listo, use speakStreaming y elija mp3 (más pequeño) o pcm (sin comprimir):
// Variante de baja latencia
const streamed = await mka1.llm.speech.speakStreaming({
  textToSpeechStreamingRequest: {
    text: 'Start speaking this response as soon as audio is ready.',
    language: 'en',
    format: 'mp3',
  },
});
# Variante de baja latencia — note format_ con guion bajo final
streamed = sdk.llm.speech.speak_streaming(
    text="Start speaking this response as soon as audio is ready.",
    language="en",
    format_="mp3",
)

Voz a texto

transcribe acepta un archivo de audio (FLAC, MP3, MP4, M4A, OGG, WAV, WebM, PCM y más) y devuelve la transcripción junto con el idioma detectado y la confianza:
import { openAsBlob } from 'node:fs';

const result = await mka1.llm.speech.transcribe({
  language: 'en',
  prompt: 'This is a technical podcast about machine learning.',
  temperature: 0.2,
  requestBody: { file: await openAsBlob('episode.wav') },
});

console.log(result.text);       // transcripción
console.log(result.confidence); // confianza de la detección
with open("episode.wav", "rb") as fh:
    result = sdk.llm.speech.transcribe(
        file={"file_name": "episode.wav", "content": fh.read()},
        language="en",
        prompt="This is a technical podcast about machine learning.",
        temperature=0.2,
    )

print(result.text)        # transcripción
print(result.confidence)  # confianza de la detección
Para separación de múltiples hablantes, establezca includeSpeakerData: true (requiere audio WAV o PCM). La respuesta entonces incluye un arreglo speakers con segmentos etiquetados y tiempos offset_ms / duration_ms. Archivos fuente: voz, salida multimodal.

Evaluar y observar

Una vez que algo funciona, MKA1 le ayuda a medirlo y a vigilarlo en producción. Una suite de evaluación con conjunto de datos, calificador y versiones
  • Evals - Construya una suite de evaluación a partir de conjuntos de datos, prompts y calificadores, y luego lance ejecuciones duraderas contra uno o más modelos. Rastree la precisión y las puntuaciones por muestra, y compare modelos en una tabla de clasificación. Úselo para elegir un modelo y para detectar regresiones antes de que se publiquen.
  • Sessions - Cada ejecución de agente se registra. Reproduzca la transcripción (mensajes, razonamiento, llamadas a herramientas) y recorra los eventos sin procesar para depurar exactamente qué hizo un agente.
  • Uso y auditoría - Revise el uso de tokens, solicitudes y almacenamiento por org y equipo en Admin → Usage, y filtre por usuario final cuando envíe X-On-Behalf-Of. Cada respuesta también devuelve un X-Request-ID que puede guardar como clave de correlación.

Auditoría

La vista de Audit del tráfico de la puerta de enlace en Admin → Audit Audit (Admin → Audit) es la superficie de revisión del tráfico que pasó por la puerta de enlace. Los administradores del clúster ven solicitudes de todas las organizaciones y equipos; los administradores de organización ven la actividad de su propia org. Busque por ruta, path o usuario; filtre por servicio, método, estado, modelo o estado de revisión; o pegue un X-Request-ID — devuelto en cada respuesta de la API — para saltar a la solicitud exacta. Marque entradas para revisión, agrupe solicitudes relacionadas en casos y exporte datos de respuesta para análisis fuera de línea.

Alertas

Endpoints de webhook de alertas en Admin → Alerts Las alertas convierten los fallos en webhooks. En Admin → Alerts, registre una URL de endpoint y elija su alcance: todo el clúster (administradores del clúster), su organización (propietarios y administradores de org) o un solo equipo — los administradores de org pueden apuntar a cualquier equipo, y los miembros de equipo pueden gestionar webhooks de su propio equipo activo. Suscriba el endpoint a uno o ambos tipos de evento — response.failed (una solicitud de respuesta falló en el proveedor del modelo) y gateway.request.failed (cualquier solicitud de la puerta de enlace devolvió un 5xx) — o deje la suscripción vacía para recibirlos todos. Los filtros opcionales limitan la entrega a claves API, códigos de error o modelos específicos. Cada endpoint tiene una página de detalle que muestra su configuración, su secreto de firma (revelarlo, copiarlo o rotarlo) y las entregas recientes con cargas útiles y estado succeeded / failed / pending. Desde ahí puede reenviar una entrega, disparar una alerta de prueba mientras integra, y editar, deshabilitar o eliminar el endpoint — editar nunca cambia el secreto de firma.

Precios, presupuestos y uso

Cada solicitud fluye por una tubería de facturación: el uso registra los volúmenes, el libro de precios de modelos los convierte en costos y los presupuestos aplican límites sobre el resultado. Esta sección cubre los tres.

Precios

Formulario de añadir precio de modelo en Admin → Pricing Cada solicitud se mide y se tarifica contra el libro de precios de modelos de su clúster. Los administradores del clúster mantienen el libro de precios en Admin → Pricing:
  • Moneda del clúster - La moneda en la que se denominan todos los precios y presupuestos.
  • Precios de modelos - La tarifa por defecto del clúster, un precio por modelo. Las dimensiones de tarifa siguen la modalidad del modelo: tokens de entrada, salida, entrada en caché y razonamiento para LLM; audio y caracteres para voz; tarifas por imagen con niveles opcionales por tamaño; búsqueda web.
  • Anulaciones por org - Precios por organización para cuando una org factura distinto del valor por defecto del clúster.
  • Tarifas efectivas - Una vista de resolución que muestra qué precio — por defecto del clúster, anulación de org o sin precio — resuelve cada modelo para una organización dada. Los modelos sin precio facturan a 0.
Los precios llevan fecha: guardar añade una nueva versión y nunca reescribe el costo pasado. El gasto aparece entonces en dos lugares:
  • Admin → Usage - Gasto total tarificado desde el libro de precios, desglosado por organización, equipo, clave API y modelo — junto con los volúmenes subyacentes (vea Uso más abajo).
  • La API - Consulte el gasto en cualquier rango de tiempo, agrupado por modelo, clave API, equipo, organización o usuario final (la identidad X-On-Behalf-Of). Este es el alimentador para sistemas de facturación; los Presupuestos (abajo) aplican límites contra el mismo gasto.
const now = Math.floor(Date.now() / 1000);

const spend = await mka1.usage.costs({
  startTime: now - 7 * 24 * 60 * 60, // últimos 7 días (segundos unix)
  endTime: now,
  groupBy: 'model,api_key_id', // dimensiones separadas por comas
});
// spend.data → [{ model, apiKeyId, teamId, externalUserId, orgId, cost }, …]
import time

now = int(time.time())
spend = sdk.usage.costs(
    start_time=now - 7 * 24 * 3600,  # últimos 7 días (segundos unix)
    end_time=now,
    group_by="model,api_key_id",  # dimensiones separadas por comas
)
# spend.data → filas con model, api_key_id, team_id, external_user_id, org_id, cost

Presupuestos

Formulario de nuevo presupuesto de organización en Admin → Budgets Los presupuestos limitan el gasto total por período en una organización o una clave API. Créelos y gestiónelos en Admin → Budgets — los administradores de organización gestionan los presupuestos de su org, mientras que los presupuestos de claves API hoy los gestiona el administrador del clúster. Un presupuesto tiene tres partes:
  • Período y límite - Diario, semanal o mensual, con un límite en la moneda del clúster. Las ventanas de gasto se reinician en los límites del calendario UTC.
  • Umbrales - Porcentajes únicos del límite, cada uno emparejado con una acción: alert (notificar) o block (rechazar más solicitudes). Un presupuesto que superó un umbral de bloqueo muestra Blocked en las columnas en vivo Spend y Status.
  • Webhook de alerta (opcional) - Una URL más un secreto de firma HMAC que recibe las notificaciones de umbral.
Cada fila de presupuesto muestra el gasto en vivo contra su límite; abra el historial de un presupuesto para revisar los eventos de umbral del período, y edite o elimine presupuestos según cambien las necesidades. Los presupuestos tienen dos propietarios: los presupuestos de clúster son techos del operador (solo lectura para administradores de org), mientras que los presupuestos de org son autoimpuestos. La aplicación es de mejor esfuerzo y fail-open, así que dimensione los límites con margen. Las mismas operaciones están disponibles por la API — conceda a la clave los scopes de Presupuestos exclusivos de administrador (read:budgets / write:budgets) en el asistente de claves del Paso 4.
// Presupuesto mensual propio en una clave API: advertir al 80%, bloquear al 100%
await mka1.budgets.setApiKey({
  apiKeyId: 'ak_…',
  requestBody: {
    period: 'monthly',
    limit: 250, // en la moneda de su clúster — vea budgets.getCurrency()
    thresholds: [
      { pct: 80, action: 'alert' },
      { pct: 100, action: 'block' },
    ],
    webhookUrl: 'https://your-app.example.com/hooks/budget',
    webhookSecret: process.env.MKA1_WEBHOOK_SECRET,
  },
});

const budgets = await mka1.budgets.getApiKey({ apiKeyId: 'ak_…' });
const events = await mka1.budgets.apiKeyEvents({ apiKeyId: 'ak_…' });
await mka1.budgets.deleteApiKey({ apiKeyId: 'ak_…', owner: 'org' });

// Variantes a nivel de org: budgets.setOrg / getOrg / deleteOrg / orgEvents ({ orgId, … })
sdk.budgets.set_api_key(
    api_key_id="ak_…",
    period="monthly",
    limit=250,
    thresholds=[
        {"pct": 80, "action": "alert"},
        {"pct": 100, "action": "block"},
    ],
)

budgets = sdk.budgets.get_api_key(api_key_id="ak_…")
events = sdk.budgets.api_key_events(api_key_id="ak_…")
sdk.budgets.delete_api_key(api_key_id="ak_…", owner="org")

# Variantes a nivel de org: set_org / get_org / delete_org / org_events (org_id=…)

Uso

El panel de Usage con tokens en el tiempo y desgloses por modelo en Admin → Usage El uso es el libro de volúmenes detrás de los precios y los presupuestos — los tokens, conteos de solicitudes y almacenamiento de cada solicitud se miden por organización, equipo, clave API y usuario final. Vive en dos lugares:
  • En la consola - Admin → Usage muestra un gráfico de tokens en el tiempo (24h / 7d / 30d), desgloses por categoría (Responses, Completions, Embeddings, Classify, Extract) con tokens de entrada/salida y conteos de solicitudes por modelo, filas por usuario final, almacenamiento de archivos y vectores, y operaciones de sandbox — todo exportable como CSV. La sección de gasto tarifica estos volúmenes desde el libro de precios de modelos (vea Precios arriba).
  • Por la API - Los endpoints por categoría (llm.usage.responses, completions, conversations, embeddings, extract, classify, vectorStores, files) devuelven series agrupadas en el tiempo. Elija un bucket_width, filtre por models, user_ids o external_user_ids (la identidad X-On-Behalf-Of) y agrupe por model, api_key_id, user_id, org_id o background para informes por dimensión.
const now = Math.floor(Date.now() / 1000);

const usage = await mka1.llm.usage.responses({
  startTime: now - 7 * 24 * 60 * 60, // últimos 7 días (segundos unix)
  endTime: now,
  bucketWidth: '1d',
  groupBy: 'model',
});
// usage.data → un bucket por día, cada uno con resultados por modelo
// (tokens de entrada/salida, conteos de solicitudes)
import time

now = int(time.time())
usage = sdk.llm.usage.responses(
    start_time=now - 7 * 24 * 3600,  # últimos 7 días (segundos unix)
    end_time=now,
    bucket_width="1d",
    group_by="model",
)
# usage.data → un bucket por día, cada uno con resultados por modelo

Serving

Serving convierte los aceleradores de su clúster — GPU, NPU o TPU — en endpoints de inferencia con autoescalado para los modelos que usted elija. Vive en su propia sección Serving de la barra lateral (administradores de organización y de clúster), y su organización debe ser aprovisionada para serving por el operador del clúster antes del primer uso. Seis bloques de construcción:
  • Deployments - Un modelo servido tras un endpoint de inferencia en aceleradores dedicados, respaldado por vLLM o SGLang. Los cambios de configuración generan una nueva revisión — vuelva a cualquier revisión anterior en cualquier momento — mientras que los cambios de escalado se aplican en el sitio. La URL del endpoint se asigna cuando el despliegue está listo, y la autenticación del endpoint requiere que los llamadores presenten una clave API válida. Cada despliegue expone estado, réplicas, revisiones, registros y métricas.
  • Models - Registre un modelo servible por nombre y origen, opcionalmente fijando una rama, etiqueta o revisión de commit para despliegues reproducibles.
  • Images - Construya imágenes de contenedor personalizadas (imagen OCI base, paquetes apt, comandos de build) para motores de serving y trabajos de fine-tuning; los despliegues usan por defecto la imagen estándar del motor.
  • Fine-tune jobs - Entrene en los aceleradores del clúster: un modelo base, un conjunto de datos, una estrategia (LoRA por defecto, o fine-tuning completo) e hiperparámetros libres. Siga los registros y la línea de tiempo de eventos, recoja checkpoints y cancele en cualquier momento.
  • Accelerators - Los tipos de aceleradores disponibles para su organización (p. ej. A100, H100) y sus límites por tipo.
  • Volumes & secrets - Volúmenes persistentes (de tamaño fijo, o elásticos que crecen bajo demanda) y secretos como un hf-token, inyectados en los despliegues como variables de entorno.
El autoescalado es por despliegue: réplicas mínimas y máximas, réplicas de reserva listas para absorber ráfagas, un tope de solicitudes concurrentes enrutadas a una réplica antes de escalar hacia afuera, y una ventana de inactividad (2–1200 segundos) antes de reducir la escala.
// 1. Registre el modelo a servir (fije una revisión para despliegues reproducibles)
await mka1.serving.models.register({
  modelRegister: { name: 'qwen-7b', source: 'Qwen/Qwen2.5-7B-Instruct' },
});

// 2. Despliéguelo tras un endpoint con autoescalado
const deployment = await mka1.serving.deployments.create({
  deploymentCreate: {
    name: 'qwen-7b-prod',
    model: 'qwen-7b',
    engine: 'vllm',
    accelerator: { type: 'H100', count: 1, fallback: ['A100'] },
    scaling: { minContainers: 1, maxContainers: 4, maxConcurrentInputs: 32 },
    engineArgs: ['--max-model-len', '8192'],
    endpointAuth: true,
  },
});
// la URL del endpoint aparece en el despliegue cuando está listo

// 3. Opérelo
await mka1.serving.deployments.updateScaling({
  deploymentId: deployment.id,
  scaling: { minContainers: 2, maxContainers: 8 }, // se aplica en el sitio — sin nueva revisión
});

const logs = await mka1.serving.deployments.getLogs({ deploymentId: deployment.id, tail: 100 });

await mka1.serving.deployments.rollback({
  deploymentId: deployment.id,
  deploymentRollbackRequest: { revision: 1 }, // los cambios de configuración generan revisiones
});
# 1. Registre el modelo a servir (fije una revisión para despliegues reproducibles)
sdk.serving.models.register(name="qwen-7b", source="Qwen/Qwen2.5-7B-Instruct")

# 2. Despliéguelo tras un endpoint con autoescalado
deployment = sdk.serving.deployments.create(
    name="qwen-7b-prod",
    model="qwen-7b",
    engine="vllm",
    accelerator={"type": "H100", "count": 1, "fallback": ["A100"]},
    scaling={"min_containers": 1, "max_containers": 4, "max_concurrent_inputs": 32},
    engine_args=["--max-model-len", "8192"],
    endpoint_auth=True,
)
# la URL del endpoint aparece en el despliegue cuando está listo

# 3. Opérelo
sdk.serving.deployments.update_scaling(
    deployment_id=deployment.id,
    min_containers=2,
    max_containers=8,  # se aplica en el sitio — sin nueva revisión
)

logs = sdk.serving.deployments.get_logs(deployment_id=deployment.id, tail=100)

sdk.serving.deployments.rollback(deployment_id=deployment.id, revision=1)

En conjunto: construya un agente de principio a fin

Los bloques de construcción se componen. Este es el flujo insignia de principio a fin: indexe conocimiento, conecte herramientas, empaquete una habilidad, ensamble un agente, ejecútelo y rastree el resultado. Formulario de creación de agente con herramientas integradas
  1. Indexe conocimiento. Suba sus documentos como Files y adjúntelos a un Vector Store para que el agente pueda fundamentar respuestas en su contenido (vea Archivos, almacenes vectoriales y recuperación).
  2. Conecte herramientas. Registre un servidor MCP (o use herramientas integradas como web_search) para que el agente pueda actuar y obtener datos en vivo (vea Agentes, herramientas y MCP).
  3. Empaquete una habilidad. Agrupe comportamiento reutilizable tras un SKILL.md y súbalo bajo Skills, luego adjúntelo.
  4. Ensamble el agente. Cree un agente guardado con un modelo, instrucciones y ese conjunto de herramientas. Configura el agente una vez, así que no reconstruye la solicitud en cada llamada.
  5. Ejecútelo. Ejecute el agente con entrada nueva desde la consola o POST /api/v1/agents/{id}/runs. Cada ejecución persiste su entrada y la respuesta de la puerta de enlace.
  6. Rastree la ejecución. Abra Sessions para reproducir la transcripción y confirmar que el agente llamó a las herramientas correctas.

Referencia y soporte

Tenga esto a mano mientras construye:
Resumen rápido
  1. Acepte la invitación al clúster → es propietario de una nueva organización.
  2. Cree un equipo e invite a compañeros.
  3. Genere una clave API en ese equipo (copie el secreto una vez).
  4. Instale un SDK y autentíquese con Authorization: Bearer.
  5. Llame a responses.create — luego componga conversaciones, memoria, RAG, agentes, herramientas y voz en su app.
Bienvenido a bordo. Ahora vaya a construir algo.