Přejít na hlavní obsah
Aplikace jsou aktuálně v alfa testování. Tato funkce je funkční, ale stále se vyvíjí.

Co jsou aplikace?

Aplikace vám umožňují vytvářet a spravovat přizpůsobení Twenty jako kód. Místo konfigurace všeho přes uživatelské rozhraní definujete v kódu svůj datový model a logické funkce — což zrychluje vývoj, údržbu i nasazování do více pracovních prostorů. Co můžete dělat už dnes:
  • Definujte vlastní objekty a pole jako kód (spravovaný datový model)
  • Vytvářejte logické funkce s vlastními spouštěči
  • Definujte dovednosti agentů AI
  • Nasazujte stejnou aplikaci do více pracovních prostorů

Předpoklady

Začínáme

Vytvořte novou aplikaci pomocí oficiálního scaffolderu, poté se ověřte a začněte vyvíjet:
# Vygenerujte kostru nové aplikace (ve výchozím nastavení zahrnuje všechny příklady)
npx create-twenty-app@latest my-twenty-app
cd my-twenty-app

# Pokud nepoužíváte yarn@4
corepack enable
yarn install

# Přihlaste se pomocí svého API klíče (budete vyzváni)
yarn twenty auth:login

# Spusťte vývojový režim: automaticky synchronizuje místní změny s vaším pracovním prostorem
yarn twenty app:dev
Nástroj pro generování kostry podporuje tři režimy pro řízení toho, které ukázkové soubory jsou zahrnuty:
# Výchozí (úplný): všechny příklady (objekt, pole, logická funkce, front-endová komponenta, zobrazení, položka navigační nabídky, dovednost)
npx create-twenty-app@latest my-app

# Minimální: pouze základní soubory (application-config.ts a default-role.ts)
npx create-twenty-app@latest my-app --minimal

# Interaktivní: vyberte, které příklady zahrnout
npx create-twenty-app@latest my-app --interactive
Odtud můžete:
# Přidejte do vaší aplikace novou entitu (s průvodcem)
yarn twenty entity:add

# Sledujte logy funkcí vaší aplikace
yarn twenty function:logs

# Spusťte funkci podle názvu
yarn twenty function:execute -n my-function -p '{"name": "test"}'

# Spusťte postinstalační funkci
yarn twenty function:execute --postInstall

# Odinstalujte aplikaci z aktuálního pracovního prostoru
yarn twenty app:uninstall

# Zobrazte nápovědu k příkazům
yarn twenty help
Viz také: referenční stránky CLI pro create-twenty-app a twenty-sdk CLI.

Struktura projektu (vytvořená scaffolderem)

Když spustíte npx create-twenty-app@latest my-twenty-app, scaffolder:
  • Zkopíruje minimální základní aplikaci do my-twenty-app/
  • Přidá lokální závislost twenty-sdk a konfiguraci pro Yarn 4
  • Vytvoří konfigurační soubory a skripty napojené na twenty CLI
  • Vygeneruje základní soubory (konfigurace aplikace, výchozí role funkcí, postinstalační funkce) a k nim ukázkové soubory podle zvoleného režimu generování kostry
Čerstvě vygenerovaná aplikace s výchozím režimem --exhaustive vypadá takto:
my-twenty-app/
  package.json
  yarn.lock
  .gitignore
  .nvmrc
  .yarnrc.yml
  .yarn/
    install-state.gz
  eslint.config.mjs
  tsconfig.json
  README.md
  public/                           # Složka s veřejnými prostředky (obrázky, písma apod.)
  src/
  ├── application-config.ts           # Povinné – hlavní konfigurace aplikace
  ├── roles/
  │   └── default-role.ts               # Výchozí role pro logické funkce
  ├── objects/
  │   └── example-object.ts             # Ukázková definice vlastního objektu
  ├── fields/
  │   └── example-field.ts              # Ukázková samostatná definice pole
  ├── logic-functions/
  │   ├── hello-world.ts                # Ukázková logická funkce
  │   └── post-install.ts               # Postinstalační logická funkce
  ├── front-components/
  │   └── hello-world.tsx               # Ukázková front-endová komponenta
  ├── views/
  │   └── example-view.ts                # Ukázková definice uloženého zobrazení
  ├── navigation-menu-items/
  │   └── example-navigation-menu-item.ts # Ukázkový odkaz postranní navigace
  └── skills/
      └── example-skill.ts                # Ukázková definice dovednosti agenta AI
S volbou --minimal se vytvoří pouze základní soubory (application-config.ts, roles/default-role.ts a logic-functions/post-install.ts). S volbou --interactive si vyberete, které ukázkové soubory chcete zahrnout. V kostce:
  • package.json: Deklaruje název aplikace, verzi, engines (Node 24+, Yarn 4) a přidává twenty-sdk plus skript twenty, který deleguje na lokální twenty CLI. Spusťte yarn twenty help pro výpis všech dostupných příkazů.
  • .gitignore: Ignoruje běžné artefakty jako node_modules, .yarn, generated/ (typovaný klient), dist/, build/, složky s coverage, logy a soubory .env*.
  • yarn.lock, .yarnrc.yml, .yarn/: Zamykají a konfigurují nástrojový řetězec Yarn 4 používaný projektem.
  • .nvmrc: Fixuje verzi Node.js požadovanou projektem.
  • eslint.config.mjs a tsconfig.json: Poskytují lintování a konfiguraci TypeScriptu pro zdrojové soubory vaší aplikace v TypeScriptu.
  • README.md: Krátké README v kořeni aplikace se základními pokyny.
  • public/: Složka pro ukládání veřejných prostředků (obrázky, písma, statické soubory), které bude vaše aplikace poskytovat. Soubory umístěné zde se během synchronizace nahrají a jsou za běhu dostupné.
  • src/: Hlavní místo, kde definujete svou aplikaci jako kód

Detekce entit

SDK detekuje entity analýzou vašich souborů TypeScript a hledá volání export default define<Entity>({...}). Každý typ entity má odpovídající pomocnou funkci exportovanou z twenty-sdk:
Pomocná funkceTyp entity
defineObject()Definice vlastních objektů
defineLogicFunction()Definice logických funkcí
defineFrontComponent()Definice frontendových komponent
defineRole()Definice rolí
defineField()Rozšíření polí u existujících objektů
defineView()Definice uložených zobrazení
defineNavigationMenuItem()Definice položek navigační nabídky
defineSkill()Definice dovedností agenta AI
Pojmenování souborů je flexibilní. Detekce entit je založená na AST — SDK prochází vaše zdrojové soubory a hledá vzor export default define<Entity>({...}). Soubory a složky můžete organizovat, jak chcete. Seskupování podle typu entity (např. logic-functions/, roles/) je pouze konvence pro organizaci kódu, nikoli požadavek.
Příklad detekované entity:
// This file can be named anything and placed anywhere in src/
import { defineObject, FieldType } from 'twenty-sdk';

export default defineObject({
  universalIdentifier: '...',
  nameSingular: 'postCard',
  // ... rest of config
});
Pozdější příkazy přidají další soubory a složky:
  • yarn twenty app:dev automaticky vygeneruje typovaného klienta API v node_modules/twenty-sdk/generated (typovaný klient Twenty + typy pracovního prostoru).
  • yarn twenty entity:add přidá soubory s definicemi entit do src/ pro vaše vlastní objekty, funkce, frontové komponenty, role, dovednosti a další.

Ověření

Při prvním spuštění yarn twenty auth:login budete vyzváni k zadání:
  • URL API (výchozí je http://localhost:3000 nebo váš aktuální profil pracovního prostoru)
  • Klíč API
Vaše přihlašovací údaje se ukládají pro jednotlivé uživatele do ~/.twenty/config.json. Můžete spravovat více profilů a přepínat mezi nimi.

Správa pracovních prostorů

# Login interactively (recommended)
yarn twenty auth:login

# Login to a specific workspace profile
yarn twenty auth:login --workspace my-custom-workspace

# List all configured workspaces
yarn twenty auth:list

# Switch the default workspace (interactive)
yarn twenty auth:switch

# Switch to a specific workspace
yarn twenty auth:switch production

# Check current authentication status
yarn twenty auth:status
Jakmile přepnete pracovní prostor pomocí yarn twenty auth:switch, všechny následující příkazy budou tento pracovní prostor používat jako výchozí. Můžete jej stále dočasně přepsat pomocí --workspace <name>.

Používejte zdroje SDK (typy a konfiguraci)

twenty-sdk poskytuje typované stavební bloky a pomocné funkce, které používáte ve své aplikaci. Níže jsou klíčové části, se kterými budete nejčastěji pracovat.

Pomocné funkce

SDK poskytuje pomocné funkce pro definování entit vaší aplikace. Jak je popsáno v Detekce entit, musíte použít export default define<Entity>({...}), aby byly vaše entity detekovány:
FunkceÚčel
defineApplication()Nakonfigurujte metadata aplikace (povinné, jedno na aplikaci)
defineObject()Definice vlastních objektů s poli
defineLogicFunction()Definice logických funkcí s obslužnými funkcemi
defineFrontComponent()Definujte frontendové komponenty pro vlastní uživatelské rozhraní
defineRole()Konfigurace oprávnění rolí a přístupu k objektům
defineField()Rozšiřte existující objekty o další pole
defineView()Definujte uložená zobrazení pro objekty
defineNavigationMenuItem()Definujte odkazy postranní navigace
defineSkill()Definuje dovednosti agenta AI
Tyto funkce validují vaši konfiguraci v době sestavení a poskytují automatické doplňování v IDE a typovou bezpečnost.

Definování objektů

Vlastní objekty popisují jak schéma, tak chování záznamů ve vašem pracovním prostoru. K definování objektů s vestavěnou validací použijte defineObject():
// src/app/postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';

enum PostCardStatus {
  DRAFT = 'DRAFT',
  SENT = 'SENT',
  DELIVERED = 'DELIVERED',
  RETURNED = 'RETURNED',
}

export default defineObject({
  universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
  nameSingular: 'postCard',
  namePlural: 'postCards',
  labelSingular: 'Post Card',
  labelPlural: 'Post Cards',
  description: 'A post card object',
  icon: 'IconMail',
  fields: [
    {
      universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
      name: 'content',
      type: FieldType.TEXT,
      label: 'Content',
      description: "Postcard's content",
      icon: 'IconAbc',
    },
    {
      universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
      name: 'recipientName',
      type: FieldType.FULL_NAME,
      label: 'Recipient name',
      icon: 'IconUser',
    },
    {
      universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
      name: 'recipientAddress',
      type: FieldType.ADDRESS,
      label: 'Recipient address',
      icon: 'IconHome',
    },
    {
      universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
      name: 'status',
      type: FieldType.SELECT,
      label: 'Status',
      icon: 'IconSend',
      defaultValue: `'${PostCardStatus.DRAFT}'`,
      options: [
        { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
        { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
        { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
        { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
      ],
    },
    {
      universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
      name: 'deliveredAt',
      type: FieldType.DATE_TIME,
      label: 'Delivered at',
      icon: 'IconCheck',
      isNullable: true,
      defaultValue: null,
    },
  ],
});
Hlavní body:
  • Použijte defineObject() pro vestavěnou validaci a lepší podporu v IDE.
  • Hodnota universalIdentifier musí být jedinečná a stabilní napříč nasazeními.
  • Každé pole vyžaduje name, type, label a svůj vlastní stabilní universalIdentifier.
  • Pole fields je volitelné — objekty můžete definovat i bez vlastních polí.
  • Nové objekty můžete vygenerovat pomocí yarn twenty entity:add, který vás provede pojmenováním, poli a vztahy.
Základní pole jsou vytvořena automaticky. Když definujete vlastní objekt, Twenty automaticky přidá standardní pole jako id, name, createdAt, updatedAt, createdBy, updatedBy a deletedAt. Nemusíte je definovat v poli fields — přidejte pouze svá vlastní pole. Výchozí pole můžete přepsat definováním pole se stejným názvem v poli fields, ale to se nedoporučuje.

Konfigurace aplikace (application-config.ts)

Každá aplikace má jeden soubor application-config.ts, který popisuje:
  • Identitu aplikace: identifikátory, zobrazovaný název a popis.
  • Jak běží její funkce: kterou roli používají pro oprávnění.
  • (Volitelné) proměnné: dvojice klíč–hodnota zpřístupněné vašim funkcím jako proměnné prostředí.
  • (Volitelná) postinstalační funkce: logická funkce, která se spouští po instalaci aplikace.
Use defineApplication() to define your application configuration:
// src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
import { POST_INSTALL_UNIVERSAL_IDENTIFIER } from 'src/logic-functions/post-install';

export default defineApplication({
  universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
  displayName: 'My Twenty App',
  description: 'My first Twenty app',
  icon: 'IconWorld',
  applicationVariables: {
    DEFAULT_RECIPIENT_NAME: {
      universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
      description: 'Default recipient name for postcards',
      value: 'Jane Doe',
      isSecret: false,
    },
  },
  defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
  postInstallLogicFunctionUniversalIdentifier: POST_INSTALL_UNIVERSAL_IDENTIFIER,
});
Poznámky:
  • Pole universalIdentifier jsou deterministická ID, která vlastníte; vygenerujte je jednou a udržujte je stabilní napříč synchronizacemi.
  • applicationVariables se stanou proměnnými prostředí pro vaše funkce (například DEFAULT_RECIPIENT_NAME je dostupné jako process.env.DEFAULT_RECIPIENT_NAME).
  • defaultRoleUniversalIdentifier se musí shodovat se souborem role (viz níže).
  • postInstallLogicFunctionUniversalIdentifier (volitelné) odkazuje na logickou funkci, která se automaticky spustí po instalaci aplikace. Viz Postinstalační funkce.

Role a oprávnění

Aplikace mohou definovat role, které zapouzdřují oprávnění k objektům a akcím ve vašem pracovním prostoru. Pole defaultRoleUniversalIdentifier v application-config.ts určuje výchozí roli používanou logickými funkcemi vaší aplikace.
  • Běhový klíč API vložený jako TWENTY_API_KEY je odvozen z této výchozí role funkcí.
  • Typovaný klient bude omezen oprávněními udělenými této roli.
  • Dodržujte princip nejmenších oprávnění: vytvořte vyhrazenou roli pouze s oprávněními, která vaše funkce potřebují, a poté odkazujte na její univerzální identifikátor.
Výchozí role funkce (*.role.ts)
Když vygenerujete novou aplikaci, CLI také vytvoří výchozí soubor role. K definování rolí s vestavěnou validací použijte defineRole():
// src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';

export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
  'b648f87b-1d26-4961-b974-0908fd991061';

export default defineRole({
  universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
  label: 'Default function role',
  description: 'Default role for function Twenty client',
  canReadAllObjectRecords: false,
  canUpdateAllObjectRecords: false,
  canSoftDeleteAllObjectRecords: false,
  canDestroyAllObjectRecords: false,
  canUpdateAllSettings: false,
  canBeAssignedToAgents: false,
  canBeAssignedToUsers: false,
  canBeAssignedToApiKeys: false,
  objectPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      canReadObjectRecords: true,
      canUpdateObjectRecords: true,
      canSoftDeleteObjectRecords: false,
      canDestroyObjectRecords: false,
    },
  ],
  fieldPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff',
      canReadFieldValue: false,
      canUpdateFieldValue: false,
    },
  ],
  permissionFlags: [PermissionFlag.APPLICATIONS],
});
Na universalIdentifier této role se poté odkazuje v application-config.ts jako na defaultRoleUniversalIdentifier. Jinými slovy:
  • *.role.ts definuje, co může výchozí role funkce dělat.
  • application-config.ts ukazuje na tuto roli, aby vaše funkce zdědily její oprávnění.
Poznámky:
  • Začněte rolí vytvořenou scaffolderem a postupně ji omezujte podle principu nejmenších oprávnění.
  • Nahraďte objectPermissions a fieldPermissions objekty/poli, která vaše funkce potřebují.
  • permissionFlags řídí přístup k schopnostem na úrovni platformy. Držte je na minimu; přidávejte pouze to, co potřebujete.
  • Podívejte se na funkční příklad v aplikaci Hello World: packages/twenty-apps/hello-world/src/roles/function-role.ts.

Konfigurace logických funkcí a vstupní bod

Každý soubor funkce používá defineLogicFunction() k exportu konfigurace s obslužnou funkcí (handlerem) a volitelnými spouštěči.
// src/app/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '~/generated';

const handler = async (params: RoutePayload) => {
  const client = new Twenty(); // generated typed client
  const name = 'name' in params.queryStringParameters
    ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
    : 'Hello world';

  const result = await client.mutation({
    createPostCard: {
      __args: { data: { name } },
      id: true,
      name: true,
    },
  });
  return result;
};

export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'create-new-post-card',
  timeoutSeconds: 2,
  handler,
  triggers: [
    // Public HTTP route trigger '/s/post-card/create'
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/post-card/create',
      httpMethod: 'GET',
      isAuthRequired: false,
    },
    // Cron trigger (CRON pattern)
    // {
    //   universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
    //   type: 'cron',
    //   pattern: '0 0 1 1 *',
    // },
    // Database event trigger
    // {
    //   universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
    //   type: 'databaseEvent',
    //   eventName: 'person.updated',
    //   updatedFields: ['name'],
    // },
  ],
});
Běžné typy spouštěčů:
  • route: Zpřístupní vaši funkci na HTTP cestě a metodě pod koncovým bodem /s/:
např. path: '/post-card/create', -> volání na <APP_URL>/s/post-card/create
  • cron: Spouští vaši funkci podle plánu pomocí výrazu CRON.
  • databaseEvent: Spouští se při událostech životního cyklu objektů v pracovním prostoru. Když je operace události updated, lze konkrétní sledovaná pole určit v poli updatedFields. Pokud zůstane nedefinované nebo prázdné, spustí funkci jakákoli aktualizace.
např. person.updated
Poznámky:
  • Pole triggers je volitelné. Funkce bez spouštěčů lze použít jako pomocné funkce volané jinými funkcemi.
  • V jedné funkci můžete kombinovat více typů spouštěčů.

Postinstalační funkce

Postinstalační funkce je logická funkce, která se automaticky spouští po instalaci vaší aplikace do pracovního prostoru. To je užitečné pro jednorázové úlohy nastavení, jako je naplnění výchozími daty, vytvoření počátečních záznamů nebo konfigurace nastavení pracovního prostoru. Když vygenerujete kostru nové aplikace pomocí create-twenty-app, vytvoří se pro vás postinstalační funkce v src/logic-functions/post-install.ts:
// src/logic-functions/post-install.ts
import { defineLogicFunction } from 'twenty-sdk';

export const POST_INSTALL_UNIVERSAL_IDENTIFIER = '<generated-uuid>';

const handler = async (): Promise<void> => {
  console.log('Post install logic function executed successfully!');
};

export default defineLogicFunction({
  universalIdentifier: POST_INSTALL_UNIVERSAL_IDENTIFIER,
  name: 'post-install',
  description: 'Runs after installation to set up the application.',
  timeoutSeconds: 300,
  handler,
});
Funkce je připojena do vaší aplikace odkazem na její univerzální identifikátor v application-config.ts:
import { POST_INSTALL_UNIVERSAL_IDENTIFIER } from 'src/logic-functions/post-install';

export default defineApplication({
  // ...
  postInstallLogicFunctionUniversalIdentifier: POST_INSTALL_UNIVERSAL_IDENTIFIER,
});
Postinstalační funkci můžete také kdykoli spustit ručně pomocí CLI:
yarn twenty function:execute --postInstall
Hlavní body:
  • Postinstalační funkce jsou standardní logické funkce — používají defineLogicFunction() stejně jako jakákoli jiná funkce.
  • Pole postInstallLogicFunctionUniversalIdentifier v defineApplication() je volitelné. Pokud je vynecháno, po instalaci se nespustí žádná funkce.
  • Výchozí časový limit je nastaven na 300 sekund (5 minut), aby umožnil delší úlohy nastavení, jako je naplnění daty.
  • Postinstalační funkce nepotřebují spouštěče — jsou spouštěny platformou během instalace nebo ručně pomocí function:execute --postInstall.

Payload spouštěče trasy

Zpětně nekompatibilní změna (v1.16, leden 2026): Formát payloadu spouštěče trasy se změnil. Před verzí v1.16 byly parametry dotazu, parametry cesty a tělo odesílány přímo jako payload. Od verze v1.16 jsou zanořeny uvnitř strukturovaného objektu RoutePayload.Před v1.16:
const handler = async (params) => {
  const { param1, param2 } = params; // Direct access
};
Po v1.16:
const handler = async (event: RoutePayload) => {
  const { param1, param2 } = event.body; // Access via .body
  const { queryParam } = event.queryStringParameters;
  const { id } = event.pathParameters;
};
Jak migrovat existující funkce: Aktualizujte svůj handler tak, aby destrukturoval z event.body, event.queryStringParameters nebo event.pathParameters místo přímo z objektu params.
Když spouštěč trasy vyvolá vaši logickou funkci, ta obdrží objekt RoutePayload, který odpovídá formátu AWS HTTP API v2. Importujte typ z twenty-sdk:
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';

const handler = async (event: RoutePayload) => {
  // Access request data
  const { headers, queryStringParameters, pathParameters, body } = event;

  // HTTP method and path are available in requestContext
  const { method, path } = event.requestContext.http;

  return { message: 'Success' };
};
Typ RoutePayload má následující strukturu:
VlastnostTypPopis
headersRecord<string, string | undefined>Záhlaví HTTP (pouze ta uvedená v forwardedRequestHeaders)
queryStringParametersRecord<string, string | undefined>Parametry query stringu (více hodnot spojených čárkami)
pathParametersRecord<string, string | undefined>Parametry cesty extrahované ze vzoru trasy (např. /users/:id{ id: '123' })
text zprávyobject | nullParsované tělo požadavku (JSON)
isBase64Encodedbooleovská hodnotaZda je tělo kódováno base64
requestContext.http.methodstringMetoda HTTP (GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstringNezpracovaná cesta požadavku

Přeposílání záhlaví HTTP

Ve výchozím nastavení se záhlaví HTTP z příchozích požadavků z bezpečnostních důvodů do vaší logické funkce ne předávají. Chcete-li zpřístupnit konkrétní záhlaví, výslovně je uveďte v poli forwardedRequestHeaders:
export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'webhook-handler',
  handler,
  triggers: [
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/webhook',
      httpMethod: 'POST',
      isAuthRequired: false,
      forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
    },
  ],
});
Ve vašem handleru k nim poté můžete přistupovat:
const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-webhook-signature'];
  const contentType = event.headers['content-type'];

  // Validate webhook signature...
  return { received: true };
};
Názvy záhlaví jsou normalizovány na malá písmena. Přistupujte k nim pomocí klíčů s malými písmeny (například event.headers['content-type']).
Nové funkce můžete vytvářet dvěma způsoby:
  • Vygenerované: Spusťte yarn twenty entity:add a zvolte možnost přidat novou logickou funkci. Tím se vygeneruje startovací soubor s obslužnou funkcí a konfigurací.
  • Ruční: Vytvořte nový soubor *.logic-function.ts a použijte defineLogicFunction() podle stejného vzoru.

Označení logické funkce jako nástroje

Logické funkce lze zpřístupnit jako nástroje pro agenty AI a pracovní postupy. Když je funkce označena jako nástroj, stane se dohledatelnou funkcemi AI produktu Twenty a lze ji vybrat jako krok v automatizacích pracovních postupů. Chcete-li označit logickou funkci jako nástroj, nastavte isTool: true a poskytněte toolInputSchema popisující očekávané vstupní parametry pomocí JSON Schema:
// src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import Twenty from '~/generated';

const handler = async (params: { companyName: string; domain?: string }) => {
  const client = new Twenty();

  const result = await client.mutation({
    createTask: {
      __args: {
        data: {
          title: `Enrich data for ${params.companyName}`,
          body: `Domain: ${params.domain ?? 'unknown'}`,
        },
      },
      id: true,
    },
  });

  return { taskId: result.createTask.id };
};

export default defineLogicFunction({
  universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
  name: 'enrich-company',
  description: 'Enrich a company record with external data',
  timeoutSeconds: 10,
  handler,
  isTool: true,
  toolInputSchema: {
    type: 'object',
    properties: {
      companyName: {
        type: 'string',
        description: 'The name of the company to enrich',
      },
      domain: {
        type: 'string',
        description: 'The company website domain (optional)',
      },
    },
    required: ['companyName'],
  },
});
Hlavní body:
  • isTool (boolean, výchozí: false): Když je nastaveno na true, funkce je zaregistrována jako nástroj a zpřístupní se agentům AI a automatizacím pracovních postupů.
  • toolInputSchema (object, volitelné): Objekt JSON Schema, který popisuje parametry, jež vaše funkce přijímá. Agenti AI používají toto schéma k pochopení toho, jaké vstupy nástroj očekává, a k ověřování volání. Pokud je vynecháno, schéma má výchozí podobu { type: 'object', properties: {} } (žádné parametry).
  • Funkce s isTool: false (nebo není nastaveno) nejsou zpřístupněny jako nástroje. Stále je lze spouštět přímo nebo volat z jiných funkcí, ale neobjeví se ve vyhledávání nástrojů.
  • Pojmenování nástrojů: Když je funkce zpřístupněna jako nástroj, její název se automaticky normalizuje na logic_function_<name> (převedeno na malá písmena, nealfanumerické znaky jsou nahrazeny podtržítky). Například enrich-company se změní na logic_function_enrich_company.
  • Můžete kombinovat isTool se spouštěči — funkce může být zároveň nástrojem (volatelným agenty AI) i spouštěna událostmi (cron, databázové události, routes).
Napište kvalitní description. Agenti AI se spoléhají na pole funkce description při rozhodování, kdy nástroj použít. Buďte konkrétní ohledně toho, co nástroj dělá a kdy se má volat.

Frontendové komponenty

Frontendové komponenty vám umožňují vytvářet vlastní React komponenty, které se vykreslují v rozhraní Twenty. K definování komponent s vestavěnou validací použijte defineFrontComponent():
// src/my-widget.front-component.tsx
import { defineFrontComponent } from 'twenty-sdk';

const MyWidget = () => {
  return (
    <div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
      <h1>My Custom Widget</h1>
      <p>This is a custom front component for Twenty.</p>
    </div>
  );
};

export default defineFrontComponent({
  universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  name: 'my-widget',
  description: 'A custom widget component',
  component: MyWidget,
});
Hlavní body:
  • Frontendové komponenty jsou React komponenty, které se vykreslují v izolovaných kontextech v rámci Twenty.
  • Pro automatickou detekci použijte příponu souboru *.front-component.tsx.
  • Pole component odkazuje na vaši React komponentu.
  • Komponenty se během yarn twenty app:dev automaticky sestaví a synchronizují.
Nové frontendové komponenty můžete vytvořit dvěma způsoby:
  • Vygenerované: Spusťte yarn twenty entity:add a zvolte možnost přidat novou frontendovou komponentu.
  • Ruční: Vytvořte nový soubor *.front-component.tsx a použijte defineFrontComponent().

Dovednosti

Dovednosti definují znovupoužitelné pokyny a schopnosti, které mohou agenti AI používat ve vašem pracovním prostoru. K definování dovedností s vestavěnou validací použijte defineSkill():
// src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';

export default defineSkill({
  universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  name: 'sales-outreach',
  label: 'Sales Outreach',
  description: 'Guides the AI agent through a structured sales outreach process',
  icon: 'IconBrain',
  content: `You are a sales outreach assistant. When reaching out to a prospect:
1. Research the company and recent news
2. Identify the prospect's role and likely pain points
3. Draft a personalized message referencing specific details
4. Keep the tone professional but conversational`,
});
Hlavní body:
  • name je jedinečný identifikátor dovednosti (doporučuje se kebab-case).
  • label je uživatelsky čitelný název zobrazovaný v UI.
  • content obsahuje pokyny dovednosti — je to text, který agent AI používá.
  • icon (volitelné) nastavuje ikonu zobrazovanou v UI.
  • description (volitelné) poskytuje doplňující kontext o účelu dovednosti.
Nové dovednosti můžete vytvářet dvěma způsoby:
  • Vygenerované: Spusťte yarn twenty entity:add a zvolte možnost přidat novou dovednost.
  • Ruční: Vytvořte nový soubor a použijte defineSkill() podle stejného vzoru.

Generovaný typovaný klient

Typovaný klient je automaticky generován pomocí yarn twenty app:dev a ukládá se do node_modules/twenty-sdk/generated podle schématu vašeho pracovního prostoru. Použijte jej ve svých funkcích:
import Twenty from '~/generated';

const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
Klient se automaticky znovu generuje pomocí yarn twenty app:dev kdykoli se změní vaše objekty nebo pole.

Běhové přihlašovací údaje v logických funkcích

Když vaše funkce běží na Twenty, platforma před spuštěním kódu vloží přihlašovací údaje jako proměnné prostředí:
  • TWENTY_API_URL: Základní URL Twenty API, na které vaše aplikace cílí.
  • TWENTY_API_KEY: Krátkodobý klíč s rozsahem omezeným na výchozí roli funkce vaší aplikace.
Poznámky:
  • Není nutné předávat URL ani klíč API vygenerovanému klientovi. Za běhu čte TWENTY_API_URL a TWENTY_API_KEY z process.env.
  • Oprávnění klíče API jsou určena rolí odkazovanou ve vašem application-config.ts prostřednictvím defaultRoleUniversalIdentifier. Toto je výchozí role používaná logickými funkcemi vaší aplikace.
  • Aplikace mohou definovat role podle principu nejmenších oprávnění. Udělte pouze oprávnění, která vaše funkce potřebují, a poté nastavte defaultRoleUniversalIdentifier na univerzální identifikátor této role.

Příklad Hello World

Prozkoumejte minimalistický end-to-end příklad, který demonstruje objekty, logické funkce, frontendové komponenty a více spouštěčů zde:

Ruční nastavení (bez scaffolderu)

Ačkoli pro nejlepší začátky doporučujeme použít create-twenty-app, projekt můžete nastavit i ručně. Neinstalujte CLI globálně. Místo toho přidejte twenty-sdk jako lokální závislost a přidejte jeden skript do souboru package.json:
yarn add -D twenty-sdk
Poté přidejte skript twenty:
{
  "scripts": {
    "twenty": "twenty"
  }
}
Nyní můžete spouštět všechny příkazy přes yarn twenty <command>, např. yarn twenty app:dev, yarn twenty help atd.

Řešení potíží

  • Chyby ověření: spusťte yarn twenty auth:login a ujistěte se, že váš klíč API má požadovaná oprávnění.
  • Nelze se připojit k serveru: ověřte URL API a že je server Twenty dosažitelný.
  • Types or client missing/outdated: restart yarn twenty app:dev — it auto-generates the typed client.
  • Režim vývoje se nesynchronizuje: ujistěte se, že běží yarn twenty app:dev a že vaše prostředí změny neignoruje.
Kanál podpory na Discordu: https://discord.com/channels/1130383047699738754/1130386664812982322