Resumen
Las funciones lógicas son funciones de TypeScript del lado del servidor que se ejecutan en la plataforma Twenty. Pueden activarse mediante solicitudes HTTP, programaciones de cron o eventos de base de datos — y también pueden exponerse como herramientas para agentes de IA.defineLogicFunction
Define funciones de lógica y sus desencadenadores
defineLogicFunction
Define funciones de lógica y sus desencadenadores
Cada archivo de función usa Tipos de desencadenadores disponibles:El tipo En tu controlador, accede a los encabezados reenviados así:Por razones de seguridad, los encabezados de la respuesta están restringidos a una lista de permitidos. Cualquier encabezado que no esté en la lista (por ejemplo, El endpoint es accesible en:El primer segmento es el id del registro de tu aplicación; el segundo es el Responder a un El desafío llega en Contrato del resolver. El tipo La carga útil incluye:Ejemplo de evento de actualización:Ejecutar solo en actualizaciones de correo electrónico:Ejemplo de evento de eliminación:El manejador recibe entonces un Los eventos se agrupan por el usuario que los provocó antes de crear los lotes, por lo que cada llamada abarca un único actor y Crea ambos una vez, en el ámbito del módulo, y cada sitio de llamada indica entonces qué acceso utiliza según el cliente al que llama. Las utilidades del SDK que acceden a los recursos propios de tu aplicación siempre usan su acceso e ignoran Puntos clave:Para declarar tus parámetros una sola vez y atender ambas superficies, define un único JSON Schema (El componente lee la llamada que está renderizando con El componente se monta en cuanto el agente termina de transmitir sus argumentos, por lo que gestiona toda la llamada, no solo el resultado. Una vez que la aplicación está instalada, Enrich Company aparece en el selector de acciones del generador de flujos de trabajo. El generador representa
defineLogicFunction() para exportar una configuración con un controlador y desencadenadores opcionales.src/logic-functions/createPostCard.logic-function.ts
- httpRoute: Expone tu función en una ruta y método HTTP. En el código de la aplicación, añade el prefijo
/s/a la ruta cuando usesRestApiClient; la URL desplegada utiliza la base inyectadaTWENTY_FUNCTIONS_URL(o\<server-url>/scuando no está configurada).
Para invocar una función de lógica activada por una ruta desde un componente de frontend (headless), consulta Llamar a una función de lógica.
- cron: Ejecuta tu función en un horario usando una expresión CRON.
- databaseEvent: Se ejecuta en eventos del ciclo de vida de objetos del espacio de trabajo. Cuando la operación del evento es
updated, se pueden especificar campos específicos que se deben escuchar en la matrizupdatedFields. Si se deja sin definir o vacío, cualquier actualización activará la función.
p. ej.person.updated,*.created,company.*
- serverRoute: expone una única ruta HTTP con ámbito de registro. Una función de resolver (declarada con
serverRouteTriggerSettings) se ejecuta en el espacio de trabajo propietario y devuelve unaResponsesíncrona o el espacio de trabajo de destino Y la función de lógica de destino para poner en cola; en la ruta de encolado, la plataforma confirma con202y ejecuta ese destino en la cola de workers. Consulta Disparador de ruta de servidor.
También puedes ejecutar manualmente una función usando la CLI:Puedes ver los registros con:
En la nube, cada ejecución consume créditos del espacio de trabajo: un cargo fijo por
invocación más un cargo por milisegundo por el tiempo que se ejecuta la función, por lo que
mantener
timeoutSeconds ajustado y el código rápido reduce los costos. Consulta
Créditos para conocer las tarifas.Carga útil del disparador de ruta
Cuando un desencadenador de ruta invoca tu función de lógica, esta recibe un objetoRoutePayload que sigue el
formato AWS HTTP API v2.
Importa el tipo RoutePayload desde twenty-sdk/logic-function:RoutePayload tiene la siguiente estructura:forwardedRequestHeaders
De forma predeterminada, los encabezados HTTP de las solicitudes entrantes no se pasan a tu función de lógica por razones de seguridad. Para acceder a encabezados específicos, enuméralos explícitamente en el arregloforwardedRequestHeaders:Los nombres de los encabezados se normalizan a minúsculas. Accede a ellos usando claves en minúsculas
(p. ej.,
event.headers['content-type']).Respuesta HTTP personalizada
De forma predeterminada, devolver un valor sencillo desde tu controlador lo envía de vuelta como una respuesta200 (JSON para objetos, text/plain para cadenas). Para controlar el código de estado y los encabezados de la respuesta, devuelve un Response desde twenty-sdk/logic-function:Set-Cookie, encabezados CORS como Access-Control-Allow-Origin, o encabezados personalizados X-*) se descarta silenciosamente antes de que se envíe la respuesta. Los encabezados de respuesta permitidos son:content-typecontent-languagecontent-dispositioncache-controlretry-after
El código de estado debe ser un código de estado HTTP válido (entre 100 y 599).
Los nombres de los encabezados de respuesta se comparan sin distinguir mayúsculas de minúsculas.
Respuestas de error de la plataforma
Más allá de las propias respuestas de tu controlador, la plataforma responde directamente a las llamadas de ruta en algunas situaciones:404 cuando la ruta o la función no existe, 403 cuando la aplicación está detenida, 402 cuando el espacio de trabajo ha agotado su asignación de créditos o no tiene una suscripción activa, 409 cuando se alcanza un límite de almacenamiento, 429 cuando se alcanza un límite de velocidad de ejecución o un límite de uso y 422 cuando las dependencies de producción de la aplicación son demasiado grandes para instalarlas; consulta límites de tamaño de dependencias.Disparador de ruta de servidor
httpRouteTriggerSettings expone una función bajo /s/ y resuelve el espacio de trabajo a partir del host de la solicitud — lo cual funciona cuando cada espacio de trabajo tiene su propio dominio. Los proveedores de terceros, sin embargo, entregan los eventos de cada inquilino a una URL. Para ese caso, usa serverRouteTriggerSettings.El disparador tiene dos partes:-
Una función de lógica de resolver — declarada con
serverRouteTriggerSettings— se ejecuta en tu espacio de trabajo propietario (el espacio de trabajo que es propietario del registro de la aplicación). Inspecciona la solicitud entrante y devuelve una de las siguientes opciones:{ workspaceId, targetLogicFunctionUniversalIdentifier, payload? }— la plataforma pone en cola ese destino en el espacio de trabajo resuelto y confirma con202 { queued: true }, o- un
Responsedetwenty-sdk/logic-function— la plataforma replica esa respuesta HTTP de forma sincrónica y no pone en cola un destino (usa esto para desafíos de verificación comourl_verificationde Slack).
rawBodyoriginal y a los encabezados reenviados, y puede rechazar sin tocar nunca el destino. - Luego, una función de lógica de destino — una función de lógica normal por espacio de trabajo — se ejecuta en el espacio de trabajo resuelto con el payload devuelto por el resolver (o el payload original de la solicitud si el resolver no lo transformó). Su valor de retorno no es observado por el solicitante HTTP cuando el resolver eligió la ruta de encolado.
src/logic-functions/resolve-server-route.logic-function.ts
src/logic-functions/handle-invoice-paid.logic-function.ts
universalIdentifier del resolver de tu manifiesto. Una ruta solo se resuelve en un resolver de ese registro, en su espacio de trabajo propietario. Cuando tu aplicación registra el webhook en sí, crea la URL desde dentro de una función lógica con getServerRouteUrl; Twenty inyecta la URL base de las rutas de servidor de tu aplicación como TWENTY_SERVER_ROUTES_URL:Las URL que solo contienen el
id o el universalIdentifier del resolvedor
(/webhooks/server/:identifier) aún se resuelven por ahora, y ambas responden con
un encabezado Deprecation. La forma universalIdentifier devuelve 409 cuando dos
registros declaran el mismo identificador. Traslade las URL registradas con sus
proveedores al formulario de registro.GET de verificación. Algunos proveedores verifican un punto de conexión antes de entregar contenido en él, enviando un GET con un desafío a la misma URL a la que más tarde enviarán eventos mediante POST; la API de WhatsApp Cloud de Meta es uno de ellos. Una ruta de servidor responde solo a POST, a menos que indiques lo contrario, así que declara ambos métodos:event.queryStringParameters, y devolver una Response lo reenvía al proveedor en la misma solicitud. Un cuerpo de cadena se envía como text/plain, que es lo que esperan estos proveedores:httpMethods reemplaza el valor predeterminado en lugar de añadirse a él, por lo que ['GET'] por sí solo hace que la ruta rechace POST. Solo se admiten GET y POST. Déjalo sin configurar a menos que el proveedor necesite el segundo verbo: una ruta que declara GET tendrá su resolver ejecutado por cualquier llamador no autenticado, incluidos los rastreadores y los desplegadores de enlaces que envían GET sin solicitarlo. Cualquier solicitud para la que la plataforma no tenga un método se responde con 405 sin que el resolver llegue a ejecutarse.La aplicación debe reclamarse e instalarse en su espacio de trabajo propietario.
Sigue Reclamar tu
aplicación para
asignar un propietario y, luego, instala la aplicación en ese espacio de trabajo. Hasta que ambas condiciones se cumplan,
el resolver no tiene dónde ejecutarse y la ruta del servidor devuelve
404
(LOGIC_FUNCTION_NOT_FOUND), incluso si la aplicación está instalada en otro lugar.
La búsqueda de Marketplace oculta las aplicaciones con rutas de servidor hasta que esta configuración y todas
las variables de servidor requeridas estén completas. Consulta costos y
disponibilidad del espacio de trabajo propietario
para obtener detalles operativos y de facturación.LogicFunctionConfig del SDK aplica esto en tiempo de compilación: tan pronto como configuras serverRouteTriggerSettings, tu handler se ve obligado a devolver un Response, o { workspaceId: string; targetLogicFunctionUniversalIdentifier: string; payload?: object } (o un Promise de cualquiera de los dos). En la ruta de envío, el workspaceId debe ser un espacio de trabajo donde la función de destino esté instalada; de lo contrario, la solicitud se rechaza con 404. Un resultado que no coincide con ninguna de las dos formas —incluido uno cuyos identificadores no sean UUID— se rechaza con 502.Tokens de portador. Algunos proveedores, como Microsoft Bot Framework, firman cada solicitud con un JWT en el encabezado
Authorization en lugar de un encabezado de firma. Una ruta de servidor puede incluir authorization en forwardedRequestHeaders para recibirlo, y el resolvedor lo verifica como cualquier otra firma. La plataforma elimina el encabezado si contiene un token emitido por Twenty, por lo que una ruta de servidor nunca recibe una sesión de Twenty. cookie y proxy-authorization nunca se reenvían, y las rutas HTTP no pueden reenviar ninguno de estos tres encabezados.Para las firmas de solicitudes, la mayoría de los proveedores firman con HMAC-SHA256; las partes que difieren son el nombre del encabezado, la codificación del digest y la cadena firmada del payload. Algunos ejemplos:El ejemplo de resolver anterior ya muestra el flujo HMAC-SHA256 de GitHub; adapta el nombre del encabezado, la codificación del digest y la cadena firmada del payload según el proveedor con el que te estés integrando.
Cuando el resolver devuelve un objeto de envío, la ruta responde
202 { queued: true } y el destino se ejecuta en la cola de workers: el solicitante nunca observa la latencia, el resultado ni los fallos del destino (estos se registran en los registros de ejecución). Esto evita que los reintentos del remitente amplifiquen las ralentizaciones del procesamiento, que es lo que se desea para la ingesta de webhooks.El resolvedor se ejecuta en el espacio de trabajo del propietario y consume sus créditos, por lo que la ruta responde 402 cuando ese espacio de trabajo ha agotado su asignación o no tiene una suscripción activa, y 429 cuando se alcanza un límite de uso. Los remitentes que reintentan ante 5xx no reintentará estas respuestas, que es lo que quieres: la denegación no se resolverá en el siguiente intento.Cuando el solicitante deba leer el cuerpo de la respuesta en la misma solicitud (desafíos de verificación, acuses de recibo interactivos), en su lugar devuelve un Response desde el resolver. La plataforma lo replica de forma síncrona y omite la cola; sus cabeceras pasan por la misma lista de permitidos que las respuestas de rutas HTTP. Mantén el resolver rápido: algunos proveedores (p. ej. Slack) agotan el tiempo de espera en pocos segundos. Como el resolver es accesible como un endpoint público, protégelo con limitación de tasa en el edge.Payload del disparador de evento de base de datos
Cuando un desencadenador de eventos de base de datos invoca tu función lógica, esta recibe unDatabaseEventPayload por cada registro modificado (o un DatabaseEventBatchPayload que abarca varios registros cuando batchMode está habilitado). El payload combina metadatos sobre el espacio de trabajo y el objeto de origen con el evento a nivel de registro.Para eliminaciones lógicas (soft deletes),
.deleted sigue la estructura de estilo de actualización porque el campo deletedAt del registro cambia.
Para eliminaciones permanentes, usa .destroyed.databaseEventTriggerSettings.updatedFields filtra qué eventos de actualización
activan la función. event.properties.updatedFields te indica qué campos
realmente cambiaron en el evento actual.databaseEventTriggerSettings acepta:Ejemplo de evento de creación:
Agrupación de eventos de base de datos
Una escritura masiva emite muchos eventos a la vez: por ejemplo, importar un buzón puede actualizar miles de registros en una sola operación, y una llamada por registro satura la cola. EstablecebatchMode para recibirlos juntos:DatabaseEventBatchPayload, que contiene los mismos metadatos que DatabaseEventPayload, pero sustituye los campos de nivel de registro por un arreglo events:El tamaño del lote no es algo en lo que un manejador pueda confiar. El servidor decide cuántos
eventos contiene una llamada, con un límite de 200, y un lote contiene desde un solo
evento hasta ese límite, según cuántos haya producido la escritura de origen.
Escribe el manejador para iterar sobre
events independientemente de su longitud.context.workspaceMemberId mantiene su significado. El filtrado de updatedFields se aplica antes de crear los lotes, por lo que un lote solo contiene los registros que solicitaste.Sin batchMode, el manejador sigue recibiendo un DatabaseEventPayload por registro.Contexto de ejecución
Los controladores de funciones de lógica genérica reciben un segundo argumento que describe la ejecución en sí, independientemente de qué la haya activado. Mientras que el primer argumento cambia de forma según el desencadenante, este no:userWorkspaceId y workspaceMemberId son null cuando nadie desencadenó la ejecución: las programaciones cron, los hooks de instalación y los webhooks no autenticados no tienen a ninguna persona detrás. También son null cuando la persona no tiene un registro de miembro del espacio de trabajo, o cuando el suyo se ha eliminado.El contexto te indica quién activó la ejecución. Lo que la ejecución puede hacer es una
declaración independiente, a continuación.
Qué acceso utiliza una llamada
Cada cliente —CoreApiClient, MetadataApiClient y RestApiClient — actúa como la persona que desencadenó la ejecución: su rol se intersecta con el de tu aplicación, por lo que la llamada nunca puede hacer más de lo que cualquiera de los dos puede hacer. Ese es el comportamiento predeterminado y significa que una persona nunca puede usar tu aplicación para superar sus propios permisos.Cuando nadie desencadenó la ejecución, no hay ninguna persona como la que actuar, por lo que el mismo cliente recurre al acceso propio de tu aplicación: las programaciones cron, los hooks de instalación y los webhooks no autenticados no requieren ninguna gestión especial.Algunas llamadas necesitan legítimamente el acceso propio de la aplicación incluso cuando hay una persona detrás de la ejecución — por ejemplo, para leer los registros de configuración de tu aplicación o realizar trabajo que esa persona no podría hacer por sí misma. Crea un segundo cliente para esos casos:RestApiClient acepta la misma opción:Una ejecución que nadie desencadenó actúa como tu aplicación. Las programaciones cron, los hooks de instalación y los webhooks no autenticados no tienen a ninguna persona detrás, por lo que el cliente predeterminado recurre al acceso propio de tu aplicación y sigue funcionando.
runAs: 'application' solo se necesita cuando quieres ese acceso en una ejecución que una persona sí desencadenó.Comprueba context.workspaceMemberId cuando una función se comporta de forma diferente según haya alguien detrás de ella, por ejemplo, para atribuir un registro.runAs: el almacén de clave-valor, las conexiones, los canales de mensajería, runAgent, getPublicAssetUrl y el cargo de créditos. En cambio, ai.generate sigue a los clientes predeterminados: actúa como la persona que desencadenó la ejecución, dentro del rol de tu aplicación, o como tu aplicación cuando nadie lo hizo.Exponer una función como herramienta de IA o acción de flujo de trabajo
Las funciones lógicas pueden exponerse en dos ámbitos, cada uno con su propio disparador:toolTriggerSettings— hace que la función sea descubrible por las funciones de IA de Twenty (chat, MCP, llamadas a funciones). Usa el JSON Schema estándar, el formato que los LLM entienden de forma nativa.workflowActionTriggerSettings— hace que la función aparezca como un paso en el constructor visual de flujos de trabajo. Usa elInputSchemacompleto de Twenty para que el constructor pueda renderizar editores de campos adecuados, selectores de variables y etiquetas.
cronTriggerSettings, databaseEventTriggerSettings y httpRouteTriggerSettings — mismo patrón, misma estructura.Relación con la acción Code del flujo de trabajo. La acción integrada Code en
el generador de flujos de trabajo es en sí misma una función lógica — Twenty crea una por cada paso de Code
y expone su editor en línea.
workflowActionTriggerSettings es la forma de convertir ese código puntual
en línea en una acción reutilizable: define la función una vez en tu aplicación y se vuelve
seleccionable en cualquier flujo de trabajo, en lugar de copiarla y pegarla en cada paso de Code. Consulta la acción
Code en la guía del
usuario para ver la perspectiva del usuario final.src/logic-functions/enrich-company.logic-function.ts
- Una función puede mezclar superficies — declara tanto
toolTriggerSettingscomoworkflowActionTriggerSettingspara exponerla en el chat Y en el constructor de flujos de trabajo. - Ambos,
toolTriggerSettings.inputSchemayworkflowActionTriggerSettings.inputSchema, son opcionales. Cuando se omiten, el generador del manifiesto los infiere a partir del código fuente del controlador (JSON Schema para la herramienta de IA,InputSchemade Twenty para la acción de flujo de trabajo). Proporciona uno explícitamente cuando quieras un tipado más rico — por ejemplo, con campos compatibles conFieldMetadataTypecomoCURRENCYoRELATIONpara el constructor de flujos de trabajo, o con camposdescriptionque el agente de IA pueda leer:
InputJsonSchema) y conviértelo para la acción de flujo de trabajo con jsonSchemaToInputSchema de twenty-sdk/logic-function. toolTriggerSettings.inputSchema usa directamente el JSON Schema, mientras que workflowActionTriggerSettings.inputSchema espera el InputSchema de Twenty:Renderizar una llamada a herramienta con un componente frontal.
De forma predeterminada, una llamada a herramienta aparece en el chat de IA como una fila de paso: el nombre de la herramienta y un indicador de carga hasta que devuelve una respuesta. ApuntatoolTriggerSettings.frontComponentUniversalIdentifier a uno de tus componentes frontales y el chat renderizará ese componente en línea en su lugar, para cada llamada a esta herramienta.useToolCall():src/front-components/invoice-preview.tsx
toolCall.status pasa por input-available, los estados de aprobación cuando la herramienta necesita una y, después, output-available, output-denied o output-error; input es lo que propuso el agente y output lo que devolvió tu controlador. Renderiza cada estado que te importe, ya que la fila de paso ya no está ahí para cubrirlos.Tanto input como output tienen el tipo Record\<string, unknown>, así que delimita el tipo de cada campo antes de usarlo en lugar de realizar conversiones de tipo. Esto es especialmente importante para cualquier valor que pases al DOM: un valor que insertes en un href sin comprobar que sea una cadena es un enlace controlado por la salida de la herramienta.Si el identificador no coincide con ningún componente frontal de la aplicación, el chat vuelve
a la fila de pasos predeterminada. Los componentes frontales del chat de IA se ejecutan con el mismo
rol que declara tu aplicación, por lo que un widget
solo puede leer y escribir lo que la propia aplicación tiene permitido.
Ejemplo completo de una acción de flujo de trabajo
workflowActionTriggerSettings acepta cuatro campos:Uniéndolo todo: una función expuesta como una acción de flujo de trabajo, con una salida declarada para que los pasos posteriores puedan hacer referencia a
taskId:src/logic-functions/enrich-company.logic-function.ts
companyName y domain como campos de entrada (cada uno puede extraer valores de pasos anteriores), y los pasos posteriores pueden hacer referencia a las salidas taskId y enriched de ese paso.Escribe una buena
description. Los agentes de IA se basan en el campo
description de la función para decidir cuándo usar la herramienta. Sé específico sobre lo que hace la herramienta y
cuándo debe invocarse.Utilidades en tiempo de ejecución.
twenty-sdk/utils vuelve a exportar pequeñas utilidades en tiempo de ejecución para que los handlers nunca importen directamente desde twenty-shared. Por ejemplo, isDefined(value) devuelve false tanto para null como para undefined — utilízalo para acotar de forma segura las entradas opcionales de los handlers, que pueden llegar como null en tiempo de ejecución incluso cuando están tipadas como T | undefined:Hooks de instalación — los controladores de preinstalación, postinstalación y desinstalación — comparten
este entorno de ejecución, pero se declaran con sus propias funciones define y no aceptan
configuraciones de disparador. Consulta Hooks de
instalación para
definePreInstallLogicFunction, definePostInstallLogicFunction y
defineUninstallLogicFunction.Comprobación de estado
Declara una comprobación de estado condefineHealthCheck para informar si tu aplicación realmente puede ejecutarse. Es para aquello que solo la aplicación puede saber: una clave presente pero revocada, una cuenta con el plan equivocado, un webhook que nunca se registró. Lo que Twenty puede ver por sí mismo —una variable obligatoria que nadie completó— está cubierto por isRequired y no necesita código.
Se ejecuta en el lado del servidor, por lo que lee variables secretas como cualquier otra función lógica. Una comprobación del espacio de trabajo no tiene a nadie detrás, por lo que el controlador no necesita argumentos.
src/logic-functions/health-check.ts
OK no muestra ningún banner; todos los demás estados muestran el título en un banner coloreado según el estado, así que elige el que corresponda al grado de acción que deba tomar la persona. Los estados son los propios ApplicationHealthStatus de Twenty, por lo que la cadena de texto simple y el miembro de enumeración son intercambiables:
/ o #: una ubicación externa, relativa al protocolo o relativa pierde su botón en lugar de convertirse en una redirección a otro lugar. El botón también se elimina cuando la aplicación no informa de ninguna ubicación y no tiene una pestaña de configuración a la que recurrir, por lo que una comprobación en una aplicación sin variables ni elementos de menú de configuración muestra su título sin un botón inactivo.
Comprobación de la configuración propia de cada miembro
Una aplicación declara una función de comprobación de estado. OmiterunOnUserPreferences o establécelo en false para ejecutar una comprobación del espacio de trabajo en la página de configuración de la aplicación, con un controlador sin argumentos. Establece runOnUserPreferences: true para ejecutar en su lugar una comprobación de miembro en su página de preferencias de aplicaciones. Un controlador de miembro recibe el { userWorkspaceId: string } requerido de la sesión autenticada:
src/logic-functions/health-check.ts
{ userWorkspaceId } de la sesión autenticada, y las variables con ámbito de usuario conservan sus valores. El objeto de parámetros y el ID son obligatorios para este modo. No se ejecuta en la configuración de la aplicación del espacio de trabajo. Pasa userWorkspaceId a listConnections() para que devuelva solo las conexiones de ese miembro. Una conexión cuya renovación de token falla se excluye de la lista, por lo que “sin conexión” también cubre “reconectar”. Un botón sin location lleva a la pestaña General de la aplicación en esa página.
Las comprobaciones de miembro requieren Twenty 2.55.0 o una versión posterior. Las preferencias de aplicaciones aún no están habilitadas
en todos los espacios de trabajo: donde no lo están, una comprobación de miembro nunca se ejecuta.
Crear una actividad de línea de tiempo
UsecreateTimelineActivity() para publicar un evento explícito del dominio desde una función lógica. Primero defina el evento como un tipo de actividad de línea de tiempo y, a continuación, dirija el tipo y los objetos mediante sus identificadores universales estables:
timelineActivityTypeUniversalIdentifier, targetObjectUniversalIdentifier y targetRecordId. También puede proporcionar happensAt, properties y workspaceMemberId. happensAt controla la posición y la hora mostrada del evento en la línea de tiempo; de forma predeterminada, corresponde a la hora de creación.
Para asociar otro registro con el evento, proporcione linkedRecordId y linkedObjectMetadataUniversalIdentifier juntos. Además, puede proporcionar linkedRecordCachedName como alternativa histórica de visualización:
timelineActivity. Mantenga los tipos de eventos explícitos sin vincular a una action; un tipo vinculado a una acción ya recibe eventos de auditoría automáticos y, de lo contrario, produciría filas duplicadas.
Clientes de API tipados (twenty-client-sdk)
El paquetetwenty-client-sdk proporciona dos clientes GraphQL tipados para interactuar con la API de Twenty desde tus funciones de lógica y componentes de frontend.
CoreApiClient
Consultar y modificar datos del espacio de trabajo (registros, objetos)
CoreApiClient
Consultar y modificar datos del espacio de trabajo (registros, objetos)
CoreApiClient es el cliente principal para consultar y mutar datos del espacio de trabajo. Se genera a partir del esquema de tu espacio de trabajo con twenty app generate-client, o después de una sincronización con twenty app apply o twenty app dev, por lo que está completamente tipado para coincidir con tus objetos y campos.shareWith solo es relevante en un objeto cuyos registros son privados; en otros casos, el argumento se ignora. En dicho objeto, enumera quién obtiene acceso al registro creado: cada entrada se dirige exactamente a uno de workspaceMemberId, roleId o everyone: true con un accessLevel de READ, READ_WRITE o FULL. Un miembro del espacio de trabajo que crea un registro siempre recibe una concesión de propietario FULL, por lo que el argumento es opcional para él; una función lógica que actúa como su aplicación o una clave de API también recibe una concesión FULL para su rol, y quienes realizan dichas llamadas, al igual que una llamada del sistema, deben pasar shareWith o se rechaza la creación. Cada entrada debe indicar un miembro o un rol del espacio de trabajo. Una función lógica o clave de API comparte mediante su rol, por lo que cada titular de ese rol obtiene el mismo acceso a los registros que crea; asigne a una clave cuyos registros deban permanecer privados para ella un rol propio.El cliente usa una sintaxis de conjunto de selección: pasa true para incluir un campo, usa __args para los argumentos y anida objetos para las relaciones. Obtienes autocompletado completo y verificación de tipos basados en el esquema de tu espacio de trabajo.Ejecuta
twenty app generate-client para actualizar el cliente a partir del
esquema de GraphQL de tu espacio de trabajo. twenty app apply y twenty app dev también lo regeneran
después de la sincronización. twenty app build solo compila localmente y no genera
el cliente.Uso de CoreSchema para anotaciones de tipos
CoreSchema proporciona tipos de TypeScript que coinciden con los objetos de tu espacio de trabajo; útil para tipar el estado de componentes o parámetros de funciones:MetadataApiClient
Configuración del espacio de trabajo, aplicaciones y cargas de archivos
MetadataApiClient
Configuración del espacio de trabajo, aplicaciones y cargas de archivos
MetadataApiClient viene preconstruido con el SDK (no se requiere generación). Consulta el endpoint /metadata para la configuración del espacio de trabajo, las aplicaciones y las cargas de archivos. Acepta la misma opción runAs que CoreApiClient — consulta Qué acceso utiliza una llamada.También es la forma en que una aplicación lee y actualiza sus propias variables de aplicación, en una función lógica como en un componente frontal. Un token de aplicación solo llega a su propia aplicación, en su propio espacio de trabajo.Una variable de usuario se encuentra en process.env con el valor del miembro que inició la ejecución, o con su valor predeterminado hasta que establezca el suyo propio. Una ejecución que nadie inició no recibe variables de usuario. Para leer el valor de las variables de usuario de tu aplicación de cada miembro, por ejemplo en una tarea cron, consulta myUserApplicationVariables con runAs: 'application'.Subir archivos
ElMetadataApiClient incluye un método uploadFile para adjuntar archivos a los campos de tipo archivo. El archivo va directamente al almacenamiento de archivos de Twenty: la API emite un destino de carga, el cliente envía los bytes allí y luego la API confirma la carga.Puntos clave:
- Utiliza el
universalIdentifierdel campo (no su ID específico del espacio de trabajo), por lo que tu código de carga funciona en cualquier espacio de trabajo donde esté instalada tu aplicación. - El tipo MIME se detecta a partir del contenido del archivo una vez cargado, por lo que no hay nada que declarar.
- La
urldevuelta es una URL firmada que puedes usar para acceder al archivo cargado.
Cuando tu código se ejecuta en Twenty (funciones de lógica o componentes de frontend), la plataforma inyecta credenciales como variables de entorno:
TWENTY_API_URL— URL base de la API de TwentyTWENTY_APP_ACCESS_TOKEN— Clave de corta duración para el acceso predeterminado: el rol de una persona se intersecta con el de tu aplicación cuando hay alguien detrás de la ejecución; el rol propio de tu aplicación cuando no hay nadie. La persona es quien haya desencadenado la ejecución en una función de lógica, o quien esté viendo la página en un componente de frontend.TWENTY_APP_APPLICATION_ACCESS_TOKEN— Clave de corta duración con alcance únicamente al rol propio de tu aplicación. Solo funciones de lógica, siempre se inyecta allí, y es lo que utilizarunAs: 'application'.
process.env automáticamente, y Qué acceso utiliza una llamada explica cómo elegir entre ellas. Los permisos propios de tu aplicación están determinados por el rol declarado con defineApplicationRole() (o referenciado mediante defaultRoleUniversalIdentifier en application-config.ts); una ejecución que actúa como una persona nunca puede superar ese rol ni el suyo.