> ## Documentation Index
> Fetch the complete documentation index at: https://twenty-claude-cool-pascal-5ay683.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills & Agenten

> Definieren Sie KI-Skills und Agenten für Ihre App.

<Warning>
  Skills und Agenten befinden sich derzeit in der Alpha-Phase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter.
</Warning>

Apps können KI-Funktionen definieren, die im Arbeitsbereich verfügbar sind — wiederverwendbare Skill-Anweisungen und Agenten mit benutzerdefinierten System-Prompts.

<AccordionGroup>
  <Accordion title="defineSkill" description="Skills für KI-Agenten definieren">
    Skills definieren wiederverwendbare Anweisungen und Fähigkeiten, die KI-Agenten in Ihrem Arbeitsbereich verwenden können. Verwenden Sie `defineSkill()`, um Skills mit eingebauter Validierung zu definieren:

    ```ts src/skills/example-skill.ts theme={null}
    import { defineSkill } from 'twenty-sdk/define';

    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`,
    });
    ```

    Hauptpunkte:

    * `name` ist eine eindeutige Kennung (als Zeichenfolge) für den Skill (kebab-case empfohlen).
    * `label` ist der menschenlesbare Anzeigename, der in der UI angezeigt wird.
    * `content` enthält die Skill-Anweisungen — dies ist der Text, den der KI-Agent verwendet.
    * `icon` (optional) legt das in der UI angezeigte Symbol fest.
    * `description` (optional) liefert zusätzlichen Kontext zum Zweck des Skills.
  </Accordion>

  <Accordion title="defineAgent" description="KI-Agenten mit benutzerdefinierten Prompts definieren">
    Agenten sind KI-Assistenten, die innerhalb Ihres Arbeitsbereichs leben. Verwenden Sie `defineAgent()`, um Agenten mit einem benutzerdefinierten System-Prompt zu erstellen:

    ```ts src/agents/example-agent.ts theme={null}
    import { defineAgent } from 'twenty-sdk/define';

    export default defineAgent({
      universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
      name: 'sales-assistant',
      label: 'Sales Assistant',
      description: 'Helps the sales team draft outreach emails and research prospects',
      icon: 'IconRobot',
      prompt: 'You are a helpful sales assistant. Help users with their questions and tasks.',
    });
    ```

    Hauptpunkte:

    * `name` ist eine eindeutige Kennung (als Zeichenfolge) für den Agenten (kebab-case empfohlen).
    * `label` ist der in der UI angezeigte Anzeigename.
    * `prompt` ist der System-Prompt, der das Verhalten des Agenten definiert.
    * `description` (optional) liefert Kontext dazu, was der Agent tut.
    * `icon` (optional) legt das in der UI angezeigte Symbol fest.
    * `modelId` (optional) überschreibt das vom Agenten verwendete Standard-KI-Modell.
    * `responseFormat` (optional) steuert die Form der Ausgabe des Agenten. Standardmäßig ist `{ type: 'text' }` für Freitext. Verwenden Sie `{ type: 'json', schema }`, um eine strukturierte JSON-Ausgabe zu erzwingen.

    Standardmäßig gibt ein Agent freien Text zurück. Um eine strukturierte Ausgabe zu erhalten, setzen Sie `responseFormat` auf `{ type: 'json' }` und geben Sie ein `schema` an:

    ```ts src/agents/structured-agent.ts theme={null}
    import { defineAgent } from 'twenty-sdk/define';

    export default defineAgent({
      universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345',
      name: 'lead-scorer',
      label: 'Lead Scorer',
      prompt: 'Score the lead and explain your reasoning.',
      responseFormat: {
        type: 'json',
        schema: {
          type: 'object',
          properties: {
            score: { type: 'number', description: 'Lead score from 0 to 100' },
            summary: { type: 'string', description: 'Short reasoning for the score' },
          },
          required: ['score', 'summary'],
          additionalProperties: false,
        },
      },
    });
    ```

    Schema-Hinweise:

    * Das Schema ist ein flaches Objekt: Der `type` jeder Eigenschaft muss ein primitiver Typ sein (`string`, `number` oder `boolean`). Verschachtelte Objekte und Arrays werden nicht unterstützt.
    * `description` (optional) an jeder Eigenschaft leitet das Modell an, was dort eingetragen werden soll.
    * `required` (optional) listet die Eigenschaften auf, die das Modell immer zurückgeben muss.
    * `additionalProperties: false` (optional) verbietet alle Eigenschaften, die nicht in `properties` deklariert sind.
  </Accordion>

  <Accordion title="runAgent" description="Einen Agenten aus einer Logikfunktion ausführen">
    `runAgent()` ermöglicht es einer Logikfunktion, einen der Agenten Ihrer App auszuführen (mit seinen Fähigkeiten und Tools). Identifizieren Sie den Agenten über den `universalIdentifier`, den Sie an `defineAgent()` übergeben haben. Übergeben Sie entweder einen `prompt`-String oder einen `messages`-Konversationsverlauf – nicht beides:

    ```ts src/logic-functions/run-enricher.ts theme={null}
    import { runAgent } from 'twenty-sdk/logic-function';

    const { result, error, success } = await runAgent({
      agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
      prompt: 'Enrich House Ad <recordId>: fill empty fields from its listing URL.',
    });
    ```

    Für Multi-Turn-Bots (Slack, Discord, Teams, …) übergeben Sie den Thread-Verlauf als `messages` anstelle eines einzelnen `prompt`:

    ```ts src/logic-functions/reply-in-thread.ts theme={null}
    import { runAgent } from 'twenty-sdk/logic-function';

    const { result, error, success } = await runAgent({
      agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
      messages: [
        { role: 'user', content: 'Who owns Acme?' },
        { role: 'assistant', content: 'Sarah owns the Acme account.' },
        { role: 'user', content: 'What was the last touchpoint?' },
      ],
    });
    ```

    Hauptpunkte:

    * Geben Sie **genau eines** von `prompt` (string) oder `messages` (1 bis 100 Einträge
      von `{ role: 'user' | 'assistant', content: string }`) an.
    * Der Agent wird **synchron** ausgeführt und kann selbst Datensätze über seine eigenen Tools lesen/aktualisieren — `runAgent()` wird aufgelöst, sobald die Ausführung abgeschlossen ist.
    * Eine App kann nur ihre eigenen Agenten ausführen.
    * Die [Standardrolle](/l/de/developers/extend/apps/config/roles) der App muss das Berechtigungsflag `AI` gewähren — fügen Sie `SystemPermissionFlag.AI` zu ihren `permissionFlagUniversalIdentifiers` hinzu (oder setzen Sie `canAccessAllTools: true`).
      Ohne dieses Flag schlägt `runAgent()` mit einem Berechtigungsfehler fehl.
    * Setzen Sie ein großzügiges `timeoutSeconds` für die Logikfunktion — Agentenläufe können mehrere Sekunden dauern.
    * `success` ist `true` und `result` ist nicht null, wenn der Lauf abgeschlossen ist; bei einem Fehler ist `success` `false`, `result` ist `null` und `error` enthält den Grund (zum Beispiel, wenn dem Workspace während des Laufs die AI-Credits ausgehen).

    ```ts src/roles/default-role.ts theme={null}
    import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define';

    export default defineApplicationRole({
      universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061',
      label: 'Default function role',
      // runAgent() requires the AI permission flag on the app's default role.
      permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI],
    });
    ```

    <Warning>
      **Vermeiden Sie Schleifen:** Wenn Sie `runAgent()` von einem `*.updated`-Datenbankereignis-Trigger aus aufrufen und der Agent denselben Datensatz aktualisiert, schränken Sie den Trigger mit `updatedFields` auf ein Feld ein, das der Agent niemals beschreibt (z. B. die Quell-URL), oder prüfen Sie, ob eines der Zielfelder noch leer ist, bevor Sie `runAgent()` aufrufen.
    </Warning>

    ### Ausführung im Namen eines Arbeitsbereichsmitglieds

    Übergeben Sie `runAsWorkspaceMemberId`, wenn die Ausführung von einer Person ausgelöst wird – zum Beispiel von einem Chatbot, der auf eine Nachricht antwortet –, damit der Agent als dieses Mitglied und nicht als die App agiert:

    ```ts src/logic-functions/answer-question.ts theme={null}
    const { result } = await runAgent({
      agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
      prompt: 'How many open opportunities do we have?',
      runAsWorkspaceMemberId: '20202020-0687-4c41-b707-ed1bfca972a7',
    });
    ```

    Der Durchlauf agiert dann mit der **eigenen Rolle des Mitglieds**: Er kann alles tun, was dieses Mitglied tun kann, und nichts darüber hinaus; von ihm erstellte Datensätze werden diesem Mitglied zugeschrieben, und die zeilenbasierten Berechtigungen des Mitglieds gelten. Die Rolle des Agenten nimmt daran nicht teil – sie ist der Standard der App für Durchläufe, hinter denen keine Person steht. Lassen Sie das Feld bei autonomen Ausführungen weg (geplante Jobs, Datenbankereignis-Trigger): Diese behalten die eigene Rolle des Agenten bei. Die ausführende Anwendung bleibt aus Gründen der Herkunftssicherung mit dem Kontext des Durchlaufs verknüpft, ohne die Berechtigungen des Mitglieds einzuengen.

    Ihre App ist dafür verantwortlich, die Person, die die Ausführung ausgelöst hat, einem Arbeitsbereichsmitglied zuzuordnen. Das Benennen eines Mitglieds erfordert ein App-Zugriffstoken, und was ein Token benennen darf, hängt davon ab, ob ihm ein Benutzer zugeordnet ist:

    * Ein Token **ohne angehängten Benutzer** kann jedes Mitglied benennen. Eine Logikfunktion läuft
      mit einem solchen, und ebenso gilt dies für Token, die über `client_credentials` oder aus einem API-
      Schlüssel ausgestellt werden.
    * Ein Token, das **im Namen eines Benutzers** ausgestellt wird, wie es eine Frontkomponente erhält, darf
      nur das eigene Mitglied dieses Benutzers benennen.

    Alles andere — eine einfache Benutzersitzung, ein API-Schlüssel ohne App-Token — darf
    überhaupt kein Mitglied benennen.

    <Warning>
      `runAgent()` löst eine Ausnahme aus, wenn das Arbeitsbereichsmitglied nicht aufgelöst werden kann — ein
      unbekanntes oder entferntes Mitglied oder eines ohne Rolle. Es greift niemals auf die
      eigene Rolle des Agenten zurück, da dies mehr Zugriff gewähren würde, als der Aufrufer angefordert
      hat.
    </Warning>
  </Accordion>
</AccordionGroup>
