# Willkommen bei oona Ein gemeinsamer Ort für Menschen, Agenten und die tägliche Arbeit. oona verbindet Chat, Aufgaben, Projekte, Dateien, Kalender und Agenten in einer gemeinsamen Arbeitsumgebung. Diese Dokumentation hilft dir beim Einstieg und beim Verbinden eigener Werkzeuge. ## Schnell loslegen 1. Melde dich bei oona an und wähle deinen Account. 2. Öffne einen Workspace, in dem du mit deinem Team arbeitest. 3. Starte ein Gespräch, lege eine Aufgabe an oder teile eine Datei. Der [Schnellstart](/docs/quickstart) führt dich durch die ersten Schritte. ## Die Arbeit deines Teams Ein **Account** ist die gemeinsame Umgebung deiner Organisation. **Workspaces** bündeln die Arbeit einzelner Teams oder Bereiche. In ihnen findest du die freigegebenen Chats, Projekte und Dateien. - [Accounts & Workspaces](/docs/workspaces): Struktur, Mitgliedschaft und Sichtbarkeit. - [Chat & Zusammenarbeit](/docs/chat): Kanäle, Threads, Erwähnungen und Standups. - [Aufgaben & Projekte](/docs/tasks): Arbeit planen und Fortschritt verfolgen. - [Dateien & Kalender](/docs/files-calendar): Dokumente teilen und Termine koordinieren. ## Menschen und Agenten Agenten können mit deinem Team arbeiten und über freigegebene Tools auf oona zugreifen. Du entscheidest, in welchen Workspaces sie arbeiten und welche Aktionen sie ausführen dürfen. Lies [Mit Agenten arbeiten](/docs/agents) und [Zugriff & Berechtigungen](/docs/permissions), bevor du einen Agenten einsetzt. ## Für Entwickler und MCP-Clients Der MCP-Endpunkt ist `https://oona.ai/mcp`. Die [Verbindungsanleitung](/docs/mcp) erklärt Anmeldung und erste Aufrufe. In der [MCP Reference](/docs/mcp-reference) findest du die aktuellen Tool-Verträge direkt aus der Anwendung. Jede Seite ist auch als Markdown verfügbar. [llms.txt](/docs/llms.txt) enthält den Seitenindex, [llms-full.txt](/docs/llms-full.txt) die vollständige Dokumentation und [mcp-tools.json](/docs/mcp-tools.json) die maschinenlesbaren Tool-Schemas. --- # Schnellstart Vom ersten Workspace zur gemeinsamen Arbeit in wenigen Schritten. ## Anmelden und Account wählen Öffne [oona](/users/sign_in) und melde dich an. Wenn du zu mehreren Accounts gehörst, wähle die Organisation, für die du gerade arbeitest. Inhalte und Berechtigungen gehören immer zum jeweiligen Account. Wenn dir ein Zugang fehlt, bitte eine zuständige Person in deiner Organisation um eine Einladung. ## Einen Workspace öffnen Wähle den Workspace deines Teams in der Navigation. Hier ist die gemeinsame Arbeit organisiert. Fehlt ein Workspace, prüfe deine Mitgliedschaft und die Freigaben mit einer zuständigen Person. Mehr zur Struktur findest du unter [Accounts & Workspaces](/docs/workspaces). ## Mit dem Team sprechen Öffne einen Chat-Kanal und schreibe eine Nachricht. Nutze einen Thread für Antworten zu einem bestimmten Thema und `@`-Erwähnungen, um eine Person anzusprechen. Private Kanäle und Direktnachrichten sind nur für berechtigte Personen zugänglich. ## Die erste Aufgabe Lege im passenden Workspace eine Aufgabe an. Vergib einen klaren Titel, beschreibe das gewünschte Ergebnis und ordne bei Bedarf eine verantwortliche Person, Labels und ein Projekt zu. Die Aufgabe erhält einen Schlüssel aus Workspace-Kürzel und laufender Nummer, zum Beispiel `ENG-128`. ## Den nächsten Schritt wählen - Lies [Chat & Zusammenarbeit](/docs/chat) für Gespräche und tägliche Updates. - Plane größere Vorhaben mit [Aufgaben & Projekten](/docs/tasks). - Verbinde einen externen Assistenten über [MCP](/docs/mcp). Welche Bereiche du siehst, hängt von den aktivierten Modulen und deinen Berechtigungen ab. --- # Accounts & Workspaces Organisiere dein Team und lege fest, wer welche Inhalte sehen kann. ## Accounts Ein Account bündelt die Mitglieder, Einstellungen und Daten einer Organisation. Du kannst mehreren Accounts angehören und zwischen ihnen wechseln. Deine Rolle und dein Zugriff können sich von Account zu Account unterscheiden. Prüfe vor dem Anlegen oder Teilen von Inhalten, ob du im richtigen Account bist. ## Workspaces Workspaces strukturieren die Arbeit innerhalb eines Accounts. Ein Workspace kann zum Beispiel zu einem Team, einer Abteilung oder einem Arbeitsbereich gehören. Er hat einen Namen und ein kurzes Kürzel, das auch in Aufgabenschlüsseln verwendet wird. Workspace-Mitgliedschaften und Freigaben legen fest, welche Chats, Projekte und Dateien dir zur Verfügung stehen. Nicht jedes aktivierte Modul muss in jedem Workspace genutzt werden. ## Kanäle und private Inhalte Öffentliche Kanäle sind innerhalb des berechtigten Workspace-Kontexts zugänglich. Für private Kanäle und Direktnachrichten gelten zusätzliche Mitgliedschaften. Die Bezeichnung „öffentlich“ bedeutet hier keine Veröffentlichung im Internet. ## Verwaltung Admins und berechtigte verwaltende Personen können Workspaces und Mitgliedschaften verwalten. Ein archivierter Workspace ist von einem aktiven Workspace zu unterscheiden; bestehende Inhalte unterliegen weiterhin den Zugriffsregeln. Für Agenten gelten zusätzlich deren Workspace-Freigaben und Zugriffsprofile. Die [Berechtigungsübersicht](/docs/permissions) erklärt die einzelnen Ebenen. --- # Chat & Zusammenarbeit Gespräche, Threads und tägliche Updates an einem Ort. ## Kanäle Nutze Kanäle für gemeinsame Themen. Öffentliche Kanäle stehen im berechtigten Workspace zur Verfügung; private Kanäle setzen eine passende Mitgliedschaft voraus. Über Direktnachrichten kannst du einzelne Personen erreichen. ## Threads und Erwähnungen Antworte in einem Thread, wenn sich deine Nachricht auf einen bestehenden Beitrag bezieht. So bleibt das Gespräch zusammen. oona unterstützt eine Thread-Ebene. Mit `@` kannst du Personen erwähnen. Reaktionen eignen sich für kurze Rückmeldungen, ohne eine zusätzliche Nachricht zu schreiben. Dateien können direkt am Gespräch geteilt werden. ## Ungelesene Nachrichten oona unterscheidet ungelesene Inhalte und persönliche Hinweise, etwa Erwähnungen und Direktnachrichten. Persönliche Zähler können deshalb von der Zahl aller ungelesenen Kanalnachrichten abweichen. Benachrichtigungen hängen außerdem von deinen Einstellungen und dem verwendeten Gerät ab. ## Standups Halte in einem täglichen Standup fest, woran du gearbeitet hast, was als Nächstes ansteht und wo du Unterstützung brauchst. Ein Eintrag kann zunächst als Entwurf bestehen und später vervollständigt werden. ## Zeiterfassung Wenn das Modul für dich freigegeben ist, kannst du Arbeitszeiten und Pausen erfassen sowie den Arbeitsort angeben. Prüfe einen offenen Eintrag vor dem Start eines neuen. Abwesenheiten und die Verwaltung anderer Personen hängen von deiner Rolle ab. ## Chat per MCP Ein Client findet Kanäle über [chat_list_channels](/docs/mcp-reference/chat_list_channels) und liest Gespräche mit [chat_get_messages](/docs/mcp-reference/chat_get_messages). Schreiben erfolgt über [chat_send_message](/docs/mcp-reference/chat_send_message) und benötigt eine entsprechende Freigabe. --- # Aufgaben & Projekte Plane Arbeit mit deinem Team und behalte den Fortschritt im Blick. ## Aufgaben Eine Aufgabe gehört zu einem Workspace und erhält einen eindeutigen Schlüssel wie `ENG-128`. Titel und Beschreibung erklären die Arbeit; Status, Verantwortliche und Labels helfen beim Organisieren. Kommentare halten Rückfragen und Entscheidungen direkt an der Aufgabe fest. ## Projekte Projekte bündeln zusammengehörige Aufgaben innerhalb eines Workspaces. Projekt-Updates und Aktivitäten zeigen Fortschritt und Entscheidungen. Verknüpfe eine Aufgabe mit dem passenden Projekt, damit das Team den Zusammenhang erkennt. ## Zyklen und Roadmaps Wenn Zyklen im Workspace aktiviert sind, helfen sie bei der Planung zeitlich begrenzter Arbeitsabschnitte. Roadmaps geben einen Überblick über größere Vorhaben und deren Zuordnung zu Projekten. Die sichtbaren Möglichkeiten hängen von den Workspace-Einstellungen ab. ## Wiederkehrende Aufgaben Eine Aufgabenserie erzeugt einzelne Aufgaben nach einem Zeitplan. Die Vorlage und die erzeugten Aufgaben sind getrennte Objekte: Eine Änderung an einer einzelnen Aufgabe ändert nicht automatisch die Serie. ## Aufgaben per MCP 1. Ermittle den Account mit [whoami](/docs/mcp-reference/whoami). 2. Finde den Workspace mit [workspace_list](/docs/mcp-reference/workspace_list). 3. Lies Aufgaben über [task_list](/docs/mcp-reference/task_list) oder [task_get](/docs/mcp-reference/task_get). 4. Verwende [task_save](/docs/mcp-reference/task_save) zum Erstellen oder Bearbeiten, wenn dein Zugriff das erlaubt. Übernimm die zurückgegebenen IDs unverändert. Ein lesbarer Aufgabenschlüssel und eine `task_…`-ID sind unterschiedliche Werte; die Tool-Referenz beschreibt, welcher Parameter erwartet wird. --- # Dateien & Kalender Teile Dokumente und organisiere Termine im passenden Workspace. ## Dateien im Workspace Drives bündeln Dateien und Ordner im jeweiligen Workspace. Teile Dokumente mit den vorgesehenen Personen und verwende die passenden Freigaben. Eine Datei in einem Workspace ist nicht automatisch für jeden Account-Nutzer zugänglich. Öffentliche Links sind eine bewusste Freigabe. Prüfe vor dem Teilen, für wen das Dokument bestimmt ist. ## Gemeinsam an Dokumenten arbeiten Unterstützte Dokumente lassen sich aus oona öffnen und bearbeiten. Der Zugriff auf das Dokument folgt den Berechtigungen für die Datei und ihren Kontext. Entzogene Berechtigungen können daher auch den Zugriff auf ein bereits bekanntes Dokument verhindern. ## Kalender und Termine Wähle den passenden Kalender, bevor du einen Termin anlegst oder bearbeitest. Kalender-Verbindungen, Einladungen und Workspace-Freigaben bestimmen, welche Termine du sehen oder verwalten kannst. Für wiederkehrende Termine ist zwischen einem einzelnen Vorkommen und der gesamten Serie zu unterscheiden. ## Dateien per MCP [attachment_upload](/docs/mcp-reference/attachment_upload) bereitet einen Upload vor. Verwende danach den zurückgegebenen Anhang beim vorgesehenen Ziel, etwa einer Nachricht oder einer Aufgabe. Bei einem vorbereiteten Upload muss die Dateiübertragung abgeschlossen sein, bevor der Anhang verwendet werden kann. Die [MCP Reference](/docs/mcp-reference) enthält auch die registrierten `drive_…`- und `calendar_…`-Tools mit ihren aktuellen Parametern. Download-URLs können zeitlich begrenzt sein; speichere für spätere Arbeit die Objekt-ID. --- # Mit Agenten arbeiten Verbinde Agenten mit klaren Aufgaben und gezielten Zugriffsrechten. ## Eine klare Aufgabe geben Beschreibe das gewünschte Ergebnis, den betroffenen Workspace und die Grenzen der Aufgabe. Ein Agent kann nur die Verbindungen und Tools nutzen, die ihm tatsächlich freigegeben wurden. ## Zugriff gezielt vergeben Zugriffsprofile legen fest, welche Tools ein Agent verwenden darf. Workspace-Freigaben bestimmen, wo er arbeitet. Aktiviere die benötigten Verbindungen und Module und erteile nur die für die Aufgabe nötigen Rechte. Ein Profil für lesende Auswertungen kann beispielsweise den Chat lesen, ohne Nachrichten schreiben zu dürfen. Auch grundlegende Tools bleiben widerrufbar. Mehr dazu unter [Zugriff & Berechtigungen](/docs/permissions). ## Im Chat arbeiten Damit ein Agent in einem Kanal antworten kann, benötigt er eine funktionierende oona-Verbindung und eine Freigabe für `chat_send_message` im passenden Kontext. Ein sichtbarer Agent ist nicht automatisch zum Schreiben berechtigt. ## Routinen und Ausführungen Wiederkehrende Aufgaben und Auslöser können Arbeit automatisch starten. Prüfe Zeitplan, Ziel-Workspace und die erwarteten Aktionen. Ausführungen und Aktivitäten helfen nachzuvollziehen, was ein Agent getan hat und ob Unterstützung nötig ist. ## Externe Clients anbinden Für einen externen Assistenten nutzt du den [MCP-Endpunkt](/docs/mcp). Der Client handelt unter der angemeldeten Identität und deren Berechtigungen. Die öffentliche Referenz beschreibt alle registrierten Tools; die tatsächlich angebotenen und aufrufbaren Tools können durch Freigaben eingeschränkt sein. --- # MCP verbinden Verbinde einen MCP-Client mit oona und finde die richtigen Tools. ## Endpunkt Verbinde deinen MCP-Client mit: ```text https://oona.ai/mcp ``` oona verarbeitet MCP-Aufrufe als JSON-RPC über HTTP POST. Der Server arbeitet zustandslos; ein separater SSE-Stream wird nicht angeboten. Ein authentifizierter GET-Aufruf auf den Endpunkt antwortet deshalb mit HTTP 405. ## Anmeldung Clients mit OAuth-Unterstützung können die Anmeldung über die Server-Discovery starten. Trage die URL in deinem Client als entfernten MCP-Server ein, melde dich im Browser bei oona an und bestätige die angefragte Verbindung. Für Skripte akzeptiert der Server außerdem einen gültigen persönlichen API-Token als `Authorization: Bearer …`. Behandle Tokens wie Passwörter und gib sie nicht in Chats oder Quellcode weiter. Die genaue Einrichtung einer entfernten Verbindung hängt vom verwendeten Client ab. ## Erste Aufrufe Rufe zuerst [whoami](/docs/mcp-reference/whoami) auf. Die Antwort enthält deine Identität und die verfügbaren Accounts. Bei mehreren Accounts wählst du den passenden aus der Antwort. Verwende diese `acct_…`-ID für Account-bezogene Aufrufe. Mit [workspace_list](/docs/mcp-reference/workspace_list) findest du sichtbare Workspaces. Objekt-IDs wie `wsp_…`, `chan_…` und `task_…` werden unverändert weitergereicht und niemals geraten. ## Ein lesender Beispielaufruf Das folgende Beispiel nutzt einen bereits vorhandenen Token aus der Umgebungsvariable `OONA_API_TOKEN` und fragt nur deine Identität ab: ```sh curl https://oona.ai/mcp \ -H "Authorization: Bearer $OONA_API_TOKEN" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ --data '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}' ``` MCP-Clients führen beim Verbindungsaufbau außerdem den üblichen `initialize`-Austausch aus. `tools/list` fragt die angebotenen Tools ab; `tools/call` ruft eines davon auf. ## Fehler verstehen - **HTTP 401**: Die Anmeldung fehlt oder der Token ist ungültig. OAuth-Clients erhalten einen Discovery-Hinweis im `WWW-Authenticate`-Header. - **HTTP 405 bei GET**: Verwende HTTP POST für MCP-Aufrufe. - **Tool-Fehler**: Prüfe die erforderlichen Parameter, den gewählten Account und deine Berechtigungen. Ein JSON-RPC-Aufruf kann HTTP 200 liefern und trotzdem einen Tool-Fehler enthalten. ## Referenz und Exporte Die [MCP Reference](/docs/mcp-reference) dokumentiert alle registrierten Tools. [mcp-tools.json](/docs/mcp-tools.json) bietet dieselben Schemas maschinenlesbar. Die Tool-Beschreibungen und Schemas stammen direkt aus den registrierten Tool-Klassen und werden mit der Anwendung veröffentlicht. --- # Zugriff & Berechtigungen Verstehe Rollen, Module und Zugriffsprofile für Menschen und Agenten. ## Account und Mitgliedschaft Jeder Zugriff gehört zu einer Identität und einem Account. Eine aktive Mitgliedschaft ist Voraussetzung für den Zugriff auf Account-Inhalte. Archivierte Accounts und inaktive Mitgliedschaften schränken den Zugriff ein. ## Rollen und Workspaces Rollen regeln, welche Aktionen du ausführen darfst. Workspace-Mitgliedschaften und Freigaben bestimmen, in welchen Bereichen du arbeitest. Private Kanäle, Direktnachrichten, Dateien und Kalender können weitere Regeln haben. ## Aktivierte Module Ein Modul muss für den Account und die betreffende Person verfügbar sein. Ein Tool-Zugriffsprofil aktiviert kein ansonsten gesperrtes Modul. Für externe Mitglieder können zusätzliche Einschränkungen gelten. ## Agentenprofile Für Agenten sind beide Tool-Kategorien standardmäßig gesperrt und widerrufbar: - **basic**: grundlegende Gesprächs- und Identitätsfunktionen, die über das Basisprofil ausdrücklich freigegeben werden können. - **gated**: fachliche, schreibende, externe oder aufwendige Tools, die eine gezielte Freigabe benötigen. Dazu können auch lesende Tools gehören. Die Kategorie beschreibt die Einordnung eines Tools, nicht eine Zusage, dass jeder Agent es verwenden darf. ## MCP-Zugriff Eine Anmeldung am MCP-Server ersetzt keine Rollen-, Workspace- oder Modulprüfung. Übernimm Account- und Objekt-IDs aus den Antworten des Servers. Die öffentliche [MCP Reference](/docs/mcp-reference) enthält die registrierten Verträge; `tools/list` liefert den Katalog für deinen angemeldeten Client. Wenn eine Aktion verweigert wird, prüfe Identität, ausgewählten Account, aktive Mitgliedschaft, Workspace-Zugriff, Modul und Tool-Freigabe. --- # MCP Reference Alle registrierten Tools mit Beschreibung, Parametern sowie Ein- und Ausgabeschema. ## Der aktuelle Tool-Katalog Wähle ein Tool in der Navigation oder in der Übersicht unten. Jede Tool-Seite enthält die Beschreibung, Pflichtparameter, die Zugriffskategorie und die vollständigen JSON-Schemas für Ein- und Ausgabe. Die technischen Tool-Verträge sind in ihrer ursprünglichen Sprache wiedergegeben. ## Mit der Identität beginnen 1. [whoami](/docs/mcp-reference/whoami) liefert die Identität und die verfügbaren Accounts. 2. [account_list](/docs/mcp-reference/account_list) listet die Accounts der angemeldeten Person. 3. [workspace_list](/docs/mcp-reference/workspace_list) findet Workspaces im gewählten Account. Übernimm die zurückgegebenen IDs. Die [MCP-Anleitung](/docs/mcp) erklärt Verbindung, Anmeldung und Beispielaufrufe. ## Berechtigungen beachten Die Referenz beschreibt alle registrierten Tools. Der Katalog ist keine Zugriffsfreigabe: Rollen, aktive Mitgliedschaften, Module, Workspace-Freigaben und Agentenprofile werden bei Aufrufen geprüft. Auch mit `basic` gekennzeichnete Tools sind widerrufbar. ## Maschinenlesbare Referenz [mcp-tools.json](/docs/mcp-tools.json) enthält alle Tool-Verträge. Jede Tool-Seite ist zusätzlich unter derselben URL mit `.md` verfügbar. [llms.txt](/docs/llms.txt) enthält einen verlinkten Index und [llms-full.txt](/docs/llms-full.txt) die gesamte Dokumentation. --- # absence_save Create / update / delete an absence ## Beschreibung Files (or updates, or deletes) an absence row for a user — vacation, unpaid_leave, or sickness. Pass `id` to update; add `delete: true` to remove instead. Same role-scoped rules as the web UI: - admin / employer: any user, any date. - member: only their own rows; sick limited to a 1-day retro cap. `unpaid_leave` (ENG-1392) uses the same lifecycle as vacation (planned; no retroactive cap) but records the day as off-book for payroll — distinct from paid vacation. Bank holidays live in the web UI; no MCP tool for them in this iteration. ## Zugriff Zugriffsprofil: `gated`. Module: `timeclock`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `id` | string | Nein | Absence prefix ID (abs_…). Omit to create. | | `user_id` | string | Nein | User prefix (user_…) or @handle. Defaults to the caller for plain members; required to specify a different user for admin / employer. | | `type` | string | Nein | Required on create. `unpaid_leave` shares vacation's lifecycle (no retroactive cap). | | `start_date` | string | Nein | ISO date YYYY-MM-DD. Required on create. | | `end_date` | string | Nein | ISO date YYYY-MM-DD. Defaults to `start_date` if omitted on create. | | `half_day` | boolean | Nein | | | `note` | string / null | Nein | | | `delete` | boolean | Nein | When true and `id` is present, delete the row. Mutually exclusive with field updates. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "id": { "type": "string", "description": "Absence prefix ID (abs_…). Omit to create." }, "user_id": { "type": "string", "description": "User prefix (user_…) or @handle. Defaults to the caller for plain members; required to specify a different user for admin / employer." }, "type": { "type": "string", "enum": [ "vacation", "sick", "unpaid_leave" ], "description": "Required on create. `unpaid_leave` shares vacation's lifecycle (no retroactive cap)." }, "start_date": { "type": "string", "description": "ISO date YYYY-MM-DD. Required on create." }, "end_date": { "type": "string", "description": "ISO date YYYY-MM-DD. Defaults to `start_date` if omitted on create." }, "half_day": { "type": "boolean" }, "note": { "type": [ "string", "null" ] }, "delete": { "type": "boolean", "description": "When true and `id` is present, delete the row. Mutually exclusive with field updates." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "absence": { "type": "object", "properties": { "id": { "type": "string" }, "type": { "type": "string" }, "user": { "type": "object" }, "start_date": { "type": "string" }, "end_date": { "type": "string" }, "half_day": { "type": "boolean" }, "note": { "type": [ "string", "null" ] } } }, "deleted": { "type": "boolean", "description": "True when the row was deleted." } }, "type": "object" } ``` --- # account_list List Accounts ## Beschreibung Lists the accounts the authenticated user is a member of, plus the caller's identity. Call this first — every other tool requires an `account_id` argument, and the returned `roles` determine what data you see elsewhere (`[]` = regular member, `["employer"]` and `["admin"]` unlock workspace-wide reads). Use the `acct_` account prefix IDs returned here on every other tool. No parameters. Safe to call on every session start; never mutates state. ## Zugriff Zugriffsprofil: `basic`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter Dieses Tool benötigt keine Parameter. ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": {}, "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "current_user": { "type": "object", "properties": { "id": { "type": "string", "description": "User prefix ID (user_…)." }, "handle": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "handle", "name" ] }, "accounts": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Account prefix ID (acct_…) — pass to every other tool as account_id." }, "name": { "type": "string" }, "personal": { "type": "boolean", "description": "True for the auto-created personal account." }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "employer" ] }, "description": "Empty array = regular member." } }, "required": [ "id", "name", "personal", "roles" ] } } }, "required": [ "current_user", "accounts" ], "type": "object" } ``` --- # account_list_users List Users ## Beschreibung Lists the people on the account — resolve `@handle` mentions, pick a `user_id` target, or show a roster. Admin and employer callers additionally see email, phone_number, time_zone (contact-sensitive data) and employment-time metadata: `working_hours` — the merged shape from ENG-1434 with `start_at` (HH:MM), `paused_minutes`, and `hours_by_weekday` ({"mon": 8.0, …}, missing key = not a workday); plus `checkin_not_required` (exempt from clock-in/out logic, e.g. C-level), and `standup_not_required`. `include_inactive` defaults to true so historical mentions still resolve; pass false for a live roster. `search` is a case-insensitive substring over handle / first_name / last_name (+ email for admin/employer). ## Zugriff Zugriffsprofil: `basic`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). Discover via account_list. | | `include_inactive` | boolean | Nein | Include inactive (departed) users so historical @handles still resolve. Default true. Pass false for a live-roster view. | | `search` | string | Nein | Case-insensitive substring, 1+ chars. Matches handle / first_name / last_name (admin/employer: also email). Use for narrowing before pulling the full list. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123). Discover via account_list." }, "include_inactive": { "type": "boolean", "description": "Include inactive (departed) users so historical @handles still resolve. Default true. Pass false for a live-roster view." }, "search": { "type": "string", "description": "Case-insensitive substring, 1+ chars. Matches handle / first_name / last_name (admin/employer: also email). Use for narrowing before pulling the full list." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "users": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "User prefix ID (user_…) — pass to tools that accept user_id (handle also accepted)." }, "db_id": { "type": "integer", "description": "Integer PK — matches user.db_id in chat/time-clock/standup response rows." }, "handle": { "type": "string", "description": "Unique within the account; what @handle mentions reference." }, "name": { "type": "string" }, "position": { "type": [ "string", "null" ], "description": "Omitted for external (guest) callers." }, "remote_worker": { "type": "boolean", "description": "Omitted for external (guest) callers." }, "status": { "type": "string", "enum": [ "active", "inactive" ], "description": "Omitted for external (guest) callers." }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "employer" ] }, "description": "Empty = regular member." }, "is_agent": { "type": "boolean", "description": "True if this user is a bot account (AI participant). Treat the row as an agent rather than a person — don't ask the bot for human feedback; don't assign tasks expecting human work." }, "email": { "type": "string", "description": "Only present for admin/employer callers." }, "phone_number": { "type": [ "string", "null" ], "description": "Only present for admin/employer callers." }, "time_zone": { "type": [ "string", "null" ], "description": "Rails TimeZone display label (e.g. 'Berlin'), not an IANA id. Only for admin/employer callers." }, "working_hours": { "type": "object", "description": "ENG-1434. Merged working-hours record for this member. `start_at` HH:MM daily start, `paused_minutes` daily break, `hours_by_weekday` a map of weekday → Float hours (missing key = not a workday for this member; don't flag them missing). Only present for admin/employer callers.", "properties": { "start_at": { "type": "string" }, "paused_minutes": { "type": "integer" }, "hours_by_weekday": { "type": "object", "description": "e.g. {\"mon\": 8.0, \"fri\": 4.0}" } } }, "checkin_not_required": { "type": "boolean", "description": "True when the user is exempt from clock-in/out (C-level, etc.) — attendance logic must NOT flag them as missing. Only present for admin/employer callers." }, "standup_not_required": { "type": "boolean", "description": "True when the user is exempt from the daily standup roster. Only present for admin/employer callers." } }, "required": [ "id", "db_id", "handle", "name", "roles", "is_agent" ] } } }, "required": [ "users" ], "type": "object" } ``` --- # agent_get Get Agent ## Beschreibung Returns a single agent by prefix id. The response is the same payload `agent_save` and `agent_list` return — including `system_prompt`, `model`, and `tools`. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Agent prefix id (agnt_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Agent prefix id (agnt_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "system_prompt": { "type": [ "string", "null" ] }, "model": { "type": [ "string", "null" ] }, "tools": { "type": "array", "items": { "type": [ "string", "object" ] } }, "active": { "type": "boolean" }, "creator_role": { "type": "string" }, "creator": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name", "active", "creator_role", "created_at" ] } }, "required": [ "agent" ], "type": "object" } ``` --- # agent_list List Agents ## Beschreibung Lists the account's AI agents (every agent is scoped to one account and visible to all its members). Sorted alphabetically by name. Filters (all optional): - `active` — true to hide retired rows, false to show only retired - `query` — case-insensitive substring match on name - `limit` — default 50, max 250 ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `active` | boolean | Nein | | | `query` | string | Nein | | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "active": { "type": "boolean" }, "query": { "type": "string" }, "limit": { "type": "integer", "default": 50 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agents": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "system_prompt": { "type": [ "string", "null" ] }, "model": { "type": [ "string", "null" ] }, "tools": { "type": "array", "items": { "type": [ "string", "object" ] } }, "active": { "type": "boolean" }, "creator_role": { "type": "string" }, "creator": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name", "active", "creator_role", "created_at" ] } } }, "required": [ "agents" ], "type": "object" } ``` --- # agent_log_list List Agent Log Entries ## Beschreibung Call this before any action you might have already taken — e.g. before commenting on a task, nudging a user, or escalating something. If a recent entry shows you already did the same action under the same subject, escalate or move on instead of repeating. Returns *your own* log entries in this account, newest first. Other users' entries are invisible. Filters (all optional, AND-combined): - `subject` — exact match. Use the same conventions as `agent_log_write` (`"task:ENG-123"`, `"standup:user_max:2026-05-07"`). - `tags` — match if the entry has *any* of the given tags (OR, not AND). - `since` — only entries created at or after this moment. Same lenient parsing as `agent_reminder_upsert.due_at`: relative offset (`+30m`, `+2h`, `+1d`), ISO 8601, date-only, space-separated, or Unix epoch. Note: relative offsets here are *future*-anchored — to scan the last 2h pass the absolute time `(Time.now - 2h).iso8601`, or just pass the date `today`. Bad input → error. - `limit` — default 50, max 200. Example: before nudging @max again about ENG-123, call with `subject: "task:ENG-123"`, `tags: ["estimate-reminder"]` — if anything comes back from the last 24h, don't nudge again. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `subject` | string | Nein | Exact-match filter, e.g. 'task:ENG-123'. | | `tags` | array | Nein | Match if the entry has ANY of these tags (OR). | | `since` | string | Nein | Only entries created at or after this moment. Accepts ISO 8601, date-only, space-separated, Unix epoch, or relative future offset. Bad input → error. | | `limit` | integer | Nein | Max rows (default 50, max 200). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "subject": { "type": "string", "description": "Exact-match filter, e.g. 'task:ENG-123'." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "Match if the entry has ANY of these tags (OR)." }, "since": { "type": "string", "description": "Only entries created at or after this moment. Accepts ISO 8601, date-only, space-separated, Unix epoch, or relative future offset. Bad input → error." }, "limit": { "type": "integer", "default": 50, "description": "Max rows (default 50, max 200)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "entries": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "body": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "tags": { "type": "array", "items": { "type": "string" } }, "created_at": { "type": "string" } }, "required": [ "id", "body", "tags", "created_at" ] } } }, "required": [ "entries" ], "type": "object" } ``` --- # agent_log_write Write Agent Log Entry ## Beschreibung Call this immediately after you complete a meaningful action that a future session might otherwise repeat — e.g. you commented on a task asking for an estimate, DM'd a user about a missed standup, or escalated something to a workspace lead. The next session will read your entries via `agent_log_list` *before* acting, and skip duplicates. Entries are append-only, scoped to (you, this account), and invisible to other users. There is no update or delete. Use a stable, machine-friendly `subject` so write and read line up — e.g. `"task:ENG-123"`, `"standup:user_max:2026-05-07"`, `"user:user_abc123"`. Use `tags` for short reusable labels you'll filter on later, e.g. `["estimate-reminder"]`, `["standup-followup", "escalated"]`. Both are optional but strongly recommended — without them you can only retrieve by recency. Example: after asking @max for an estimate on ENG-123, call with `body: "Asked @max for estimate"`, `subject: "task:ENG-123"`, `tags: ["estimate-reminder"]`. `body` ≤ 8 KB; `subject` ≤ 200 chars. ## Zugriff Zugriffsprofil: `basic`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `body` | string | Ja | What you just did. ≤ 8 KB. | | `subject` | string | Nein | Stable identifier you'll match on later, e.g. 'task:ENG-123'. ≤ 200 chars. | | `tags` | array | Nein | Short labels for OR-filtering, e.g. ['estimate-reminder']. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "body": { "type": "string", "description": "What you just did. ≤ 8 KB." }, "subject": { "type": "string", "description": "Stable identifier you'll match on later, e.g. 'task:ENG-123'. ≤ 200 chars." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "Short labels for OR-filtering, e.g. ['estimate-reminder']." } }, "required": [ "account_id", "body" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "entry": { "type": "object", "properties": { "id": { "type": "string" }, "body": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "tags": { "type": "array", "items": { "type": "string" } }, "created_at": { "type": "string" } }, "required": [ "id", "body", "tags", "created_at" ] } }, "required": [ "entry" ], "type": "object" } ``` --- # agent_reminder_list_due List Due Agent Reminders ## Beschreibung Call this at the very start of every session, before doing anything else. It returns the reminders you previously scheduled for yourself that are now due — i.e. `due_at <= now`, not yet completed, and created within the last 14 days. Reminders older than 14 days are auto-hidden so the inbox doesn't grow unbounded. Sorted by `due_at` ascending — oldest-due first, so the most overdue work surfaces immediately. Workflow per row: read the `prompt`, do the work, then call `agent_reminder_upsert` with the row's `id` and `completed: true`. If the situation changed and you want to defer instead, call `agent_reminder_upsert` with the same `id` and a new `due_at`. Filters (all optional): - `subject` — exact match (e.g. `"task:ENG-123"`). - `tags` — match if the reminder has *any* of these tags. - `limit` — default 50, max 200. Returns *your own* reminders only; other users' reminders are invisible. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `subject` | string | Nein | | | `tags` | array | Nein | | | `limit` | integer | Nein | Max rows (default 50, max 200). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "subject": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "limit": { "type": "integer", "default": 50, "description": "Max rows (default 50, max 200)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "reminders": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "prompt": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "tags": { "type": "array", "items": { "type": "string" } }, "due_at": { "type": "string" }, "completed_at": { "type": [ "string", "null" ] }, "created_at": { "type": "string" } }, "required": [ "id", "prompt", "tags", "due_at", "created_at" ] } } }, "required": [ "reminders" ], "type": "object" } ``` --- # agent_reminder_upsert Create or Update Agent Reminder ## Beschreibung Schedules a follow-up prompt for yourself, or updates one you already scheduled. Use this whenever the right next step isn't "do it now" but "check back later" — e.g. you DM'd a user about a missed standup and want to re-check in 2 hours, or you asked a teammate for an estimate and want to escalate if it's still missing tomorrow. Two modes, decided by whether `id` is set: - Without `id` → create. `prompt` and `due_at` required. Returns the new reminder's `id` (`arem_…`). Repeated calls without `id` create new rows (not idempotent — use a stable `subject` to dedupe yourself). - With `id` → update. Only the fields you pass are changed. Use this to: - push the reminder out: pass `id` + a new `due_at` - mark it handled: pass `id` + `completed: true` (idempotent) - re-open: pass `id` + `completed: false` - rewrite the prompt as the situation evolves. Workflow: at session start, call `agent_reminder_list_due` first to find what's due, do the work, then call this tool with `id` + `completed: true` to clear it. `due_at` accepts several formats — pick whichever is easiest: - **Relative offset (most convenient for "in X")**: `+30m`, `+2h`, `+1d`, `+1w` (units: s/m/h/d/w; minutes / hours / days / weeks). No spaces. - **ISO 8601 datetime**: `2026-05-07T10:00:00Z` or `2026-05-07T12:00:00+02:00` (timezone offset preserved). - **Date only**: `2026-05-07` (becomes 00:00 in your timezone). - **Space-separated**: `2026-05-07 10:00` or `2026-05-07 10:00:00`. - **Unix epoch seconds**: `1746604800`. Negative offsets are rejected (reminders are always for the future). Bad input returns an error that lists every accepted format. Use the same `subject` and `tags` conventions as the logbook (`"task:ENG-123"`, `["standup-followup"]`) — they make the inbox filterable. Reminders auto-expire 14 days after creation if not completed (they stop appearing in `list_due`), so don't use this for long-horizon planning. Scoped to (you, this account); other users can't see or update your reminders. `prompt` ≤ 8 KB; `subject` ≤ 200 chars. Example (create, relative): `prompt: "Did @max submit standup? If not, DM @lead."`, `due_at: "+2h"`, `subject: "standup:user_max:2026-05-07"`, `tags: ["standup-followup"]`. Example (create, ISO): same `prompt`, `due_at: "2026-05-07T10:00:00Z"`. Example (push out 1 day): `id: "arem_abc123"`, `due_at: "+1d"`. Example (complete): `id: "arem_abc123"`, `completed: true`. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Reminder prefix id (arem_…). Omit to create. | | `prompt` | string | Nein | What you want yourself to do later. Required on create. ≤ 8 KB. | | `due_at` | string | Nein | When the reminder becomes due. Required on create. Accepts relative offset ('+30m', '+2h', '+1d', '+1w'), ISO 8601 ('2026-05-07T10:00:00Z'), date-only ('2026-05-07'), space-separated ('2026-05-07 10:00'), or Unix epoch seconds. See tool description for full list. | | `subject` | string / null | Nein | Optional stable identifier, e.g. 'task:ENG-123'. | | `tags` | array | Nein | Optional short labels. | | `completed` | boolean | Nein | true → mark handled (idempotent); false → re-open. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Reminder prefix id (arem_…). Omit to create." }, "prompt": { "type": "string", "description": "What you want yourself to do later. Required on create. ≤ 8 KB." }, "due_at": { "type": "string", "description": "When the reminder becomes due. Required on create. Accepts relative offset ('+30m', '+2h', '+1d', '+1w'), ISO 8601 ('2026-05-07T10:00:00Z'), date-only ('2026-05-07'), space-separated ('2026-05-07 10:00'), or Unix epoch seconds. See tool description for full list." }, "subject": { "type": [ "string", "null" ], "description": "Optional stable identifier, e.g. 'task:ENG-123'." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "Optional short labels." }, "completed": { "type": "boolean", "description": "true → mark handled (idempotent); false → re-open." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "reminder": { "type": "object", "properties": { "id": { "type": "string" }, "prompt": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "tags": { "type": "array", "items": { "type": "string" } }, "due_at": { "type": "string" }, "completed_at": { "type": [ "string", "null" ] }, "created_at": { "type": "string" } }, "required": [ "id", "prompt", "tags", "due_at", "created_at" ] } }, "required": [ "reminder" ], "type": "object" } ``` --- # agent_run_create Fire an Agent Run Manually ## Beschreibung Run a routine, or run an agent with a supplied prompt. A routine uses its own agent and prompt. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `prompt` | string | Nein | Required for an ad-hoc run. | | `agent_id` | string / null | Nein | Agent prefix id (agnt_…). Required unless a schedule with a bound agent is given. | | `agent_schedule_id` | string / null | Nein | Schedule prefix id (asch_…). Omit for an ad-hoc run. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "prompt": { "type": "string", "description": "Required for an ad-hoc run." }, "agent_id": { "type": [ "string", "null" ], "description": "Agent prefix id (agnt_…). Required unless a schedule with a bound agent is given." }, "agent_schedule_id": { "type": [ "string", "null" ], "description": "Schedule prefix id (asch_…). Omit for an ad-hoc run." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_run": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "string" }, "agent_schedule_id": { "type": [ "string", "null" ] }, "agent_trigger_id": { "type": [ "string", "null" ] }, "agent_id": { "type": [ "string", "null" ] }, "scheduled_for": { "type": [ "string", "null" ] }, "started_at": { "type": [ "string", "null" ] }, "finished_at": { "type": [ "string", "null" ] }, "skip_reason": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "url": { "type": "string" }, "prompt_snapshot": { "type": "string" }, "result": { "type": [ "string", "null" ] }, "error": { "type": [ "string", "null" ] } }, "required": [ "id", "status", "prompt_snapshot", "created_at", "url" ] } }, "required": [ "agent_run" ], "type": "object" } ``` --- # agent_run_get Get Agent Run ## Beschreibung Returns a single `AgentRun` row by prefix id, including the full `prompt_snapshot`, `result`, `error`, and `skip_reason` (all plain text — no Tiptap conversion). The base list payload from `agent_run_list` is included; this endpoint just adds the verbose fields. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Run prefix id (arun_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Run prefix id (arun_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_run": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "string" }, "agent_schedule_id": { "type": [ "string", "null" ] }, "agent_trigger_id": { "type": [ "string", "null" ] }, "agent_id": { "type": [ "string", "null" ] }, "scheduled_for": { "type": [ "string", "null" ] }, "started_at": { "type": [ "string", "null" ] }, "finished_at": { "type": [ "string", "null" ] }, "skip_reason": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "url": { "type": "string" }, "prompt_snapshot": { "type": "string" }, "result": { "type": [ "string", "null" ] }, "error": { "type": [ "string", "null" ] } }, "required": [ "id", "status", "prompt_snapshot", "created_at", "url" ] } }, "required": [ "agent_run" ], "type": "object" } ``` --- # agent_run_list List Agent Runs ## Beschreibung Lists `AgentRun` rows the caller can see, newest first. Scoped via `AgentRunPolicy::Scope` — members see only runs from their own schedules; admins and employers see every run in the account. Filters (all optional): - `agent_schedule_id` / `agent_id` — narrow by the linked record (prefix IDs) - `status` — "queued" / "running" / "success" / "failed" / "completed_with_errors" (ran but a tool/action errored) / "skipped" - `created_at` — return only rows created at or after this moment. Accepts: ISO 8601, `YYYY-MM-DD`, space-separated, Unix epoch, or a relative offset like `+30m` / `+2h` / `+1d` / `+1w` (which means "in the future from now" — useful as a sentinel, less so for run-listing). - `limit` — default 50, max 250 Each row carries a `url` field pointing at the run's page so a UI can link straight to it. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `agent_schedule_id` | string | Nein | | | `agent_id` | string | Nein | | | `status` | string | Nein | | | `created_at` | string | Nein | Lower bound. Accepts: ISO 8601 ('2026-05-07T10:00:00Z'), date-only ('2026-05-07'), space-separated ('2026-05-07 10:00'), Unix epoch seconds ('1746604800'), or relative offset ('+30m', '+2h', '+1d', '+1w') | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "agent_schedule_id": { "type": "string" }, "agent_id": { "type": "string" }, "status": { "type": "string", "enum": [ "queued", "running", "success", "failed", "skipped" ] }, "created_at": { "type": "string", "description": "Lower bound. Accepts: ISO 8601 ('2026-05-07T10:00:00Z'), date-only ('2026-05-07'), space-separated ('2026-05-07 10:00'), Unix epoch seconds ('1746604800'), or relative offset ('+30m', '+2h', '+1d', '+1w')" }, "limit": { "type": "integer", "default": 50 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_runs": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "string" }, "agent_schedule_id": { "type": [ "string", "null" ] }, "agent_trigger_id": { "type": [ "string", "null" ] }, "agent_id": { "type": [ "string", "null" ] }, "scheduled_for": { "type": [ "string", "null" ] }, "started_at": { "type": [ "string", "null" ] }, "finished_at": { "type": [ "string", "null" ] }, "skip_reason": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "url": { "type": "string" } }, "required": [ "id", "status", "created_at", "url" ] } } }, "required": [ "agent_runs" ], "type": "object" } ``` --- # agent_save Create or Update Agent ## Beschreibung Linear-style upsert for AI agent personas. Pass `id` (prefix `agnt_…`) to update, omit to create. On create: - `name` is required. The agent belongs to `account_id` and is visible to every member of that account. - `creator_id` is set to the current user. - `creator_role` is snapshotted from your role at this moment ("admin" or "employer"). The snapshot is frozen — a later role change can't reach back and unlock (or lock) this row. On update: - Only fields you pass are changed. - `creator_role` is immutable. `tools` is a free-form JSON array — list whichever tool names the runner expects (e.g. `["chat_send_message", "task_save"]`). ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Agent prefix id (agnt_…). Omit to create. | | `name` | string | Nein | Required on create. ≤ 120 chars. | | `system_prompt` | string / null | Nein | | | `model` | string / null | Nein | Model identifier the runner should use (e.g. 'claude-sonnet-4-6'). | | `tools` | array | Nein | Tool names the runner should expose to this agent. | | `active` | boolean | Nein | false to retire without deleting (scheduler skips inactive agents). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Agent prefix id (agnt_…). Omit to create." }, "name": { "type": "string", "description": "Required on create. ≤ 120 chars." }, "system_prompt": { "type": [ "string", "null" ] }, "model": { "type": [ "string", "null" ], "description": "Model identifier the runner should use (e.g. 'claude-sonnet-4-6')." }, "tools": { "type": "array", "items": { "type": "string" }, "description": "Tool names the runner should expose to this agent." }, "active": { "type": "boolean", "description": "false to retire without deleting (scheduler skips inactive agents)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "system_prompt": { "type": [ "string", "null" ] }, "model": { "type": [ "string", "null" ] }, "tools": { "type": "array", "items": { "type": [ "string", "object" ] } }, "active": { "type": "boolean" }, "creator_role": { "type": "string" }, "creator": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name", "active", "creator_role", "created_at" ] } }, "required": [ "agent" ], "type": "object" } ``` --- # agent_schedule_get Get Agent Schedule ## Beschreibung Returns a single schedule plus every trigger and the most recent runs (`recent_runs`, capped at 20, newest first). ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Schedule prefix id (asch_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Schedule prefix id (asch_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_schedule": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "prompt": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "concurrency": { "type": "string" }, "catch_up": { "type": "string" }, "catch_up_cap": { "type": "integer" }, "agent_id": { "type": [ "string", "null" ] }, "owner": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "triggers": { "type": "array", "items": { "type": "object" } }, "recent_runs": { "type": "array", "items": { "type": "object" } } }, "required": [ "id", "title", "prompt", "status", "account_id", "created_at" ] } }, "required": [ "agent_schedule" ], "type": "object" } ``` --- # agent_schedule_list List Agent Schedules ## Beschreibung Lists schedule rows the caller can see — account-scoped plus your own private — with their triggers inlined so the UI doesn't need a second round-trip per row. Sorted by `created_at` ascending. Filters (all optional): - `status` — "draft" / "active" / "paused" / "archived" - `agent_id` — show only schedules bound to a given agent - `limit` — default 50, max 250 ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `status` | string | Nein | | | `agent_id` | string | Nein | | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "status": { "type": "string", "enum": [ "draft", "active", "paused", "archived" ] }, "agent_id": { "type": "string" }, "limit": { "type": "integer", "default": 50 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_schedules": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "prompt": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "concurrency": { "type": "string" }, "catch_up": { "type": "string" }, "catch_up_cap": { "type": "integer" }, "agent_id": { "type": [ "string", "null" ] }, "owner": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "triggers": { "type": "array", "items": { "type": "object" } } }, "required": [ "id", "title", "prompt", "status", "account_id", "created_at" ] } } }, "required": [ "agent_schedules" ], "type": "object" } ``` --- # agent_schedule_save Create or Update Agent Schedule ## Beschreibung Create or update a routine with its own title and prompt. Runs use the selected agent. Activation requires an agent and an active trigger. Pass id to update. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Routine prefix id (asch_…). Omit to create. | | `title` | string | Nein | | | `prompt` | string | Nein | Instructions sent to the agent on each run. | | `agent_id` | string | Nein | Agent prefix id. Required before activation. | | `status` | string | Nein | | | `concurrency` | string | Nein | | | `catch_up` | string | Nein | | | `catch_up_cap` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Routine prefix id (asch_…). Omit to create." }, "title": { "type": "string" }, "prompt": { "type": "string", "description": "Instructions sent to the agent on each run." }, "agent_id": { "type": "string", "description": "Agent prefix id. Required before activation." }, "status": { "type": "string", "enum": [ "draft", "active", "paused", "archived" ] }, "concurrency": { "type": "string", "enum": [ "coalesce", "always_enqueue", "skip_if_active" ] }, "catch_up": { "type": "string", "enum": [ "skip_missed", "enqueue_capped" ] }, "catch_up_cap": { "type": "integer" } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_schedule": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "prompt": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "concurrency": { "type": "string" }, "catch_up": { "type": "string" }, "catch_up_cap": { "type": "integer" }, "agent_id": { "type": [ "string", "null" ] }, "owner": { "type": [ "object", "null" ] }, "account_id": { "type": [ "string", "null" ] }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "title", "prompt", "status", "account_id", "created_at" ] } }, "required": [ "agent_schedule" ], "type": "object" } ``` --- # agent_trigger_list List Agent Triggers ## Beschreibung Lists every trigger for one `AgentSchedule`, sorted by `next_run_at` ascending so the soonest-to-fire row comes first. Inactive (`active = false`) triggers are included — filter client-side if you only want firing ones. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `agent_schedule_id` | string | Ja | Schedule prefix id (asch_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "agent_schedule_id": { "type": "string", "description": "Schedule prefix id (asch_…)." } }, "required": [ "account_id", "agent_schedule_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_triggers": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "agent_schedule_id": { "type": "string" }, "frequency": { "type": "string" }, "run_at": { "type": [ "string", "null" ] }, "weekday": { "type": [ "integer", "null" ] }, "day_of_month": { "type": [ "integer", "null" ] }, "cron_expression": { "type": [ "string", "null" ] }, "timezone": { "type": "string" }, "next_run_at": { "type": [ "string", "null" ] }, "last_run_at": { "type": [ "string", "null" ] }, "active": { "type": "boolean" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "agent_schedule_id", "frequency", "timezone", "active", "created_at" ] } } }, "required": [ "agent_triggers" ], "type": "object" } ``` --- # agent_trigger_save Create or Update Agent Trigger ## Beschreibung Linear-style upsert for cadence rows attached to an `AgentSchedule`. Pass `id` (prefix `atrg_…`) to update, omit to create. `agent_schedule_id` is required. Frequencies and their inputs: - `hourly` — fires at the top of every hour - `daily` — needs `run_at` ("HH:MM") - `weekly` — needs `run_at` + `weekday` (0=Sunday … 6=Saturday) - `monthly` — needs `run_at` + `day_of_month` (1–31; days that don't exist in a given month fall to the last day) - `cron` — needs `cron_expression` (5-field standard cron, parsed by Fugit; uses the trigger's timezone) `next_run_at` is recomputed on every save — you never set it directly. DST-aware: timezones like Europe/Berlin keep the wall-clock hour stable across the March / October switches. Authorization delegates to the parent schedule: who can update the schedule can update its triggers. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Trigger prefix id (atrg_…). Omit to create. | | `agent_schedule_id` | string | Nein | Required on create. | | `frequency` | string | Nein | | | `run_at` | string / null | Nein | Wall-clock time-of-day 'HH:MM' for daily/weekly/monthly. | | `weekday` | integer / null | Nein | 0=Sunday … 6=Saturday. Weekly only. | | `day_of_month` | integer / null | Nein | 1–31. Monthly only. | | `cron_expression` | string / null | Nein | 5-field standard cron. Cron-frequency only. | | `timezone` | string | Nein | IANA timezone (e.g. 'Europe/Berlin'). Defaults to 'Europe/Berlin' on create. | | `active` | boolean | Nein | false to retire a cadence row without deleting (scheduler skips inactive triggers). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Trigger prefix id (atrg_…). Omit to create." }, "agent_schedule_id": { "type": "string", "description": "Required on create." }, "frequency": { "type": "string", "enum": [ "hourly", "daily", "weekly", "monthly", "cron" ] }, "run_at": { "type": [ "string", "null" ], "description": "Wall-clock time-of-day 'HH:MM' for daily/weekly/monthly." }, "weekday": { "type": [ "integer", "null" ], "description": "0=Sunday … 6=Saturday. Weekly only." }, "day_of_month": { "type": [ "integer", "null" ], "description": "1–31. Monthly only." }, "cron_expression": { "type": [ "string", "null" ], "description": "5-field standard cron. Cron-frequency only." }, "timezone": { "type": "string", "description": "IANA timezone (e.g. 'Europe/Berlin'). Defaults to 'Europe/Berlin' on create." }, "active": { "type": "boolean", "description": "false to retire a cadence row without deleting (scheduler skips inactive triggers)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "agent_trigger": { "type": "object", "properties": { "id": { "type": "string" }, "agent_schedule_id": { "type": "string" }, "frequency": { "type": "string" }, "run_at": { "type": [ "string", "null" ] }, "weekday": { "type": [ "integer", "null" ] }, "day_of_month": { "type": [ "integer", "null" ] }, "cron_expression": { "type": [ "string", "null" ] }, "timezone": { "type": "string" }, "next_run_at": { "type": [ "string", "null" ] }, "last_run_at": { "type": [ "string", "null" ] }, "active": { "type": "boolean" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "agent_schedule_id", "frequency", "timezone", "active", "created_at" ] } }, "required": [ "agent_trigger" ], "type": "object" } ``` --- # attachment_upload Upload Files (presigned / inline / fetch) ## Beschreibung Uploads files and returns per file an `att_…` attachment_id plus a `file_url` (short link, viewable for 15 min). Pass either form to `chat_send_message` / `task_save` / `task_comment_save` / `email_send` (`attachment_ids`) or `drive_file_upload` (`attachment_id`). Up to 10 files per call; transports may be mixed per file. **Whenever you can run curl, use the presigned transport — everything else is slow and token-hungry.** 1. PRESIGNED (preferred, ≤ 1 GB): pass exact `byte_size` and base64 MD5 `checksum`: openssl dgst -md5 -binary | openssl base64 You get `upload_url` + `headers` + a ready `curl_command`; PUT the raw bytes (2xx = done). `status` is "awaiting_upload" until then — consumers reject the handle with upload_incomplete before your PUT succeeded. 2. INLINE (≤ 1 MB decoded): pass `base64_bytes` (RFC 4648, no data-URI prefix). ONLY for clients that cannot run shell commands, or truly tiny text files. DO NOT hand-encode base64 — use a shell: openssl base64 -A -in # portable base64 -i # macOS 3. FETCH (≤ 50 MB): pass `source_url` — the server downloads the http(s) resource (25 s timeout, private hosts refused). `filename`/`mime_type` optional here (derived from the URL / response Content-Type). Finalize (attach/store) within 24 h — uploads never attached to anything are purged after that. ## Zugriff Zugriffsprofil: `basic`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `files` | array | Ja | Up to 10 files. Each item uses EXACTLY ONE transport: byte_size+checksum (presigned, preferred) \| base64_bytes (inline) \| source_url (fetch). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "files": { "type": "array", "minItems": 1, "maxItems": 10, "description": "Up to 10 files. Each item uses EXACTLY ONE transport: byte_size+checksum (presigned, preferred) | base64_bytes (inline) | source_url (fetch).", "items": { "type": "object", "properties": { "filename": { "type": "string", "description": "No path components. Required for presigned/inline; optional for source_url (derived from the URL path)." }, "mime_type": { "type": "string", "description": "Required for presigned/inline; optional for source_url (falls back to the response Content-Type)." }, "byte_size": { "type": "integer", "minimum": 1, "maximum": 1073741824, "description": "PRESIGNED: exact file size in bytes; storage rejects a PUT of any other size." }, "checksum": { "type": "string", "description": "PRESIGNED: base64 MD5 (24 chars ending '=='): openssl dgst -md5 -binary | openssl base64" }, "base64_bytes": { "type": "string", "description": "INLINE: RFC 4648 base64, whitespace tolerated, no data-URI prefix. Max 1 MB decoded." }, "source_url": { "type": "string", "description": "FETCH: http(s) URL fetched server-side. Max 50 MB, 25 s timeout, private/internal hosts refused." } } } } }, "required": [ "account_id", "files" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "files": { "type": "array", "items": { "type": "object", "properties": { "attachment_id": { "type": "string", "description": "Blob prefix id (att_…) — one of the two handle forms." }, "filename": { "type": "string" }, "transport": { "type": "string", "enum": [ "presigned", "inline", "fetch" ] }, "status": { "type": "string", "enum": [ "awaiting_upload", "stored" ], "description": "presigned entries stay awaiting_upload until your PUT succeeds." }, "file_url": { "type": "string", "format": "uri", "description": "Short view link (/f/att_…) — the other handle form; browser-openable for 15 min." }, "file_url_expires_at": { "type": "string", "format": "date-time" }, "mime_type": { "type": "string" }, "byte_size": { "type": "integer" }, "upload_url": { "type": "string", "format": "uri", "description": "presigned only: PUT target." }, "headers": { "type": "object", "additionalProperties": { "type": "string" }, "description": "presigned only: send these exact headers with the PUT." }, "curl_command": { "type": "string", "description": "presigned only: ready-to-run PUT." }, "upload_url_expires_at": { "type": "string", "format": "date-time", "description": "presigned only." } }, "required": [ "attachment_id", "filename", "transport", "status", "file_url", "file_url_expires_at", "mime_type", "byte_size" ] } } }, "required": [ "files" ], "type": "object" } ``` --- # calendar_event_copy Copy Calendar Event ## Beschreibung Copy one visible event into a writable calendar in the same account. Creates a single event, without guests or Google Meet. A stable request_id makes retries idempotent. Both calendars must be available in the current workspace. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `destination_calendar_id` | string | Ja | | | `request_id` | string | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "destination_calendar_id": { "type": "string" }, "request_id": { "type": "string", "minLength": 8, "maxLength": 100 } }, "required": [ "account_id", "calendar_id", "event_id", "destination_calendar_id", "request_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_delete Delete Calendar Event ## Beschreibung Delete one event from a calendar you can edit. Google events are deleted there too, without invitation emails. Requires the current version from a prior read. For Google series, this is the default; explicit all scope deletes the master series and requires its current series version. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `expected_version` | integer | Ja | | | `series_scope` | string | Nein | Series deletion scope. Google and native calendars support this, all and future. Google future splits reset following exceptions. | | `expected_series_version` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "expected_version": { "type": "integer", "minimum": 0 }, "series_scope": { "type": "string", "enum": [ "this", "all", "future" ], "description": "Series deletion scope. Google and native calendars support this, all and future. Google future splits reset following exceptions." }, "expected_series_version": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "calendar_id", "event_id", "expected_version" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "deleted": { "type": "boolean" }, "event_id": { "type": "string" } }, "required": [ "deleted", "event_id" ], "type": "object" } ``` --- # calendar_event_get Get Calendar Event ## Beschreibung Read one event from an explicitly permitted calendar. Returns the version required to update or delete safely. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | Event prefix ID (evt_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string", "description": "Event prefix ID (evt_…)." } }, "required": [ "account_id", "calendar_id", "event_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_invite Manage Calendar Guests and Send Invitations ## Beschreibung Replace guests of an oona or Google event you organize and send invitation updates. This sends external email. Create an event with calendar_event_save first, then read its current version. Pass every desired guest email; [] removes guests and sends cancellations. Existing guests' RSVP is preserved. Use all for a complete series with its current series version. Workspace calendar write access and this separate tool grant are required. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `expected_version` | integer | Ja | | | `guests` | array | Ja | | | `series_scope` | string | Nein | | | `expected_series_version` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "expected_version": { "type": "integer", "minimum": 0 }, "guests": { "type": "array", "maxItems": 200, "items": { "type": "string", "maxLength": 254 } }, "series_scope": { "type": "string", "enum": [ "this", "all", "future" ] }, "expected_series_version": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "calendar_id", "event_id", "expected_version", "guests" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_list List Calendar Events ## Beschreibung List cached events overlapping a time range of at most 62 days. Use ISO 8601 timestamps with explicit UTC offsets. Google calendars sync in the background; last_synced_at states freshness. Use calendar_sync when the requested range is not synchronized or freshness is insufficient. All-day end_on is exclusive. Pagination uses an offset and returns has_more. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | Calendar prefix ID (cal_…). | | `from` | string | Ja | | | `to` | string | Ja | | | `offset` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string", "description": "Calendar prefix ID (cal_…)." }, "from": { "type": "string" }, "to": { "type": "string" }, "offset": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "calendar_id", "from", "to" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "events": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "has_more": { "type": "boolean" }, "next_offset": { "type": [ "integer", "null" ] }, "last_synced_at": { "type": [ "string", "null" ] }, "sync_error": { "type": [ "string", "null" ] }, "range_synchronized": { "type": "boolean" }, "sync_window_start_at": { "type": [ "string", "null" ] }, "sync_window_end_at": { "type": [ "string", "null" ] } }, "required": [ "events", "has_more", "range_synchronized" ], "type": "object" } ``` --- # calendar_event_move Move Calendar Event ## Beschreibung Move an event between writable calendars in the current account/workspace. Native calendars support individual recurring occurrences; Google supports standalone organizer events between calendars on the same connected Google account. Google may notify guests of the organizer change. Requires the current event version. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `destination_calendar_id` | string | Ja | | | `expected_version` | integer | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "destination_calendar_id": { "type": "string" }, "expected_version": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "calendar_id", "event_id", "destination_calendar_id", "expected_version" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_reminders_set Set Calendar Event Alerts ## Beschreibung Change only the personal alerts on this calendar's event copy, including an external Google invitation whose title and times cannot be edited. Requires calendar write access and the current event version. Changes this occurrence only; organizer fields and other guests' alerts stay unchanged. Up to five popup alerts, or Google email alerts; useDefault true uses Google calendar defaults, false with overrides [] removes alerts. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `expected_version` | integer | Ja | | | `reminders` | object | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "expected_version": { "type": "integer", "minimum": 0 }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } } }, "required": [ "account_id", "calendar_id", "event_id", "expected_version", "reminders" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_respond Respond to Calendar Invitation ## Beschreibung Accept, tentatively accept, or decline an oona or Google invitation as the calendar participant. Sends the response to the organizer. Requires calendar write access and the version returned by calendar_event_get. Email-derived invitations additionally require mailbox send access; configured email confirmation returns a review link. Native recurring requests respond to the series; Google changes only this occurrence. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Ja | | | `response` | string | Ja | | | `expected_version` | integer | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "response": { "type": "string", "enum": [ "accepted", "tentative", "declined" ] }, "expected_version": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "calendar_id", "event_id", "response", "expected_version" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] }, "confirmation_required": { "type": "boolean" }, "review_url": { "type": "string" } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_event_save Create or Update Calendar Event ## Beschreibung Create or fully update an event in a calendar you can edit. Creation requires a stable request_id (8–100 characters); reuse it when retrying to avoid duplicates. Updates require event_id and expected_version from a prior read. Supply full event fields; omitted description/location are cleared. For all-day events, use start_on/end_on dates, with end_on exclusive. Timed events require starts_at/ends_at with UTC offsets. Google writes default to this occurrence; explicit all scope updates the master series. Writes never send invitations and do not edit sharing or attendees. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `event_id` | string | Nein | | | `request_id` | string | Nein | | | `expected_version` | integer | Nein | | | `google_meet` | boolean | Nein | Optionally create a Google Meet on a supported Google calendar. Existing meetings are preserved. | | `reminders` | object | Nein | Optional personal alerts. Omit to preserve. Set useDefault false and overrides [] to remove; up to five popup alerts (also in the owner's oona Inbox) or Google email alerts. Google defaults are available on Google calendars only. | | `recurrence` | object | Nein | oona or Google calendar repeat rule. Weekdays use ISO Monday=1 through Sunday=7. Omit on update to retain the existing rule. Use frequency none to stop repeating with all/future scope. | | `series_scope` | string | Nein | Edit this occurrence or all events; Google and native calendars support this and following events; Google future splits reset following exceptions. Other individually edited/cancelled dates are preserved for all. | | `expected_series_version` | integer | Nein | Required for all/future operations, from a fresh event read. | | `title` | string | Ja | | | `description` | string | Nein | | | `location` | string | Nein | | | `time_zone` | string | Nein | | | `all_day` | boolean | Nein | | | `start_on` | string | Nein | | | `end_on` | string | Nein | | | `starts_at` | string | Nein | | | `ends_at` | string | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "event_id": { "type": "string" }, "request_id": { "type": "string", "minLength": 8, "maxLength": 100 }, "expected_version": { "type": "integer", "minimum": 0 }, "google_meet": { "type": "boolean", "description": "Optionally create a Google Meet on a supported Google calendar. Existing meetings are preserved." }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } }, "description": "Optional personal alerts. Omit to preserve. Set useDefault false and overrides [] to remove; up to five popup alerts (also in the owner's oona Inbox) or Google email alerts. Google defaults are available on Google calendars only." }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } }, "description": "oona or Google calendar repeat rule. Weekdays use ISO Monday=1 through Sunday=7. Omit on update to retain the existing rule. Use frequency none to stop repeating with all/future scope." }, "series_scope": { "type": "string", "enum": [ "this", "all", "future" ], "description": "Edit this occurrence or all events; Google and native calendars support this and following events; Google future splits reset following exceptions. Other individually edited/cancelled dates are preserved for all." }, "expected_series_version": { "type": "integer", "minimum": 0, "description": "Required for all/future operations, from a fresh event read." }, "title": { "type": "string", "maxLength": 500 }, "description": { "type": "string", "maxLength": 50000 }, "location": { "type": "string", "maxLength": 1000 }, "time_zone": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": "string" }, "end_on": { "type": "string" }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" } }, "required": [ "account_id", "calendar_id", "title" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "event": { "type": "object", "properties": { "id": { "type": "string" }, "calendar_id": { "type": "string" }, "title": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "location": { "type": [ "string", "null" ] }, "starts_at": { "type": "string" }, "ends_at": { "type": "string" }, "all_day": { "type": "boolean" }, "start_on": { "type": [ "string", "null" ] }, "end_on": { "type": [ "string", "null" ] }, "time_zone": { "type": "string" }, "version": { "type": "integer" }, "google_meet_url": { "type": [ "string", "null" ] }, "conference_status": { "type": [ "string", "null" ] }, "reminders": { "type": "object", "properties": { "useDefault": { "type": "boolean" }, "overrides": { "type": "array", "maxItems": 5, "items": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "popup", "email" ] }, "minutes": { "type": "integer", "minimum": 0, "maximum": 40320 } }, "required": [ "method", "minutes" ] } } } }, "recurrence": { "type": "object", "properties": { "frequency": { "type": "string", "enum": [ "none", "daily", "weekly", "monthly", "yearly" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 99 }, "weekdays": { "type": "array", "maxItems": 7, "items": { "type": "integer", "minimum": 1, "maximum": 7 } }, "monthly_mode": { "type": "string", "enum": [ "date", "weekday", "last_weekday", "last_day" ] }, "ends_on": { "type": "string" }, "count": { "type": "integer", "minimum": 1, "maximum": 1000 } } }, "series_id": { "type": [ "string", "null" ] }, "series_version": { "type": [ "integer", "null" ] }, "google_recurrence": { "type": "array", "items": { "type": "string" }, "description": "Original Google RRULE/EXDATE/RDATE entries; preserved when recurrence is omitted on updates. Read the event directly for a fresh series version." }, "invitation": { "type": "boolean" }, "response_status": { "type": [ "string", "null" ] }, "organizer": { "type": [ "string", "null" ] }, "guests": { "type": "array", "items": { "type": "object", "properties": { "email": { "type": "string" }, "displayName": { "type": "string" }, "responseStatus": { "type": "string" }, "optional": { "type": "boolean" }, "organizer": { "type": "boolean" }, "self": { "type": "boolean" } } } }, "can_manage_guests": { "type": "boolean" }, "can_edit_reminders": { "type": "boolean" }, "can_respond": { "type": "boolean" }, "recurring_occurrence": { "type": "boolean" }, "writable": { "type": "boolean" } }, "required": [ "id", "calendar_id", "title", "starts_at", "ends_at", "all_day", "time_zone", "version", "invitation", "can_respond", "recurring_occurrence", "writable" ] } }, "required": [ "event" ], "type": "object" } ``` --- # calendar_list List Calendars ## Beschreibung List your own and workspace-shared calendars in one account. Agent calls only see calendars shared with their authenticated workspace. Use cal_ IDs with event tools. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "calendars": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "provider": { "type": "string", "enum": [ "local", "google" ] }, "time_zone": { "type": "string" }, "writable": { "type": "boolean" }, "last_synced_at": { "type": [ "string", "null" ] }, "sync_error": { "type": [ "string", "null" ] } }, "required": [ "id", "name", "provider", "time_zone", "writable" ] } } }, "required": [ "calendars" ], "type": "object" } ``` --- # calendar_project_tasks_list Read Project Workload on a Workspace Calendar ## Beschreibung Read live tasks from projects displayed on a shared workspace calendar. Both calendar and project/task access are required. Workspace agents are restricted to their authenticated workspace. from/to are YYYY-MM-DD, to is exclusive, maximum 62 days. Task due_on is inclusive. A single date is a marker; undated_count counts tasks with neither date. Peak counts simultaneous open tasks, never working hours. Completed tasks are excluded by default; canceled/archived work is always excluded. Up to 1000 matching tasks contribute to workload; truncated explicitly marks incomplete totals. Page through these tasks with offset (200/page), or narrow dates/assignee if truncated. Use existing task tools to change the originals. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `workspace_id` | string | Ja | | | `calendar_id` | string | Ja | | | `from` | string | Ja | | | `to` | string | Ja | | | `assignee_id` | string | Nein | user_ prefix or unassigned; omit for everyone. | | `include_completed` | boolean | Nein | | | `offset` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "workspace_id": { "type": "string" }, "calendar_id": { "type": "string" }, "from": { "type": "string" }, "to": { "type": "string" }, "assignee_id": { "type": "string", "description": "user_ prefix or unassigned; omit for everyone." }, "include_completed": { "type": "boolean" }, "offset": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "workspace_id", "calendar_id", "from", "to" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "projects": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] } }, "tasks": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "title": { "type": "string" }, "project_id": { "type": "string" }, "assignee_id": { "type": [ "string", "null" ] }, "start_on": { "type": [ "string", "null" ] }, "due_on": { "type": [ "string", "null" ] }, "status": { "type": [ "string", "null" ] } }, "required": [ "id", "key", "title", "project_id", "assignee_id", "start_on", "due_on", "status" ] } }, "people": { "type": "array", "items": { "type": "object", "properties": { "user_id": { "type": [ "string", "null" ] }, "name": { "type": "string" }, "task_count": { "type": "integer" }, "peak_open_tasks": { "type": "integer" } }, "required": [ "user_id", "name", "task_count", "peak_open_tasks" ] } }, "undated_count": { "type": "integer" }, "truncated": { "type": "boolean" }, "has_more": { "type": "boolean" }, "next_offset": { "type": [ "integer", "null" ] } }, "required": [ "projects", "tasks", "people", "undated_count", "truncated", "has_more", "next_offset" ], "type": "object" } ``` --- # calendar_projects_set Choose Projects for a Workspace Calendar ## Beschreibung Replace the projects displayed on an existing shared workspace calendar. Human calendar owners and workspace managers only. Project IDs must belong to this workspace. An empty list removes all project overlays. This changes the workspace's shared display setting; it does not create calendar events, grant project access or write to Google. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `workspace_id` | string | Ja | | | `calendar_id` | string | Ja | | | `project_ids` | array | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "workspace_id": { "type": "string" }, "calendar_id": { "type": "string" }, "project_ids": { "type": "array", "items": { "type": "string" } } }, "required": [ "account_id", "workspace_id", "calendar_id", "project_ids" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "calendar_id": { "type": "string" }, "workspace_id": { "type": "string" }, "project_ids": { "type": "array", "items": { "type": "string" } } }, "required": [ "calendar_id", "workspace_id", "project_ids" ], "type": "object" } ``` --- # calendar_request_list List Calendar Invitations ## Beschreibung List incoming oona and email calendar invitations, including response status, version and linked event. Agent calls see only requests from mailboxes or calendars shared with their authenticated workspace. No import or response is performed. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `pending_only` | boolean | Nein | | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "pending_only": { "type": "boolean" }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "requests": { "type": "array", "items": { "type": "object" } } }, "required": [ "requests" ], "type": "object" } ``` --- # calendar_request_respond Respond to an Incoming Calendar Request ## Beschreibung Accept, tentatively accept or decline an incoming oona/email invitation. This sends a response. For Yes/Maybe choose a writable oona calendar owned by the invited person; an existing linked Google event is reused. Email requests require mailbox sending access and both features. Agents need the mailbox and destination calendar shared with the same authenticated workspace. If email-send confirmation is configured, returns a review URL without changing or sending anything. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `request_id` | string | Ja | | | `calendar_id` | string | Nein | | | `response` | string | Ja | | | `expected_version` | integer | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "request_id": { "type": "string" }, "calendar_id": { "type": "string" }, "response": { "type": "string", "enum": [ "accepted", "tentative", "declined" ] }, "expected_version": { "type": "integer", "minimum": 0 } }, "required": [ "account_id", "request_id", "response", "expected_version" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "request": { "type": "object" }, "confirmation_required": { "type": "boolean" }, "review_url": { "type": "string" } }, "type": "object" } ``` --- # calendar_share Share an Owned Calendar with a Workspace ## Beschreibung Set or revoke workspace access to a calendar you own. Human owners only: agents cannot grant themselves resource access. Permission none revokes this workspace, read permits viewing, write permits editing. Other workspace grants are unchanged. Shared calendars appear under the workspace, never in another member's personal Calendar. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `workspace_id` | string | Ja | | | `permission` | string | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "workspace_id": { "type": "string" }, "permission": { "type": "string", "enum": [ "none", "read", "write" ] } }, "required": [ "account_id", "calendar_id", "workspace_id", "permission" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "calendar_id": { "type": "string" }, "workspace_id": { "type": "string" }, "permission": { "type": "string" } }, "required": [ "calendar_id", "workspace_id", "permission" ], "type": "object" } ``` --- # calendar_sync Sync Google Calendar ## Beschreibung Request a Google calendar refresh for an explicit range of at most 62 days, using ISO 8601 timestamps with UTC offsets. Requires access to that calendar. Returns immediately; use calendar_event_list afterward to check last_synced_at and range_synchronized. Local calendars need no synchronization. ## Zugriff Zugriffsprofil: `gated`. Module: `calendar`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `calendar_id` | string | Ja | | | `from` | string | Ja | | | `to` | string | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "calendar_id": { "type": "string" }, "from": { "type": "string" }, "to": { "type": "string" } }, "required": [ "account_id", "calendar_id", "from", "to" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "queued": { "type": "boolean" }, "calendar_id": { "type": "string" }, "last_synced_at": { "type": [ "string", "null" ] } }, "required": [ "queued", "calendar_id" ], "type": "object" } ``` --- # chat_add_reaction Add Chat Reaction ## Beschreibung Adds an emoji reaction to a chat message. Idempotent — retrying the same `(message, user, emoji)` triple returns `already_existed: true` instead of erroring. A single user may stack multiple different emojis on the same message. Response carries the full current reaction list, so you don't need a follow-up `chat_get_messages`. Channel membership is required; admin/employer do NOT override (same rule as `chat_send_message`). ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `channel_id` | string | Ja | Channel prefix ID (e.g., chan_xyz789) — must be a channel you can post in. | | `message_id` | string | Ja | Message prefix ID (e.g., msg_abc123) of the target. Both roots and replies accept reactions. | | `emoji` | string | Ja | Unicode emoji (e.g., 🔥, 👍, ✅). Do not escape the string — send literal Unicode, not \u1f525 sequences. Up to 32 chars so modifier sequences (skin tone, ZWJ) still fit. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "channel_id": { "type": "string", "description": "Channel prefix ID (e.g., chan_xyz789) — must be a channel you can post in." }, "message_id": { "type": "string", "description": "Message prefix ID (e.g., msg_abc123) of the target. Both roots and replies accept reactions." }, "emoji": { "type": "string", "minLength": 1, "maxLength": 32, "description": "Unicode emoji (e.g., 🔥, 👍, ✅). Do not escape the string — send literal Unicode, not \\u1f525 sequences. Up to 32 chars so modifier sequences (skin tone, ZWJ) still fit." } }, "required": [ "account_id", "channel_id", "message_id", "emoji" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "message_id": { "type": "string" }, "emoji": { "type": "string" }, "already_existed": { "type": "boolean", "description": "True when the reaction already existed before this call — idempotent retry confirmation." }, "reactions": { "type": "array", "description": "Complete current reaction list for the message after this call, ordered by created_at ASC.", "items": { "type": "object", "properties": { "emoji": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": "string" }, "handle": { "type": "string" }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "emoji", "user", "created_at" ] } } }, "required": [ "message_id", "emoji", "already_existed", "reactions" ], "type": "object" } ``` --- # chat_channel_save Create, Update or Archive Chat Channel ## Beschreibung Admins and employers manage public/private channels they can access. Omit id to create; name and workspace_id are required and channel_type defaults to public. The creator joins as a channel admin. Pass a chan_… id to change only supplied fields. Set archived: true to archive or false to restore, preserving messages and memberships. Employers need workspace access; private channels also require channel membership or workspace-manager access. Changing public/private on an existing channel requires an account admin or workspace manager. member_ids replaces a private channel's roster, retaining the creator and acting user if already members. Members must be active and have workspace access. Omit member_ids to preserve the roster; [] removes other members. Restore an archived channel before changing its roster. Public-channel agents are assigned through workspace settings. Agents in private rosters must already be deployed to the workspace. Channels cannot move workspace here. Restore an archived workspace before managing its channels. DMs use chat_start_dm. Discover IDs and archived channels with chat_list_channels. ## Zugriff Zugriffsprofil: `gated`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `id` | string | Nein | Channel prefix ID (chan_…). Omit to create. | | `workspace_id` | string | Nein | Required on create: workspace prefix ID (wsp_…) or key. Immutable on update. | | `name` | string | Nein | Required on create; at most 100 characters. | | `description` | string / null | Nein | Plain text. Null or an empty string clears it. | | `channel_type` | string | Nein | | | `archived` | boolean | Nein | Existing channel only: true archives, false restores. | | `member_ids` | array | Nein | Private channels only: complete desired roster of user_… IDs or @handles. Creator and existing acting member are retained. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "id": { "type": "string", "description": "Channel prefix ID (chan_…). Omit to create." }, "workspace_id": { "type": "string", "description": "Required on create: workspace prefix ID (wsp_…) or key. Immutable on update." }, "name": { "type": "string", "description": "Required on create; at most 100 characters." }, "description": { "type": [ "string", "null" ], "description": "Plain text. Null or an empty string clears it." }, "channel_type": { "type": "string", "enum": [ "public", "private" ] }, "archived": { "type": "boolean", "description": "Existing channel only: true archives, false restores." }, "member_ids": { "type": "array", "items": { "type": "string" }, "description": "Private channels only: complete desired roster of user_… IDs or @handles. Creator and existing acting member are retained." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "channel": { "type": "object", "properties": { "id": { "type": "string", "description": "Channel prefix ID (chan_…) — pass to chat_get_messages / chat_send_message." }, "workspace_id": { "type": [ "string", "null" ], "description": "Null for account-wide DMs." }, "name": { "type": "string" }, "channel_type": { "type": "string", "enum": [ "public", "private", "direct" ] }, "description": { "type": [ "string", "null" ] }, "is_archived": { "type": "boolean" }, "last_message_at": { "type": [ "string", "null" ], "description": "ISO 8601 timestamp; null if no messages yet." }, "is_member": { "type": "boolean", "description": "Whether the caller is a member of this channel." }, "member_ids": { "type": "array", "items": { "type": "string" }, "description": "Current roster as user_… prefix IDs." } }, "required": [ "id", "workspace_id", "name", "channel_type", "is_archived", "is_member" ] } }, "required": [ "channel" ], "type": "object" } ``` --- # chat_get_messages Get Chat Messages ## Beschreibung Reads messages from a chat channel or DM. Two response shapes: - Default ("channel view"): root threads with their replies nested underneath each root. Sorted oldest-first within the returned window — `messages[last]` is the newest. - Thread view (`parent_message_id` set): flat list of replies, no nesting (oona supports one thread level). `limit` (1-200, default 50) caps ROOT count — replies always come along in full, even outside the time filter (context preserved). `before_id` pages backwards by root id. See Server Instructions for date-filter semantics. Attachments + reactions inline on every message (bulk-loaded). `download_url` is signed + 30-min valid. Access: the channel must be inside one of the caller's workspaces. Public channels and joined private/DM channels are readable; account admins may read every channel in the tenant. ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `channel_id` | string | Ja | Channel prefix ID (e.g., chan_xyz789) from chat_list_channels. | | `limit` | integer | Nein | Max ROOT threads (replies are always fully loaded). Default 50. | | `before_id` | string | Nein | Paginate backwards: pass the oldest ROOT id from your previous response (msg_…) to get the next older page. Ignored in thread view. | | `since` | string | Nein | Only return roots with created_at >= this ISO 8601 timestamp (e.g., 2026-04-21T00:00:00Z). Ignored in thread view. | | `until` | string | Nein | Only return roots with created_at < this ISO 8601 timestamp. Ignored in thread view. | | `start_date` | string | Nein | Calendar-day lower bound on root created_at (beginning of day in UTC). Use for single-day or multi-day ranges. Ignored in thread view. | | `end_date` | string | Nein | Calendar-day upper bound (end of day). Defaults to start_date when only start_date is given — pair them for a range. Ignored in thread view. | | `parent_message_id` | string | Nein | Switch to flat thread view: return only replies to this root (msg_…). Time filters and limit are ignored. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "channel_id": { "type": "string", "description": "Channel prefix ID (e.g., chan_xyz789) from chat_list_channels." }, "limit": { "type": "integer", "minimum": 1, "maximum": 200, "description": "Max ROOT threads (replies are always fully loaded). Default 50." }, "before_id": { "type": "string", "description": "Paginate backwards: pass the oldest ROOT id from your previous response (msg_…) to get the next older page. Ignored in thread view." }, "since": { "type": "string", "format": "date-time", "description": "Only return roots with created_at >= this ISO 8601 timestamp (e.g., 2026-04-21T00:00:00Z). Ignored in thread view." }, "until": { "type": "string", "format": "date-time", "description": "Only return roots with created_at < this ISO 8601 timestamp. Ignored in thread view." }, "start_date": { "type": "string", "format": "date", "description": "Calendar-day lower bound on root created_at (beginning of day in UTC). Use for single-day or multi-day ranges. Ignored in thread view." }, "end_date": { "type": "string", "format": "date", "description": "Calendar-day upper bound (end of day). Defaults to start_date when only start_date is given — pair them for a range. Ignored in thread view." }, "parent_message_id": { "type": "string", "description": "Switch to flat thread view: return only replies to this root (msg_…). Time filters and limit are ignored." } }, "required": [ "account_id", "channel_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "channel": { "type": "object", "properties": { "id": { "type": "string", "description": "Channel prefix ID (chan_…)." }, "name": { "type": "string" } }, "required": [ "id", "name" ] }, "messages": { "type": "array", "description": "Channel view: roots with `replies` nested. Thread view: flat list of replies (no `replies` field).", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Message prefix ID (msg_…)." }, "body": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" }, "parent_message_id": { "type": [ "string", "null" ], "description": "null for roots; parent root's msg_… for replies." }, "replies_count": { "type": "integer" }, "reactions": { "type": "array", "description": "Flat list of all emoji reactions on this message, ordered by created_at ASC. Group by `emoji` client-side for counts.", "items": { "type": "object", "properties": { "emoji": { "type": "string", "description": "Unicode emoji." }, "user": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "emoji", "user", "created_at" ] } }, "attachments": { "type": "array", "description": "Files attached to this message, ordered by upload time. download_url is a signed URL valid for 30 minutes — possession is the capability.", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Blob prefix ID (att_…)." }, "filename": { "type": "string" }, "mime_type": { "type": "string" }, "byte_size": { "type": "integer" }, "download_url": { "type": "string", "format": "uri" }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "filename", "mime_type", "byte_size", "download_url", "created_at" ] } }, "replies": { "type": "array", "description": "Only present in channel view, on root messages.", "items": { "type": "object" } } }, "required": [ "id", "body", "user", "created_at", "parent_message_id", "replies_count", "reactions", "attachments" ] } } }, "required": [ "channel", "messages" ], "type": "object" } ``` --- # chat_list_channels List Chat Channels ## Beschreibung Lists chat channels the caller can see: public/private channels inside their workspaces, public channels, private channels the caller joined (admins also see every private one), and the caller's DMs. Archived channels are hidden unless `include_archived: true`. Ordered public → private → direct, then alphabetically by name within each group. Note: DMs appear here only if a DM was already started with that partner — use `chat_start_dm` to initiate a new one. Admins and employers can create, edit, archive and restore shared channels with chat_channel_save, subject to workspace/channel access. ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). Discover via account_list. | | `workspace_id` | string | Nein | Optional workspace prefix ID (wsp_…) or key. When present, returns only public/private channels in that workspace; account-wide DMs are omitted. | | `include_archived` | boolean | Nein | Include archived channels (hidden from the web sidebar). Default false. Set true to search an archived channel by name. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123). Discover via account_list." }, "workspace_id": { "type": "string", "description": "Optional workspace prefix ID (wsp_…) or key. When present, returns only public/private channels in that workspace; account-wide DMs are omitted." }, "include_archived": { "type": "boolean", "description": "Include archived channels (hidden from the web sidebar). Default false. Set true to search an archived channel by name." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "channels": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Channel prefix ID (chan_…) — pass to chat_get_messages / chat_send_message." }, "workspace_id": { "type": [ "string", "null" ], "description": "Null for account-wide DMs." }, "name": { "type": "string" }, "channel_type": { "type": "string", "enum": [ "public", "private", "direct" ] }, "description": { "type": [ "string", "null" ] }, "is_archived": { "type": "boolean" }, "last_message_at": { "type": [ "string", "null" ], "description": "ISO 8601 timestamp; null if no messages yet." }, "is_member": { "type": "boolean", "description": "Whether the caller is a member of this channel." } }, "required": [ "id", "workspace_id", "name", "channel_type", "is_archived", "is_member" ] } } }, "required": [ "channels" ], "type": "object" } ``` --- # chat_remove_reaction Remove Chat Reaction ## Beschreibung Removes the caller's own emoji reaction from a chat message. No `user_id` param — moderation of others' reactions stays in the web UI. Error if the caller hasn't reacted with that emoji. Response echoes the remaining reactions on the message. ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `channel_id` | string | Ja | Channel prefix ID (e.g., chan_xyz789). | | `message_id` | string | Ja | Message prefix ID (e.g., msg_abc123) of the target. | | `emoji` | string | Ja | The exact emoji string you added (Unicode — same value you passed to chat_add_reaction). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "channel_id": { "type": "string", "description": "Channel prefix ID (e.g., chan_xyz789)." }, "message_id": { "type": "string", "description": "Message prefix ID (e.g., msg_abc123) of the target." }, "emoji": { "type": "string", "minLength": 1, "maxLength": 32, "description": "The exact emoji string you added (Unicode — same value you passed to chat_add_reaction)." } }, "required": [ "account_id", "channel_id", "message_id", "emoji" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "message_id": { "type": "string" }, "emoji": { "type": "string" }, "removed": { "type": "boolean" }, "reactions": { "type": "array", "description": "Reactions remaining on the message after removal, ordered by created_at ASC.", "items": { "type": "object", "properties": { "emoji": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": "string" }, "handle": { "type": "string" }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "emoji", "user", "created_at" ] } } }, "required": [ "message_id", "emoji", "removed", "reactions" ], "type": "object" } ``` --- # chat_send_message Send Chat Message ## Beschreibung Posts a message to a chat channel or DM — optionally with file attachments (images, PDFs, video, any MIME type). Synchronous: hits the DB and Turbo-broadcasts to members before returning. - Body is GFM Markdown, ≤ 32 KB. `@handle` mentions resolve against active account members; response's `mentions` echoes what mapped (resolve handles via `account_list_users`). - `attachment_ids` entries come from `attachment_upload` — pass the `att_…` id or the `file_url`, either works. Body becomes optional when at least one attachment is present. - `parent_message_id` threads the post (single-level only). - Not idempotent — retries create duplicate rows. - Workspace members can post to public channels and their threads without joining the channel. Private channels and DMs require channel membership; account admins retain tenant-wide access. ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `channel_id` | string | Ja | Channel prefix ID (e.g., chan_xyz789) from chat_list_channels. | | `body` | string | Nein | Markdown content. Do not escape the string — use literal newlines and special characters, not escape sequences. Supports GFM plus @handle mentions (resolved against active account members). Max 32 KB. Optional when attachment_ids is present. | | `parent_message_id` | string | Nein | Thread this reply under this root message's prefix ID (msg_…). Single-level threading only — replies to replies are rejected. | | `attachment_ids` | array | Nein | Attachment handles from attachment_upload — att_… ids or file_urls, mixed freely. Each blob may only be attached to one chat message. Body may be empty when at least one attachment is present. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "channel_id": { "type": "string", "description": "Channel prefix ID (e.g., chan_xyz789) from chat_list_channels." }, "body": { "type": "string", "maxLength": 32768, "description": "Markdown content. Do not escape the string — use literal newlines and special characters, not escape sequences. Supports GFM plus @handle mentions (resolved against active account members). Max 32 KB. Optional when attachment_ids is present." }, "parent_message_id": { "type": "string", "description": "Thread this reply under this root message's prefix ID (msg_…). Single-level threading only — replies to replies are rejected." }, "attachment_ids": { "type": "array", "maxItems": 20, "items": { "type": "string" }, "description": "Attachment handles from attachment_upload — att_… ids or file_urls, mixed freely. Each blob may only be attached to one chat message. Body may be empty when at least one attachment is present." } }, "required": [ "account_id", "channel_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "message": { "type": "object", "properties": { "id": { "type": "string", "description": "Message prefix ID (msg_…)." }, "body": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" }, "parent_message_id": { "type": [ "string", "null" ] }, "replies_count": { "type": "integer" }, "mentions": { "type": "object", "description": "Server-side resolution of @handle tokens in body — confirms what you intended actually mapped.", "properties": { "resolved_users": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "handle": { "type": "string" }, "name": { "type": "string" } } } }, "mention_all": { "type": "boolean", "description": "True when `@all` was used." } } }, "reactions": { "type": "array", "description": "Always an empty array on a freshly-sent message — here for shape parity with chat_get_messages.", "items": { "type": "object" } }, "attachments": { "type": "array", "description": "Files attached to this message (via attachment_ids). Same shape as chat_get_messages.", "items": { "type": "object", "properties": { "id": { "type": "string" }, "filename": { "type": "string" }, "mime_type": { "type": "string" }, "byte_size": { "type": "integer" }, "download_url": { "type": "string", "format": "uri", "description": "Signed URL, valid 30 minutes." }, "created_at": { "type": "string", "format": "date-time" } } } } }, "required": [ "id", "body", "user", "created_at", "parent_message_id", "replies_count", "mentions", "reactions", "attachments" ] } }, "required": [ "message" ], "type": "object" } ``` --- # chat_start_dm Start Direct Message ## Beschreibung Find-or-create the account-wide 1-on-1 DM channel with another internal account member. A second call with the same participant returns the same `chan_…` id and un-archives a dormant DM (matching the web UI's "New DM" picker). Use when `chat_list_channels` doesn't already show a DM with the partner. Both participants must be active internal members of the same account; guests cannot create, see, or receive DMs. DMing yourself is rejected. `name` on the returned channel is an opaque internal id — render the partner's handle in UI copy instead. ## Zugriff Zugriffsprofil: `basic`. Module: `chat`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `user_id` | string | Ja | Partner's prefix ID (user_…), @handle, or bare handle (e.g., 'kurth' or '@kurth'). Must be an active internal member of the account. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "user_id": { "type": "string", "description": "Partner's prefix ID (user_…), @handle, or bare handle (e.g., 'kurth' or '@kurth'). Must be an active internal member of the account." } }, "required": [ "account_id", "user_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "channel": { "type": "object", "properties": { "id": { "type": "string", "description": "Channel prefix ID (chan_…) — pass to chat_send_message / chat_get_messages." }, "workspace_id": { "type": [ "string", "null" ], "description": "Always null for account-wide DMs." }, "name": { "type": "string", "description": "Opaque internal name; render the partner's handle in UI copy." }, "channel_type": { "type": "string", "enum": [ "direct" ] }, "description": { "type": [ "string", "null" ] }, "is_archived": { "type": "boolean" }, "last_message_at": { "type": [ "string", "null" ], "format": "date-time" }, "is_member": { "type": "boolean" } }, "required": [ "id", "workspace_id", "name", "channel_type", "is_archived", "is_member" ] } }, "required": [ "channel" ], "type": "object" } ``` --- # cycle_get Get Cycle ## Beschreibung Fetches a single cycle by prefix id (`cyc_…`). Returns the cycle's window, status, bucket (current / upcoming / past relative to today), the owning workspace, and progress stats — total tasks, completed count, completion ratio. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Cycle prefix ID (cyc_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Cycle prefix ID (cyc_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "cycle": { "type": "object", "properties": { "id": { "type": "string" }, "number": { "type": "integer" }, "name": { "type": [ "string", "null" ] }, "description": { "type": [ "string", "null" ] }, "status": { "type": "string", "enum": [ "planned", "active", "completed", "cancelled" ] }, "starts_on": { "type": "string", "format": "date" }, "ends_on": { "type": "string", "format": "date" }, "bucket": { "type": "string", "enum": [ "current", "upcoming", "past" ] }, "workspace": { "type": "object" }, "progress": { "type": "object", "properties": { "total_tasks": { "type": "integer" }, "completed_tasks": { "type": "integer" }, "completion_ratio": { "type": "number", "description": "0.0 to 1.0; 0.0 when there are no tasks yet." } } } }, "required": [ "id", "number", "status", "starts_on", "ends_on", "bucket", "workspace", "progress" ] } }, "required": [ "cycle" ], "type": "object" } ``` --- # cycle_list List Cycles ## Beschreibung Lists cycles the caller can see. Cycles are per-workspace sprint windows with a monotonic `number` per workspace (never reused across deletions) and a `status` (planned / active / completed / cancelled). At most one cycle per workspace is `active` at a time. Filter by `workspace_id`, `status`, or `bucket` (`current` / `upcoming` / `past`, computed from today's date). Sorted by start date ascending. Archived rows are excluded. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `workspace_id` | string | Nein | Workspace prefix ID or key (e.g. ENG). | | `status` | string | Nein | | | `bucket` | string | Nein | Time-window relative to today. | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key (e.g. ENG)." }, "status": { "type": "string", "enum": [ "planned", "active", "completed", "cancelled" ] }, "bucket": { "type": "string", "enum": [ "current", "upcoming", "past" ], "description": "Time-window relative to today." }, "limit": { "type": "integer", "default": 50 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "cycles": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Cycle prefix ID (cyc_…)." }, "number": { "type": "integer", "description": "Auto-increment per workspace, monotonic across deletions." }, "name": { "type": [ "string", "null" ], "description": "Optional label; falls back to 'Cycle #'." }, "status": { "type": "string", "enum": [ "planned", "active", "completed", "cancelled" ] }, "starts_on": { "type": "string", "format": "date" }, "ends_on": { "type": "string", "format": "date" }, "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "name": { "type": "string" } } }, "bucket": { "type": "string", "enum": [ "current", "upcoming", "past" ], "description": "Computed from today's date." } }, "required": [ "id", "number", "status", "starts_on", "ends_on", "workspace", "bucket" ] } } }, "required": [ "cycles" ], "type": "object" } ``` --- # drive_activity Drive Activity Log ## Beschreibung Returns the audit log for a drive — same rows the Activity tab renders. Filter by `kinds` (an array of action strings) or `since` (ISO 8601 / relative offset). Sorted `created_at DESC`, capped at 100 rows per call. Manager only. Common action strings: `file_uploaded`, `file_downloaded`, `file_renamed`, `file_moved`, `file_trashed`, `file_restored`, `file_purged`, `file_fetched`, `folder_created`, `folder_moved`, `folder_trashed`, `folder_restored`, `bulk_zip_downloaded`, `link_created`, `link_updated`, `link_revoked`, `link_restored`, `link_downloaded`, `drive_created`, `drive_archived`, `drive_restored`. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Ja | | | `kinds` | array | Nein | Filter to these action strings only. | | `since` | string | Nein | ISO 8601, date, or relative offset (`-1d`, `-2h`). Rows older than this are dropped. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string" }, "kinds": { "type": "array", "items": { "type": "string" }, "description": "Filter to these action strings only." }, "since": { "type": "string", "description": "ISO 8601, date, or relative offset (`-1d`, `-2h`). Rows older than this are dropped." } }, "required": [ "account_id", "drive_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "drive_id": { "type": "string" }, "count": { "type": "integer" }, "events": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "action": { "type": "string" }, "actor": { "type": [ "object", "null" ], "description": "User who did it, or null for anonymous public-link downloads." }, "target_type": { "type": [ "string", "null" ] }, "target_id": { "type": [ "string", "null" ], "description": "Prefix ID of the DriveFile / DriveFolder / DriveLink if applicable." }, "payload": { "type": "object" }, "created_at": { "type": "string", "format": "date-time" } } } } }, "required": [ "drive_id", "count", "events" ], "type": "object" } ``` --- # drive_changes Track Drive changes ## Beschreibung Reads ordered file and folder changes in a Drive since a persistent cursor. Includes create, content update, rename, move, delete and restore (create with the original ID). Start with cursor 0; persist the returned cursor only after processing the page. While has_more is true, request another page with that cursor. Cursors belong to one Drive. This is polling, not a subscription. Use drive_activity for human activity/actors instead. Returns metadata only, never file contents, storage keys or signed URLs. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `drive_id` | string | Ja | Drive prefix ID (drv_…). | | `cursor` | integer | Nein | Last successfully processed cursor for this Drive; default 0. | | `limit` | integer | Nein | Page size; default 100, maximum 500. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "drive_id": { "type": "string", "description": "Drive prefix ID (drv_…)." }, "cursor": { "type": "integer", "minimum": 0, "description": "Last successfully processed cursor for this Drive; default 0." }, "limit": { "type": "integer", "minimum": 1, "maximum": 500, "description": "Page size; default 100, maximum 500." } }, "required": [ "account_id", "drive_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "drive_id": { "type": "string" }, "cursor": { "type": "integer" }, "has_more": { "type": "boolean" }, "changes": { "type": "array", "items": { "type": "object", "properties": { "sequence": { "type": "integer" }, "id": { "type": "string" }, "kind": { "type": "string", "enum": [ "file", "folder" ] }, "parent_id": { "type": [ "string", "null" ] }, "name": { "type": "string" }, "version": { "type": "integer" }, "operation": { "type": "string", "enum": [ "create", "update", "delete", "move", "rename" ] }, "deleted": { "type": "boolean" }, "size": { "type": "integer" }, "content_version": { "type": "string" } }, "required": [ "sequence", "id", "kind", "parent_id", "name", "version", "operation", "deleted" ] } } }, "required": [ "drive_id", "cursor", "has_more", "changes" ], "type": "object" } ``` --- # drive_file_content Read File (text/Markdown body) ## Beschreibung Returns the inline body of a text-family file (Markdown, plain text, log, csv, or any `text/*` MIME) as a UTF-8 string. Byte cap: 256 KB — larger files are truncated and `truncated: true` is set on the response. This is the same content path the in-app Quick-Look preview uses, minus the redcarpet HTML render. For images, PDFs, or anything binary → returns `error: unsupported_kind` and a hint to use `drive_file_get`'s download URL. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `file_id` | string | Ja | | | `max_bytes` | integer | Nein | Optional byte cap smaller than the default 256 KB. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "file_id": { "type": "string" }, "max_bytes": { "type": "integer", "minimum": 1, "description": "Optional byte cap smaller than the default 256 KB." } }, "required": [ "account_id", "file_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "content_type": { "type": [ "string", "null" ] }, "byte_size": { "type": "integer" }, "sync_version": { "type": "integer" }, "content": { "type": "string" }, "truncated": { "type": "boolean" } }, "required": [ "id", "name", "content_type", "byte_size", "sync_version", "content", "truncated" ], "type": "object" } ``` --- # drive_file_get Get File Metadata + Download URL ## Beschreibung Returns a single file's metadata plus a short-lived signed download URL (5-minute TTL, `disposition=attachment`). The URL is the same one the in-app Download button would emit, so anything that can fetch a signed Active Storage blob works. For inline preview of Markdown / text bodies, prefer `drive_file_content` — no signed-URL fetch needed. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `file_id` | string | Ja | File prefix ID (dfi_…) from drive_folder_list or drive_search. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "file_id": { "type": "string", "description": "File prefix ID (dfi_…) from drive_folder_list or drive_search." } }, "required": [ "account_id", "file_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "content_type": { "type": [ "string", "null" ] }, "byte_size": { "type": "integer" }, "sync_version": { "type": "integer" }, "folder_id": { "type": [ "string", "null" ] }, "drive_id": { "type": "string" }, "path": { "type": "string", "description": "Drive name + folder chain joined by ' / '." }, "uploaded_by": { "type": [ "object", "null" ] }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "download_url": { "type": "string", "description": "Signed Active Storage URL, 5-minute expiry, disposition=attachment." }, "has_active_share_link": { "type": "boolean" } }, "required": [ "id", "name", "content_type", "byte_size", "sync_version", "folder_id", "drive_id", "path", "uploaded_by", "created_at", "updated_at", "download_url", "has_active_share_link" ], "type": "object" } ``` --- # drive_file_save Update, Rename or Move File ## Beschreibung Renames a file (`name`) and/or moves it into another folder within the same drive (`folder_id`, null moves to root). To replace content while preserving the file ID, upload the new bytes with `attachment_upload`, then pass `attachment_id` and `base_version` from the last `drive_file_content` or `drive_file_get` read. A stale base_version returns version_conflict without changing the file; re-read the current file and merge your edits before retrying. Previous content is retained in file history and changes sync to Macs. Cross-drive moves are not supported (validation would reject them). Access: `DriveFilePolicy#update?` — editor or higher. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | File prefix ID (dfi_…). | | `name` | string | Nein | | | `folder_id` | string / null | Nein | Destination folder (dfo_…) in the SAME drive. Pass null to move to root. | | `attachment_id` | string | Nein | att_… ID or file_url from attachment_upload with replacement bytes. | | `base_version` | integer | Nein | Last-read sync_version. Required when replacing content; also accepted for rename/move. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "File prefix ID (dfi_…)." }, "name": { "type": "string", "maxLength": 255 }, "folder_id": { "type": [ "string", "null" ], "description": "Destination folder (dfo_…) in the SAME drive. Pass null to move to root." }, "attachment_id": { "type": "string", "description": "att_… ID or file_url from attachment_upload with replacement bytes." }, "base_version": { "type": "integer", "minimum": 0, "description": "Last-read sync_version. Required when replacing content; also accepted for rename/move." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "folder_id": { "type": [ "string", "null" ] }, "drive_id": { "type": "string" }, "sync_version": { "type": "integer" } }, "required": [ "id", "name", "folder_id", "drive_id", "sync_version" ], "type": "object" } ``` --- # drive_file_trash Move File to Trash ## Beschreibung Soft-deletes a file — moves it into the drive's Trash, where a Manager can restore or permanently purge it. Same behaviour as the in-app row Delete action. Content stays in Active Storage until purge. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | File prefix ID (dfi_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "File prefix ID (dfi_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "trashed": { "type": "boolean" } }, "required": [ "id", "trashed" ], "type": "object" } ``` --- # drive_file_upload Store File in a Drive ## Beschreibung Stores an uploaded file in a drive. Upload first via `attachment_upload`, then pass the returned handle here — either the `att_…` attachment_id or the `file_url`. For presigned uploads the PUT must have completed, otherwise this returns `upload_incomplete`. `filename` is the name inside the drive (used verbatim; a sibling collision auto-renames to "name (1).ext"). MIME type and byte size come from the uploaded blob. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Ja | | | `folder_id` | string / null | Nein | Destination folder (dfo_…). Omit for root. | | `filename` | string | Ja | | | `attachment_id` | string | Ja | att_… id or file_url from attachment_upload. Up to 1 GB. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string" }, "folder_id": { "type": [ "string", "null" ], "description": "Destination folder (dfo_…). Omit for root." }, "filename": { "type": "string", "minLength": 1, "maxLength": 255 }, "attachment_id": { "type": "string", "description": "att_… id or file_url from attachment_upload. Up to 1 GB." } }, "required": [ "account_id", "drive_id", "filename", "attachment_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "content_type": { "type": "string" }, "byte_size": { "type": "integer" }, "folder_id": { "type": [ "string", "null" ] }, "drive_id": { "type": "string" } }, "required": [ "id", "name", "content_type", "byte_size", "folder_id", "drive_id" ], "type": "object" } ``` --- # drive_folder_list List Folder Contents ## Beschreibung Lists the immediate children (folders + files, both live) of the given folder — or the drive's root when `folder_id` is omitted. Each row carries `kind = folder | file`, size / content_type for files, updated_at, uploader / creator. Not recursive — call again for each folder you want to descend into. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Ja | | | `folder_id` | string | Nein | Folder prefix ID (dfo_…). Omit to list the drive's root. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string" }, "folder_id": { "type": "string", "description": "Folder prefix ID (dfo_…). Omit to list the drive's root." } }, "required": [ "account_id", "drive_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "drive_id": { "type": "string" }, "folder_id": { "type": [ "string", "null" ], "description": "The folder we listed under, or null for root." }, "breadcrumb": { "type": "array", "description": "Path from root down to (but not including) the current folder, deepest last.", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } } } }, "entries": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "kind": { "type": "string", "enum": [ "folder", "file" ] }, "name": { "type": "string" }, "content_type": { "type": [ "string", "null" ], "description": "File MIME (null for folders)." }, "byte_size": { "type": [ "integer", "null" ], "description": "File size in bytes (null for folders)." }, "folder_id": { "type": [ "string", "null" ], "description": "Parent folder id — matches the request's folder_id." }, "uploaded_by": { "type": [ "object", "null" ] }, "updated_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "kind", "name", "content_type", "byte_size", "folder_id", "uploaded_by", "updated_at" ] } } }, "required": [ "drive_id", "folder_id", "breadcrumb", "entries" ], "type": "object" } ``` --- # drive_folder_save Create or Update Folder ## Beschreibung Linear-style upsert. Omit `id` to create a new folder in the given drive; pass `id` (dfo_…) to rename or move an existing one. `parent_id` picks the destination folder (omit for root). Access: create requires editor+ on the drive; update requires editor+ AND same-drive parent (Pundit `DriveFolderPolicy`). ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Nein | Drive prefix ID. Required on create; ignored on update (folder's drive is fixed). | | `id` | string | Nein | Folder prefix ID (dfo_…). Omit to create. | | `name` | string | Nein | | | `parent_id` | string / null | Nein | Parent folder prefix ID (dfo_…). Pass null to move to root. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string", "description": "Drive prefix ID. Required on create; ignored on update (folder's drive is fixed)." }, "id": { "type": "string", "description": "Folder prefix ID (dfo_…). Omit to create." }, "name": { "type": "string", "maxLength": 200 }, "parent_id": { "type": [ "string", "null" ], "description": "Parent folder prefix ID (dfo_…). Pass null to move to root." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "parent_id": { "type": [ "string", "null" ] }, "drive_id": { "type": "string" }, "created": { "type": "boolean" } }, "required": [ "id", "name", "parent_id", "drive_id", "created" ], "type": "object" } ``` --- # drive_folder_trash Move Folder to Trash ## Beschreibung Soft-deletes a folder and its entire subtree (all descendant folders + files). Restore via the in-app Trash tab. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Folder prefix ID (dfo_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Folder prefix ID (dfo_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "trashed": { "type": "boolean" } }, "required": [ "id", "trashed" ], "type": "object" } ``` --- # drive_get Get Drive ## Beschreibung Returns a single drive's metadata plus the caller's inherited workspace role. Root-level counts (folders + files, live only) are included so an agent can decide whether to page in. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Ja | Drive prefix ID (drv_…) from drive_list. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string", "description": "Drive prefix ID (drv_…) from drive_list." } }, "required": [ "account_id", "drive_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "workspace_role": { "type": "string", "enum": [ "member", "manager" ] }, "archived": { "type": "boolean" }, "root_folder_count": { "type": "integer", "description": "Live folders directly under the root." }, "root_file_count": { "type": "integer", "description": "Live files directly under the root." }, "total_file_count": { "type": "integer", "description": "Live files anywhere in the drive." }, "created_by": { "type": "object" }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "description", "workspace_role", "archived", "root_folder_count", "root_file_count", "total_file_count", "created_by", "created_at", "updated_at" ], "type": "object" } ``` --- # drive_link_revoke Revoke Share Link ## Beschreibung Marks the link as revoked. The public URL immediately returns 410 Gone. Reversible — call `drive_link_save` with the same `id` and no revoke bit (there's no `restore` MCP shortcut yet; use the in-app UI or send a follow-up save call). ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string" } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "revoked": { "type": "boolean" } }, "required": [ "id", "revoked" ], "type": "object" } ``` --- # drive_link_save Create or Update Share Link ## Beschreibung Linear-style upsert. Omit `id` to mint a fresh share link for the given file. Pass `id` (dlk_…) to update expiry or password on an existing link. Same primitives as the in-app share modal: - `expires_at` — ISO 8601, date-only, or relative offset (`+7d`, `+2h`). Null / omitted = no expiry. - `password` — plaintext; hashed via has_secure_password AND stored plaintext-encrypted so a manager can look it up later. Null / omitted on create = no password. On update, omit to keep existing; pass empty string to clear. Manager on the drive is required (Pundit DriveLinkPolicy). Returns the public `/links/:token` URL. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | DriveLink prefix ID (dlk_…). Omit to create. | | `file_id` | string | Nein | File prefix ID (dfi_…). Required on create. | | `expires_at` | string / null | Nein | ISO 8601, date, or relative offset (`+7d`). | | `password` | string / null | Nein | Plaintext password. Empty string clears on update. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "DriveLink prefix ID (dlk_…). Omit to create." }, "file_id": { "type": "string", "description": "File prefix ID (dfi_…). Required on create." }, "expires_at": { "type": [ "string", "null" ], "description": "ISO 8601, date, or relative offset (`+7d`)." }, "password": { "type": [ "string", "null" ], "description": "Plaintext password. Empty string clears on update." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "file_id": { "type": "string" }, "token": { "type": "string" }, "public_url": { "type": "string" }, "expires_at": { "type": [ "string", "null" ], "format": "date-time" }, "password_protected": { "type": "boolean" }, "revoked": { "type": "boolean" }, "created": { "type": "boolean" } }, "required": [ "id", "file_id", "token", "public_url", "expires_at", "password_protected", "revoked", "created" ], "type": "object" } ``` --- # drive_list List Drives ## Beschreibung Lists drives the caller can see in this account, sorted by `updated_at DESC`. Archived drives are excluded by default; set `include_archived: true` to see them too. Each row carries the caller's inherited workspace role (`member` / `manager`), the file count, and the drive's own metadata. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `include_archived` | boolean | Nein | When true, archived drives are included in the result. Default false. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "include_archived": { "type": "boolean", "description": "When true, archived drives are included in the result. Default false." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "drives": { "type": "array", "description": "Drives visible to the caller, sorted updated_at DESC.", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Drive prefix ID (drv_…) — pass to every other drive_* tool." }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "workspace_role": { "type": "string", "enum": [ "member", "manager" ] }, "file_count": { "type": "integer", "description": "Live (non-trashed) file count." }, "archived": { "type": "boolean" }, "created_by": { "type": "object", "properties": { "id": { "type": "string" }, "handle": { "type": "string" }, "name": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "description", "workspace_role", "file_count", "archived", "created_by", "created_at", "updated_at" ] } } }, "required": [ "drives" ], "type": "object" } ``` --- # drive_save Create or Update Drive ## Beschreibung Linear-style upsert. Omit `id` to create a new drive in a workspace (the workspace is the mandatory outer access boundary) in this account. Access is inherited immediately from that workspace; the drive creates no separate grant. Pass `id` (drv_…) to rename or re-describe an existing drive. Account admins may pass `workspace_id` while updating to move the complete drive. Toggle `archive: true` / `false` to soft-hide or restore a drive. Name is unique per workspace (case-insensitive) among active drives; the DB has a `WHERE archived_at IS NULL` unique index that enforces it, so trying to reuse a live drive's name returns a validation error. Access (DrivePolicy): - Create: any member of the selected workspace. - Update / archive: account admin or destination workspace manager. - Move to another workspace: account admin only. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Drive prefix ID (drv_…). Omit to create. | | `workspace_id` | string | Nein | Workspace prefix ID (wsp_…) or key. Required on create; admin-only on update. | | `name` | string | Nein | | | `description` | string / null | Nein | | | `archive` | boolean | Nein | true = archive (soft-hide from lists); false = un-archive. Omit to leave archive state unchanged. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Drive prefix ID (drv_…). Omit to create." }, "workspace_id": { "type": "string", "description": "Workspace prefix ID (wsp_…) or key. Required on create; admin-only on update." }, "name": { "type": "string", "maxLength": 80 }, "description": { "type": [ "string", "null" ] }, "archive": { "type": "boolean", "description": "true = archive (soft-hide from lists); false = un-archive. Omit to leave archive state unchanged." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "workspace_id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "workspace_role": { "type": "string", "enum": [ "member", "manager" ] }, "archived": { "type": "boolean" }, "created": { "type": "boolean", "description": "true iff this call inserted a fresh drive." }, "created_by": { "type": "object" }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "workspace_id", "name", "description", "workspace_role", "archived", "created", "created_by", "created_at", "updated_at" ], "type": "object" } ``` --- # drive_search Search Files in a Drive ## Beschreibung Case-insensitive substring match on file names within a single drive. Same query the in-app search box runs. Returns up to 100 live files sorted by `updated_at DESC`. Does NOT search folder names or file contents. ## Zugriff Zugriffsprofil: `gated`. Module: `files`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `drive_id` | string | Ja | | | `q` | string | Ja | Substring to match on file name. Case-insensitive. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "drive_id": { "type": "string" }, "q": { "type": "string", "minLength": 1, "description": "Substring to match on file name. Case-insensitive." } }, "required": [ "account_id", "drive_id", "q" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "drive_id": { "type": "string" }, "q": { "type": "string" }, "count": { "type": "integer" }, "truncated": { "type": "boolean", "description": "True when the result was capped at 100 rows." }, "results": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "content_type": { "type": [ "string", "null" ] }, "byte_size": { "type": "integer" }, "folder_id": { "type": [ "string", "null" ] }, "path": { "type": "string" }, "updated_at": { "type": "string", "format": "date-time" } } } } }, "required": [ "drive_id", "q", "count", "truncated", "results" ], "type": "object" } ``` --- # email_account_list List Email Accounts ## Beschreibung Lists all Gmail accounts the caller has connected in this oona account, with each account's user-defined labels and current unread-thread count. Use this first to discover account IDs (`mail_…`) and label IDs (`elbl_…`) before calling other email tools. System labels are not returned per-account but can be used directly with their well-known IDs: `INBOX`, `TRASH`, `SPAM`, `STARRED`, `UNREAD`, `IMPORTANT`, `CHAT`, `DRAFT`, `SENT`. Account-scoped: the same Gmail address connected in another account is a different `mail_…` ID and is invisible from here. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "accounts": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Email-account prefix ID (mail_…)." }, "email_address": { "type": "string" }, "display_name": { "type": [ "string", "null" ] }, "status": { "type": "string", "enum": [ "connecting", "active", "error", "paused", "disconnected" ] }, "can_organize": { "type": "boolean" }, "can_send": { "type": "boolean" }, "send_confirmation_required": { "type": "boolean" }, "color_hex": { "type": [ "string", "null" ] }, "unread_count": { "type": "integer", "description": "Threads with at least one unread message." }, "labels": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Label prefix ID (elbl_…)." }, "name": { "type": "string" }, "kind": { "type": "string", "enum": [ "user", "system" ] }, "color_hex": { "type": [ "string", "null" ] } }, "required": [ "id", "name", "kind" ] } } }, "required": [ "id", "email_address", "status", "unread_count", "labels" ] } } }, "required": [ "accounts" ], "type": "object" } ``` --- # email_attachment_url Get Email Attachment Download URL ## Beschreibung Returns a short-lived signed URL (~15 min) for downloading an email attachment. The attachment's account binding is inferred from the `eatt_…` ID. Email attachments are lazy: the row is created at header-sync time but the bytes are pulled on demand. If the blob isn't yet stored locally, this tool fetches it from Gmail synchronously before returning the URL. The URL is fine to pass to any HTTP client — it carries its own signature and does not need an Authorization header. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `attachment_id` | string | Ja | Email attachment prefix ID (eatt_…) from email_thread_get FULL_CONTENT. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "attachment_id": { "type": "string", "description": "Email attachment prefix ID (eatt_…) from email_thread_get FULL_CONTENT." } }, "required": [ "account_id", "attachment_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "url": { "type": "string", "format": "uri", "description": "Signed download URL, valid 15 minutes." }, "expires_at": { "type": "string", "format": "date-time" }, "filename": { "type": "string" }, "content_type": { "type": [ "string", "null" ] }, "size_bytes": { "type": [ "integer", "null" ] } }, "required": [ "url", "expires_at", "filename" ], "type": "object" } ``` --- # email_convert_to_task Convert Email to Task ## Beschreibung Creates a Task from an email and links the two so the conversion is traceable and idempotent. Pass exactly one of `message_id` (`emsg_…`) or `thread_id` (`ethr_…`); for a thread the latest message is used as the anchor. `workspace_id` is the destination workspace (prefix `wsp_…` or KEY like `ENG`); `project_id` (`proj_…` or slug) is optional and must belong to that workspace. Defaults: `title` = the email subject; the task description is seeded from the email body (override with `description`, Markdown). `assignee` is a `@handle` or user prefix. `link_kind` is `created_from` (default — this task was made from the email) or `referenced_in`. Idempotent: if the source is already linked with the same `link_kind`, the existing task is returned with `created: false` and no new task is made. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `message_id` | string | Nein | Source message (emsg_…). Provide this OR thread_id. | | `thread_id` | string | Nein | Source thread (ethr_…); its latest message is used. Provide this OR message_id. | | `workspace_id` | string | Ja | Destination workspace prefix ID (wsp_…) or KEY (e.g. ENG). | | `project_id` | string | Nein | Optional project (proj_… or slug); must belong to the workspace. | | `title` | string | Nein | Task title. Defaults to the email subject. | | `description` | string | Nein | Task description in Markdown. Defaults to the email body. | | `assignee` | string | Nein | Assignee @handle or user prefix ID. | | `link_kind` | string | Nein | Provenance link kind. Default created_from. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "message_id": { "type": "string", "description": "Source message (emsg_…). Provide this OR thread_id." }, "thread_id": { "type": "string", "description": "Source thread (ethr_…); its latest message is used. Provide this OR message_id." }, "workspace_id": { "type": "string", "description": "Destination workspace prefix ID (wsp_…) or KEY (e.g. ENG)." }, "project_id": { "type": "string", "description": "Optional project (proj_… or slug); must belong to the workspace." }, "title": { "type": "string", "description": "Task title. Defaults to the email subject." }, "description": { "type": "string", "description": "Task description in Markdown. Defaults to the email body." }, "assignee": { "type": "string", "description": "Assignee @handle or user prefix ID." }, "link_kind": { "type": "string", "enum": [ "created_from", "referenced_in" ], "description": "Provenance link kind. Default created_from." } }, "required": [ "account_id", "workspace_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "task": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "url": { "type": "string" } }, "required": [ "id", "key", "url" ] }, "link": { "type": "object", "properties": { "id": { "type": "string" }, "kind": { "type": "string" } }, "required": [ "id", "kind" ] }, "created": { "type": "boolean", "description": "false when an existing link/task was returned (idempotent)." } }, "required": [ "task", "link", "created" ], "type": "object" } ``` --- # email_send Send Email ## Beschreibung Sends an email from one of the caller's connected Gmail accounts in this account. Covers five modes via parameters — they're mutually exclusive: - **New** (default): omit `reply_to_message_id`, `forward_of`, and `redirect_of`. - **Reply**: set `reply_to_message_id` to an `emsg_…`. The subject is auto-prefixed with `Re:` if absent, threading headers (`In-Reply-To`, `References`) are populated, and the message stays in the original Gmail conversation. The original is auto-quoted below your body — write only your own reply, not the citation. - **Reply-all**: same as reply, plus set `reply_all: true` to copy the original `To` + `Cc` (minus your own addresses) into the outgoing `Cc`. - **Forward**: set `forward_of` to an `emsg_…`. Subject gets `Fwd:` prefix, the original is quoted below your body, original attachments are NOT auto-carried (re- attach explicitly via `attachment_ids` if needed). - **Redirect**: set `redirect_of` to an `emsg_…`. Body is NOT taken from `body_markdown`; the original message is forwarded verbatim with optional `comment` rendered in an attribution box. `Reply-To` is set to the original sender so the recipient can reply directly to them. `subject` / `body_markdown` are ignored in this mode. `as_draft: true` saves to the sender's Drafts instead of sending. Works with new/reply/forward; not with redirect. Body is Markdown — server renders to HTML (and a plain- text fallback) so the recipient sees formatting and clickable links. Use standard GFM (headings, lists, bold, italic, links, code). Attachments: pass `attachment_ids` — handles from `attachment_upload` (att_… ids or file_urls). Combined size <= 25 MB (Gmail's limit). On success returns `{ message_id, thread_id }` (live send) or `{ draft_id }` (when `as_draft: true`). Gating: if the mailbox owner enabled "Require confirmation for agent send", a live send is held as a draft and returns `{ confirmation_required: true, draft_id }` instead of sending — a human approves it later. Otherwise, direct live sends are rate-limited (50/hour per user); over the cap returns `{ rate_limited: true, retry_after }`. `as_draft` and confirmation-held sends do not count against the cap (held sends are governed by human approval instead). ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `from_account_id` | string | Ja | Sender mail account prefix ID (mail_…). Discover via email_account_list. | | `to` | array | Ja | Primary recipients. Plain addresses only — no "Name ". | | `cc` | array | Nein | Cc recipients. Plain addresses only. | | `bcc` | array | Nein | Bcc recipients. Plain addresses only. | | `subject` | string | Nein | Subject line. Auto-prefixed with Re:/Fwd: in reply/forward modes if absent. Ignored in redirect mode. | | `body_markdown` | string | Nein | GFM Markdown body. Server renders to HTML; plain text is auto-derived. Ignored in redirect mode. | | `reply_to_message_id` | string | Nein | Message prefix ID (emsg_…) to reply to. Exclusive with forward_of/redirect_of. | | `reply_all` | boolean | Nein | Reply-mode only: include original To+Cc (minus self) in outgoing Cc. | | `forward_of` | string | Nein | Message prefix ID (emsg_…) to forward. Exclusive with reply_to_message_id/redirect_of. | | `redirect_of` | string | Nein | Message prefix ID (emsg_…) to redirect. Exclusive with reply_to_message_id/forward_of. | | `comment` | string | Nein | Redirect mode only: short note rendered in an attribution box above the forwarded body. | | `attachment_ids` | array | Nein | Attachment handles from attachment_upload — att_… ids or file_urls. | | `as_draft` | boolean | Nein | Save to Drafts instead of sending. Default false. Not compatible with redirect. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "from_account_id": { "type": "string", "description": "Sender mail account prefix ID (mail_…). Discover via email_account_list." }, "to": { "type": "array", "items": { "type": "string" }, "description": "Primary recipients. Plain addresses only — no \"Name \"." }, "cc": { "type": "array", "items": { "type": "string" }, "description": "Cc recipients. Plain addresses only." }, "bcc": { "type": "array", "items": { "type": "string" }, "description": "Bcc recipients. Plain addresses only." }, "subject": { "type": "string", "description": "Subject line. Auto-prefixed with Re:/Fwd: in reply/forward modes if absent. Ignored in redirect mode." }, "body_markdown": { "type": "string", "description": "GFM Markdown body. Server renders to HTML; plain text is auto-derived. Ignored in redirect mode." }, "reply_to_message_id": { "type": "string", "description": "Message prefix ID (emsg_…) to reply to. Exclusive with forward_of/redirect_of." }, "reply_all": { "type": "boolean", "description": "Reply-mode only: include original To+Cc (minus self) in outgoing Cc." }, "forward_of": { "type": "string", "description": "Message prefix ID (emsg_…) to forward. Exclusive with reply_to_message_id/redirect_of." }, "redirect_of": { "type": "string", "description": "Message prefix ID (emsg_…) to redirect. Exclusive with reply_to_message_id/forward_of." }, "comment": { "type": "string", "description": "Redirect mode only: short note rendered in an attribution box above the forwarded body." }, "attachment_ids": { "type": "array", "items": { "type": "string" }, "description": "Attachment handles from attachment_upload — att_… ids or file_urls." }, "as_draft": { "type": "boolean", "description": "Save to Drafts instead of sending. Default false. Not compatible with redirect." } }, "required": [ "account_id", "from_account_id", "to" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "message_id": { "type": [ "string", "null" ], "description": "Set when the message was sent." }, "thread_id": { "type": [ "string", "null" ], "description": "Set when the message was sent." }, "draft_id": { "type": [ "string", "null" ], "description": "Set when as_draft was true, or when a live send was held for confirmation." }, "mode": { "type": "string", "enum": [ "new", "reply", "reply_all", "forward", "redirect" ] }, "confirmation_required": { "type": "boolean", "description": "ENG-1218: true when the send was held as a draft for human approval instead of sent." }, "rate_limited": { "type": "boolean", "description": "ENG-1218: true when the hourly send rate limit was hit; nothing was sent." }, "retry_after": { "type": [ "integer", "null" ], "description": "Seconds to wait before retrying, when rate_limited." } }, "type": "object" } ``` --- # email_send_no_reply Send No-Reply Email ## Beschreibung Sends a single transactional email from the system no-reply address (`oona `). Use this for notifications and alerts that do NOT expect a reply — report finished, run completed, threshold crossed. For anything where the recipient might reply, use `email_send` from a connected Gmail mailbox instead. The sender address is fixed by app config and is NOT overridable. The `from_name` parameter only changes the display name shown next to it (e.g. `"Reports" `). Recipients (`to` / `cc` / `bcc`) are passed as comma-separated strings — `"a@x.com, b@x.com"`. At least one `to` is required. Body: at least one of `text_content` or `html_content` must be present. If only one is given the mail is single-part; if both are given it goes out as multipart (text + html). Unlike `email_send`, neither body is Markdown — the agent provides each format verbatim. Attachments: optional inline base64 list, each item `{filename, content (base64), content_type?}`. Combined size ≤ 10 MB across the whole email. `content_type` defaults to `application/octet-stream` when omitted. On success returns `{ sent: true, from, subject, to_count, cc_count, bcc_count, attachment_count }`. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `to` | string | Ja | Primary recipients, comma-separated. At least one required. | | `cc` | string | Nein | Cc recipients, comma-separated. Optional. | | `bcc` | string | Nein | Bcc recipients, comma-separated. Optional. | | `subject` | string | Ja | Subject line. | | `text_content` | string | Nein | Plain-text body. At least one of text_content / html_content is required. | | `html_content` | string | Nein | HTML body. At least one of text_content / html_content is required. | | `from_name` | string | Nein | Display name shown in the From header. The address itself stays the configured no-reply. | | `attachments` | array | Nein | Optional inline attachments. Combined size ≤ 10 MB across the whole email. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "to": { "type": "string", "description": "Primary recipients, comma-separated. At least one required." }, "cc": { "type": "string", "description": "Cc recipients, comma-separated. Optional." }, "bcc": { "type": "string", "description": "Bcc recipients, comma-separated. Optional." }, "subject": { "type": "string", "description": "Subject line." }, "text_content": { "type": "string", "description": "Plain-text body. At least one of text_content / html_content is required." }, "html_content": { "type": "string", "description": "HTML body. At least one of text_content / html_content is required." }, "from_name": { "type": "string", "description": "Display name shown in the From header. The address itself stays the configured no-reply." }, "attachments": { "type": "array", "description": "Optional inline attachments. Combined size ≤ 10 MB across the whole email.", "items": { "type": "object", "properties": { "filename": { "type": "string", "description": "Filename shown in the mail." }, "content": { "type": "string", "description": "Base64-encoded file bytes." }, "content_type": { "type": "string", "description": "MIME type. Defaults to application/octet-stream." } }, "required": [ "filename", "content" ] } } }, "required": [ "account_id", "to", "subject" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "sent": { "type": "boolean" }, "from": { "type": "string", "description": "The From header that was used (incl. display name)." }, "subject": { "type": "string" }, "to_count": { "type": "integer" }, "cc_count": { "type": "integer" }, "bcc_count": { "type": "integer" }, "attachment_count": { "type": "integer" } }, "type": "object" } ``` --- # email_share_to_chat Share Email to Chat ## Beschreibung Posts an email into a chat channel or DM so the workspace can see it without leaving chat, and links the two for traceability. Pass exactly one of `message_id` (`emsg_…`) or `thread_id` (`ethr_…`); for a thread the latest message is shared. Pass exactly one target: `channel_id` (`chan_…` from chat_list_channels) or `dm_with_user` (a `@handle` / user prefix — starts-or-finds the 1:1 DM). The posted message is authored by you: an optional `comment` on top, then a quote block (sender / subject / snippet) unless `include_quote` is false, and the email's attachments unless `include_attachments` is false (default true for both). You must have post access to the target channel (membership, or admin/employer reach). Idempotent per (email, channel): if the email is already shared into that channel the existing chat message is returned with `created: false` — a retry won't double-post. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `message_id` | string | Nein | Source message (emsg_…). Provide this OR thread_id. | | `thread_id` | string | Nein | Source thread (ethr_…); its latest message is shared. Provide this OR message_id. | | `channel_id` | string | Nein | Target channel (chan_…). Provide this OR dm_with_user. | | `dm_with_user` | string | Nein | Target DM partner: @handle or user prefix ID. Starts-or-finds the 1:1 DM. Provide this OR channel_id. | | `comment` | string | Nein | Optional note posted above the email quote. | | `include_attachments` | boolean | Nein | Re-attach the email's files to the chat message. Default true. | | `include_quote` | boolean | Nein | Include the From / Subject / snippet quote block. Default true. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "message_id": { "type": "string", "description": "Source message (emsg_…). Provide this OR thread_id." }, "thread_id": { "type": "string", "description": "Source thread (ethr_…); its latest message is shared. Provide this OR message_id." }, "channel_id": { "type": "string", "description": "Target channel (chan_…). Provide this OR dm_with_user." }, "dm_with_user": { "type": "string", "description": "Target DM partner: @handle or user prefix ID. Starts-or-finds the 1:1 DM. Provide this OR channel_id." }, "comment": { "type": "string", "description": "Optional note posted above the email quote." }, "include_attachments": { "type": "boolean", "description": "Re-attach the email's files to the chat message. Default true." }, "include_quote": { "type": "boolean", "description": "Include the From / Subject / snippet quote block. Default true." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "chat_message": { "type": "object", "properties": { "id": { "type": "string" }, "url": { "type": "string" } }, "required": [ "id", "url" ] }, "share_link_id": { "type": "string", "description": "The EmailChatShare prefix ID (ecsh_…)." }, "created": { "type": "boolean", "description": "false when an existing share was returned (idempotent re-share)." } }, "required": [ "chat_message", "share_link_id", "created" ], "type": "object" } ``` --- # email_thread_get Get Email Thread ## Beschreibung Retrieves a specific email thread by its prefixed ID (`ethr_…`) including its messages, ordered oldest → newest. The thread's account binding is inferred from the ID, so no `account_id` is needed here beyond the account context. `message_format` controls how much per-message detail you get: - `FULL_CONTENT` (default) — snippet, headers, plain-text and HTML body, and the list of attachments (each with its `eatt_…` ID and metadata). Use this when you need to read or quote the content. - `MINIMAL` — snippet plus the key headers (Subject, From, To, Cc, Date) only; body content and attachment metadata are omitted. Use this for cheap thread previews. Body content arrives as plain text (`body_text`) and HTML (`body_html`). Plain text is usually what an agent should reason over; the HTML is included for completeness. To download an attachment's bytes, call `email_attachment_url` with the `eatt_…` ID returned here. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `thread_id` | string | Ja | Thread prefix ID (ethr_…) from email_thread_search. | | `message_format` | string | Nein | Per-message detail level. Default FULL_CONTENT. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "thread_id": { "type": "string", "description": "Thread prefix ID (ethr_…) from email_thread_search." }, "message_format": { "type": "string", "enum": [ "FULL_CONTENT", "MINIMAL" ], "description": "Per-message detail level. Default FULL_CONTENT." } }, "required": [ "account_id", "thread_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "thread": { "type": "object", "properties": { "id": { "type": "string" }, "account_id": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "snippet": { "type": [ "string", "null" ] }, "participants": { "type": "array", "items": { "type": "object" } }, "message_count": { "type": "integer" }, "last_message_at": { "type": [ "string", "null" ], "format": "date-time" }, "is_unread": { "type": "boolean" }, "is_starred": { "type": "boolean" }, "has_attachments": { "type": "boolean" }, "messages": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "from": { "type": [ "object", "null" ] }, "to": { "type": "array", "items": { "type": "object" } }, "cc": { "type": "array", "items": { "type": "object" } }, "bcc": { "type": "array", "items": { "type": "object" } }, "subject": { "type": [ "string", "null" ] }, "snippet": { "type": [ "string", "null" ] }, "date": { "type": [ "string", "null" ], "format": "date-time" }, "is_unread": { "type": "boolean" }, "is_starred": { "type": "boolean" }, "is_draft": { "type": "boolean" }, "is_sent": { "type": "boolean" }, "labels": { "type": "array", "items": { "type": "string" } }, "body_text": { "type": [ "string", "null" ], "description": "Only in FULL_CONTENT." }, "body_html": { "type": [ "string", "null" ], "description": "Only in FULL_CONTENT." }, "attachments": { "type": "array", "description": "Only in FULL_CONTENT. Use email_attachment_url to download.", "items": { "type": "object", "properties": { "id": { "type": "string" }, "filename": { "type": "string" }, "content_type": { "type": [ "string", "null" ] }, "size_bytes": { "type": [ "integer", "null" ] }, "is_inline": { "type": "boolean" } } } } }, "required": [ "id", "from", "subject", "snippet", "date", "is_unread", "is_starred", "is_draft", "is_sent", "labels" ] } } }, "required": [ "id", "account_id", "subject", "snippet", "message_count", "last_message_at", "is_unread", "is_starred", "has_attachments", "messages" ] } }, "required": [ "thread" ], "type": "object" } ``` --- # email_thread_modify Modify Email Thread ## Beschreibung Modifies a thread's state: applies / removes labels, marks read or unread, stars / un-stars, moves to or from trash. Changes are pushed to Gmail (so they sync to the user's other clients) and the local mirror is updated to match. Convenience shortcuts: - **Archive** = `remove_labels: ["INBOX"]` - **Mark thread read** = `read: true` - **Star** = `starred: true` (same as adding `STARRED`) - **Move to spam** = `add_labels: ["SPAM"]` Label IDs accept either Gmail's system well-known IDs (`INBOX`, `UNREAD`, `STARRED`, `IMPORTANT`, `TRASH`, `SPAM`, `DRAFT`, `SENT`, `CHAT`) or a user label's prefix ID (`elbl_…`) discovered via `email_account_list`. Account binding is inferred from the thread ID — no `from_account_id` is needed. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `thread_id` | string | Ja | Thread prefix ID (ethr_…). | | `add_labels` | array | Nein | Label IDs to add. System well-knowns or elbl_… IDs. | | `remove_labels` | array | Nein | Label IDs to remove. Same format as add_labels. | | `read` | boolean | Nein | true → remove UNREAD on every message; false → mark all unread. | | `starred` | boolean | Nein | true → add STARRED; false → remove STARRED. | | `trashed` | boolean | Nein | true → move to trash; false → restore from trash. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "thread_id": { "type": "string", "description": "Thread prefix ID (ethr_…)." }, "add_labels": { "type": "array", "items": { "type": "string" }, "description": "Label IDs to add. System well-knowns or elbl_… IDs." }, "remove_labels": { "type": "array", "items": { "type": "string" }, "description": "Label IDs to remove. Same format as add_labels." }, "read": { "type": "boolean", "description": "true → remove UNREAD on every message; false → mark all unread." }, "starred": { "type": "boolean", "description": "true → add STARRED; false → remove STARRED." }, "trashed": { "type": "boolean", "description": "true → move to trash; false → restore from trash." } }, "required": [ "account_id", "thread_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "ok": { "type": "boolean" }, "thread": { "type": "object", "description": "MINIMAL-format thread state after the mutation (no per-message bodies/attachments).", "properties": { "id": { "type": "string" }, "account_id": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "snippet": { "type": [ "string", "null" ] }, "message_count": { "type": "integer" }, "last_message_at": { "type": [ "string", "null" ], "format": "date-time" }, "is_unread": { "type": "boolean" }, "is_starred": { "type": "boolean" }, "has_attachments": { "type": "boolean" } } } }, "required": [ "ok", "thread" ], "type": "object" } ``` --- # email_thread_search Search Email Threads ## Beschreibung Lists email threads from the caller's connected Gmail accounts in this oona account. Filters via Gmail's native query syntax — the same operators that work in Gmail web search: - **Sender/recipient:** `from:`, `to:`, `cc:`, `bcc:`, `deliveredto:`, `list:` - **Time:** `after:YYYY/MM/DD`, `before:YYYY/MM/DD`, `newer:`, `older:`, `older_than:1y`, `newer_than:7d` - **Content:** `subject:`, `has:attachment`, `filename:`, `"exact phrase"`, `+exact`, `rfc822msgid:`, `AROUND` - **Status/location:** `is:unread`, `is:starred`, `is:important`, `in:inbox|sent|drafts|trash|spam|anywhere`, `category:primary|social|promotions|updates|forums|reservations|purchases` - **Labels:** `label:Newsletter` (use the label name as shown to the user) - **Size:** `larger:10M`, `smaller:500K` - **Logic:** `AND`, `OR`, `-exclude`, `( )` grouping Examples: - `"is:unread newer_than:7d"` - `"from:finance@versacommerce.de subject:invoice"` - `"has:attachment in:inbox -from:no-reply"` Returns thread headers + a short snippet. Use `email_thread_get` with a returned `ethr_…` ID to read the messages. By default searches across **all** connected accounts in the account; pass `account_ids` to narrow. Pagination via `page_size` (max 50) and `page_token`. ## Zugriff Zugriffsprofil: `gated`. Module: `email`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `account_ids` | array | Nein | Restrict to specific Gmail accounts (mail_… from email_account_list). Default: all live accounts. | | `query` | string | Nein | Gmail query syntax. Empty = list everything except spam/trash. | | `include_trash` | boolean | Nein | Include threads from TRASH. Default false. | | `page_size` | integer | Nein | Default 20, max 50. | | `page_token` | string | Nein | Opaque cursor from a previous response's next_page_token. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "account_ids": { "type": "array", "items": { "type": "string" }, "description": "Restrict to specific Gmail accounts (mail_… from email_account_list). Default: all live accounts." }, "query": { "type": "string", "description": "Gmail query syntax. Empty = list everything except spam/trash." }, "include_trash": { "type": "boolean", "description": "Include threads from TRASH. Default false." }, "page_size": { "type": "integer", "minimum": 1, "maximum": 50, "description": "Default 20, max 50." }, "page_token": { "type": "string", "description": "Opaque cursor from a previous response's next_page_token." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "threads": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "account_id": { "type": "string" }, "subject": { "type": [ "string", "null" ] }, "snippet": { "type": [ "string", "null" ] }, "participants": { "type": "array", "items": { "type": "object" } }, "message_count": { "type": "integer" }, "last_message_at": { "type": [ "string", "null" ], "format": "date-time" }, "is_unread": { "type": "boolean" }, "is_starred": { "type": "boolean" }, "has_attachments": { "type": "boolean" } }, "required": [ "id", "account_id", "subject", "message_count", "is_unread", "is_starred" ] } }, "next_page_token": { "type": [ "string", "null" ] } }, "required": [ "threads" ], "type": "object" } ``` --- # group_get Get Group ## Beschreibung Returns one group's metadata + every member. Useful before making a follow-up `group_member_add` / `group_member_remove` call so the agent can confirm the current roster. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Group prefix ID (grp_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Group prefix ID (grp_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "group": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "archived": { "type": "boolean" }, "created_at": { "type": "string", "format": "date-time" }, "members": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "User prefix ID or @handle." }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } }, "required": [ "id", "name" ] } } }, "required": [ "id", "name", "archived", "created_at", "members" ] } }, "required": [ "group" ], "type": "object" } ``` --- # group_list List Groups ## Beschreibung Lists member groups in the account. Groups are a primitive for scoping (channel access, document sharing, project visibility) — no ACL surfaces consume them yet, but the IDs returned here are stable and safe to attach to future permission rows. Soft-deleted (archived) groups are excluded by default; pass `include_archived: true` to surface them as well. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `include_archived` | boolean | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "include_archived": { "type": "boolean", "default": false } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "groups": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Group prefix ID (grp_…)." }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "member_count": { "type": "integer" }, "archived": { "type": "boolean" }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "member_count", "archived", "created_at" ] } } }, "required": [ "groups" ], "type": "object" } ``` --- # group_member_add Add Group Member ## Beschreibung Adds `user` to `group`. Idempotent: a re-add returns the existing row unchanged. Refuses to add a user from a different account. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `group_id` | string | Ja | Group prefix ID (grp_…). | | `user` | string | Ja | User prefix ID or @handle. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "group_id": { "type": "string", "description": "Group prefix ID (grp_…)." }, "user": { "type": "string", "description": "User prefix ID or @handle." } }, "required": [ "account_id", "group_id", "user" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "group_id": { "type": "string" }, "user_id": { "type": "string" }, "added": { "type": "boolean", "description": "false when the user was already a member." } }, "required": [ "group_id", "user_id", "added" ], "type": "object" } ``` --- # group_member_remove Remove Group Member ## Beschreibung Removes `user` from `group`. Idempotent: removing a non-member returns `removed: false` without erroring. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `group_id` | string | Ja | | | `user` | string | Ja | User prefix ID or @handle. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "group_id": { "type": "string" }, "user": { "type": "string", "description": "User prefix ID or @handle." } }, "required": [ "account_id", "group_id", "user" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "group_id": { "type": "string" }, "user_id": { "type": "string" }, "removed": { "type": "boolean" } }, "required": [ "group_id", "user_id", "removed" ], "type": "object" } ``` --- # group_save Create or Update Group ## Beschreibung Upserts a member group. On create, name is required; on update, only the keys you pass are changed (name + description + archived). Name must be unique per account among active groups — archiving a group frees its name for reuse. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Group prefix ID. Omit to create. | | `name` | string | Nein | Required on create. | | `description` | string / null | Nein | | | `archived` | boolean | Nein | true → archive; false → unarchive. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Group prefix ID. Omit to create." }, "name": { "type": "string", "description": "Required on create." }, "description": { "type": [ "string", "null" ] }, "archived": { "type": "boolean", "description": "true → archive; false → unarchive." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "group": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "archived": { "type": "boolean" } }, "required": [ "id", "name", "archived" ] } }, "required": [ "group" ], "type": "object" } ``` --- # http_request HTTP Request ## Beschreibung Call an external HTTP service with method, URL, headers and an optional body. Put authentication and Content-Type in headers, e.g. {"Authorization":"Bearer …","Content-Type":"application/json"}. The body is a string; serialize JSON yourself. Returns status, response headers (arrays of values), body and body_encoding (utf-8 or base64 for binary). HTTP error statuses are returned normally. Redirects are NOT followed: inspect Location before making a separate request; never forward credentials blindly. Public Internet endpoints only. Request/response body limit: 1 MB; timeout: 30s. Requests are never automatically retried. A timeout may still mean a mutation succeeded. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `method` | string | Ja | | | `url` | string | Ja | Absolute HTTP(S) URL. | | `headers` | object | Nein | | | `body` | string | Nein | Raw request body, e.g. serialized JSON. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "method": { "type": "string", "enum": [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" ] }, "url": { "type": "string", "description": "Absolute HTTP(S) URL." }, "headers": { "type": "object", "additionalProperties": { "type": "string" } }, "body": { "type": "string", "description": "Raw request body, e.g. serialized JSON." } }, "required": [ "account_id", "method", "url" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "status": { "type": "integer" }, "headers": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "string" } } }, "body": { "type": "string" }, "body_encoding": { "type": "string", "enum": [ "utf-8", "base64" ] } }, "required": [ "status", "headers", "body", "body_encoding" ], "type": "object" } ``` --- # label_list List Labels ## Beschreibung Lists labels in the account, alphabetically. Labels are workspace-scoped — pass `workspace_id` to narrow to one workspace. The same name may exist in several workspaces; clients should disambiguate via the returned `workspace` block or the label's prefix id. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `workspace_id` | string | Nein | Optional workspace prefix ID or key. Narrows results to one workspace. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "workspace_id": { "type": "string", "description": "Optional workspace prefix ID or key. Narrows results to one workspace." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "labels": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "color": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "key", "name" ] } }, "required": [ "id", "name", "color", "workspace" ] } } }, "required": [ "labels" ], "type": "object" } ``` --- # project_activities Project Activities ## Beschreibung Unified recent-activity feed — answers "what happened on this project / task / workspace lately?" without enumerating every task. Merges four sources, sorted newest-first: - project_event (created / status_changed / target_changed / lead_changed / name_changed) - project_update (status updates the workspace posts on the project Activity tab; includes health + body) - task_event (task status / assignee / priority / due / label / project / subtask changes) - task_comment (comments on tasks within the project) Default window: last 30 days, newest 50 entries. Scoping (at least one of these is required): - project_id proj_… prefix or slug — scope to one project (the primary mode; matches the tool's goal). - workspace_id workspace prefix or key (ENG) — scope to all the workspace's projects. - task_id task_… prefix or KEY-N — drill into one task's events + comments. Modifiers (all optional): - kinds array, any of project_event / project_update / task_event / task_comment. - created_at ISO 8601 timestamp (2026-05-01T00:00:00Z) OR ISO 8601 duration (-P7D = last 7 days, -P1D = last 24h). Lower bound on created_at. - cursor opaque, from a previous response's next_cursor. - limit 1-250, default 50. Pagination: pass `next_cursor` from a previous response to fetch the next older page. Per-row `id` is the prefix id of the underlying record (pa_/pu_/act_/cmt_) and the `url` field is a paste-able web URL. Access: only entries from projects the caller can read are returned (admin/employer see all account projects; regular members see their workspaces' projects plus projects they lead). ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `project_id` | string | Nein | Project prefix ID (proj_…) or slug. | | `workspace_id` | string | Nein | Workspace prefix ID or key (e.g. ENG). | | `task_id` | string | Nein | Task prefix ID (task_…) or issue key (e.g. ENG-3) — refines to one task. | | `kinds` | array | Nein | Subset of activity sources to include. Defaults to all four. | | `created_at` | string | Nein | Lower bound on created_at. ISO 8601 timestamp or ISO duration (-P7D, -P1D). | | `cursor` | string | Nein | Opaque cursor from a previous response's next_cursor. | | `limit` | integer | Nein | Max entries (default 50, max 250). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "project_id": { "type": "string", "description": "Project prefix ID (proj_…) or slug." }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key (e.g. ENG)." }, "task_id": { "type": "string", "description": "Task prefix ID (task_…) or issue key (e.g. ENG-3) — refines to one task." }, "kinds": { "type": "array", "items": { "type": "string", "enum": [ "project_event", "project_update", "task_event", "task_comment" ] }, "description": "Subset of activity sources to include. Defaults to all four." }, "created_at": { "type": "string", "description": "Lower bound on created_at. ISO 8601 timestamp or ISO duration (-P7D, -P1D)." }, "cursor": { "type": "string", "description": "Opaque cursor from a previous response's next_cursor." }, "limit": { "type": "integer", "default": 50, "description": "Max entries (default 50, max 250)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "events": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "kind": { "type": "string", "enum": [ "project_event", "project_update", "task_event", "task_comment" ] }, "event": { "type": [ "string", "null" ] }, "created_at": { "type": "string", "format": "date-time" }, "actor": { "type": [ "object", "null" ] }, "project": { "type": [ "object", "null" ], "description": "Null only for events of orphaned tasks (project deleted via dependent: :nullify)." }, "task": { "type": [ "object", "null" ] }, "payload": { "type": [ "object", "null" ] }, "body_markdown": { "type": [ "string", "null" ] }, "health": { "type": [ "string", "null" ] }, "url": { "type": "string" } }, "required": [ "id", "kind", "created_at", "url" ] } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "events" ], "type": "object" } ``` --- # project_get Get Project ## Beschreibung Fetches a single project including the latest update body, member list, and computed progress. Description is returned in Markdown so agents can read + diff it; pair with `project_save` when writing back. The returned `project.id` is the canonical `proj_…` prefix ID — round-trip it through `project_save`, `task_save({project_id: …})`, or `project_update_save`. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Project prefix ID (proj_…) or slug. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Project prefix ID (proj_…) or slug." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] } }, "required": [ "project" ], "type": "object" } ``` --- # project_list List Projects ## Beschreibung Lists projects the caller can read in the account. Each row includes the project's `proj_…` prefix ID — pass it back to `project_get`, `task_save({project_id: …})`, etc. Filter by `workspace_id`, status (`backlog | planned | in_progress | paused | completed | cancelled`), `priority` (`urgent | high | medium | low | no_priority`), and `archived` (defaults to false). Sorted by name. `progress_ratio` is computed live from `completed_tasks / total_tasks`. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID. | | `workspace_id` | string | Nein | Workspace prefix ID or key (e.g. ENG). | | `status` | string | Nein | Project status enum key. | | `priority` | string | Nein | Priority enum key. | | `archived` | boolean | Nein | Include archived projects (default false). | | `query` | string | Nein | Substring match on name or summary. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID." }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key (e.g. ENG)." }, "status": { "type": "string", "description": "Project status enum key." }, "priority": { "type": "string", "description": "Priority enum key." }, "archived": { "type": "boolean", "description": "Include archived projects (default false)." }, "query": { "type": "string", "description": "Substring match on name or summary." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "projects": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] } } }, "required": [ "projects" ], "type": "object" } ``` --- # project_save Create or Update Project ## Beschreibung Linear-style upsert. Pass `id` to update; omit to create. Description accepts Markdown and is converted to Tiptap JSON. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Project prefix ID (proj_…) or slug. Omit to create. | | `workspace_id` | string | Nein | Required on create. Prefix or key. | | `name` | string | Nein | | | `summary` | string / null | Nein | | | `description_markdown` | string / null | Nein | | | `status` | string | Nein | | | `priority` | string | Nein | | | `icon_emoji` | string / null | Nein | Single unicode emoji glyph (e.g. "🚀"). The common `:shortcode:` aliases (`:rocket:`, `:fire:`, `:white_check_mark:`, …) are also accepted and converted to the matching glyph at save time. Pass an empty string to clear. | | `color` | string | Nein | | | `target_on` | string / null | Nein | | | `start_on` | string / null | Nein | | | `lead` | string / null | Nein | User prefix or @handle. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Project prefix ID (proj_…) or slug. Omit to create." }, "workspace_id": { "type": "string", "description": "Required on create. Prefix or key." }, "name": { "type": "string" }, "summary": { "type": [ "string", "null" ] }, "description_markdown": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "priority": { "type": "string" }, "icon_emoji": { "type": [ "string", "null" ], "description": "Single unicode emoji glyph (e.g. \"🚀\"). The common `:shortcode:` aliases (`:rocket:`, `:fire:`, `:white_check_mark:`, …) are also accepted and converted to the matching glyph at save time. Pass an empty string to clear." }, "color": { "type": "string" }, "target_on": { "type": [ "string", "null" ] }, "start_on": { "type": [ "string", "null" ] }, "lead": { "type": [ "string", "null" ], "description": "User prefix or @handle." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] } }, "required": [ "project" ], "type": "object" } ``` --- # project_update_save Post a Project Update ## Beschreibung Posts a status update on a project (Linear's `save_status_update`). Optional `health` records the project's health: pass one of `on_track | at_risk | off_track`, or omit for no health change. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `project_id` | string | Ja | Project prefix ID (proj_…) or slug. | | `body` | string | Ja | Update body (plain text or Markdown). | | `health` | string / null | Nein | on_track, at_risk, or off_track. Optional. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "project_id": { "type": "string", "description": "Project prefix ID (proj_…) or slug." }, "body": { "type": "string", "description": "Update body (plain text or Markdown)." }, "health": { "type": [ "string", "null" ], "description": "on_track, at_risk, or off_track. Optional." } }, "required": [ "account_id", "project_id", "body" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "update": { "type": "object", "properties": { "id": { "type": "string" }, "body": { "type": "string" } }, "required": [ "id", "body" ] } }, "required": [ "update" ], "type": "object" } ``` --- # roadmap_activities Roadmap Activity Feed ## Beschreibung Returns the reverse-chronological activity feed for a roadmap. Both roadmap-level events (created / title_changed / description_changed / archived / unarchived) and entry-level events (entry_created / entry_title_changed / entry_status_changed / entry_dates_changed / entry_destroyed / entry_project_linked / entry_project_unlinked) flow into the same feed, ordered newest first. `payload` shape depends on the event: - `title_changed`, `entry_title_changed`: `{from, to}` - `entry_status_changed`: `{from, to}` (status names) - `entry_dates_changed`: `{starts_on: {from,to}, due_on: {from,to}}` - `entry_project_linked` / `entry_project_unlinked`: `{project_id, project_name}` (denormalised so the log survives project renames) - `entry_created`: `{title}` - Other events carry an empty or minimal payload. `limit` defaults to 50, clamped to [1, 200]. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `roadmap_id` | string | Ja | Roadmap prefix ID (rmap_…). | | `limit` | integer | Nein | Number of rows to return. Default 50, clamped to [1, 200]. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "roadmap_id": { "type": "string", "description": "Roadmap prefix ID (rmap_…)." }, "limit": { "type": "integer", "description": "Number of rows to return. Default 50, clamped to [1, 200]." } }, "required": [ "account_id", "roadmap_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "activities": { "type": "array", "description": "Newest first.", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "ra_…" }, "event": { "type": "string", "description": "Event name; see the description for the full list." }, "payload": { "type": [ "object", "null" ], "description": "Event-specific data; shape depends on event." }, "user": { "type": [ "object", "null" ], "description": "Actor. Null for system events.", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] }, "roadmap_entry_id": { "type": [ "string", "null" ], "description": "Set for entry-level events; null for roadmap-level events." }, "created_at": { "type": "string", "description": "ISO 8601." } }, "required": [ "id", "event", "created_at" ] } } }, "required": [ "activities" ], "type": "object" } ``` --- # roadmap_entry_destroy Delete Roadmap Entry ## Beschreibung Permanently deletes a roadmap entry. All of its project links go with it. An `entry_destroyed` activity row is written to the parent roadmap's feed so the deletion remains auditable via `roadmap_activities`. Two-step confirmation (deletion is not silent): the first call — with `confirm` omitted or false — deletes NOTHING and returns a preview (`confirm_required: true`) naming the entry. Repeat with `confirm: true` to actually delete it. Surface the preview to the user and get their go-ahead before confirming. Destructive and NOT idempotent — once confirmed, calling it again with the same id returns `not found or not accessible`. Prefer setting `status: cancelled` via `roadmap_entry_save` when you only want to mark work as discarded but keep the historical record. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Entry prefix ID (rent_…). | | `confirm` | boolean | Nein | Must be true to delete. Omit/false returns a dry-run preview and deletes nothing. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Entry prefix ID (rent_…)." }, "confirm": { "type": "boolean", "description": "Must be true to delete. Omit/false returns a dry-run preview and deletes nothing." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "deleted": { "type": "boolean", "description": "True once deleted; false on a preview." }, "confirm_required": { "type": "boolean", "description": "True on a preview — call again with confirm: true to delete." }, "id": { "type": "string", "description": "The entry's prefix ID, echoed back." }, "title": { "type": "string", "description": "The entry's title (so the preview is human-readable)." } }, "required": [ "deleted", "id" ], "type": "object" } ``` --- # roadmap_entry_link_project Link Project to Roadmap Entry ## Beschreibung Links a project to a roadmap entry so the entry can carry execution context (which projects are actually delivering it). Constraints: - The project must belong to the same workspace as the roadmap. Cross-workspace links are rejected with a validation error. - Idempotent: re-linking the same project returns the existing link row without raising. Writes an `entry_project_linked` activity row. Reverse with `roadmap_entry_unlink_project`. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `roadmap_entry_id` | string | Ja | Entry prefix ID (rent_…). | | `project_id` | string | Ja | Project prefix ID (proj_…). Must belong to the same workspace as the roadmap. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "roadmap_entry_id": { "type": "string", "description": "Entry prefix ID (rent_…)." }, "project_id": { "type": "string", "description": "Project prefix ID (proj_…). Must belong to the same workspace as the roadmap." } }, "required": [ "account_id", "roadmap_entry_id", "project_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "link": { "type": "object", "properties": { "id": { "type": "string", "description": "Link prefix ID (rep_…)." }, "roadmap_entry_id": { "type": "string", "description": "rent_…" }, "project_id": { "type": "string", "description": "proj_…" }, "project_name": { "type": "string", "description": "Denormalised for convenience — saves a separate `project_get`." } }, "required": [ "id", "roadmap_entry_id", "project_id", "project_name" ] } }, "required": [ "link" ], "type": "object" } ``` --- # roadmap_entry_move Move Roadmap Entry ## Beschreibung Moves a roadmap entry to a different roadmap **in the same workspace**. The entry keeps its title, description, status, dates and every linked project — only its parent roadmap (and a fresh tail position) change. An `entry_moved` activity is written to BOTH roadmaps' feeds. Same-workspace only: an entry inherits its roadmap's workspace and its project links are workspace-bound, so a cross-workspace target is rejected. Move the projects' workspace or unlink first if you need to reorganise across workspaces. Two-step confirmation (the move is not silent): the first call — with `confirm` omitted or false — performs NO change and returns a preview (`confirm_required: true`) describing the source and target. Repeat the call with `confirm: true` to actually move the entry. Surface the preview to the user and get their go-ahead before confirming. Auth: the actor must be able to update both the entry's current roadmap and the target roadmap. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `id` | string | Ja | Entry prefix ID (rent_…). | | `target_roadmap_id` | string | Ja | Destination roadmap prefix ID (rmap_…). Must be in the same workspace as the entry. | | `confirm` | boolean | Nein | Must be true to execute. Omit/false returns a dry-run preview and changes nothing. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "id": { "type": "string", "description": "Entry prefix ID (rent_…)." }, "target_roadmap_id": { "type": "string", "description": "Destination roadmap prefix ID (rmap_…). Must be in the same workspace as the entry." }, "confirm": { "type": "boolean", "description": "Must be true to execute. Omit/false returns a dry-run preview and changes nothing." } }, "required": [ "account_id", "id", "target_roadmap_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "moved": { "type": "boolean", "description": "True once the move has been executed; false on a preview." }, "confirm_required": { "type": "boolean", "description": "True on a preview — call again with confirm: true to execute." }, "from": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "title" ] }, "to": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "title" ] }, "entry": { "type": "object", "description": "The entry payload (current state on preview, post-move state on execute)." } }, "required": [ "moved", "from", "to", "entry" ], "type": "object" } ``` --- # roadmap_entry_save Create or Update Roadmap Entry ## Beschreibung Linear-style upsert for one row inside a roadmap. Omit `id` to create, pass `id` to update. Create requires `roadmap_id`, `title`, AND `due_on`. The entry inherits its workspace from the parent roadmap. This tool can't reparent an entry — use `roadmap_entry_move` to move it to another roadmap in the same workspace. Field semantics: - `status` ∈ {planned, in_progress, done, cancelled}. Defaults to `planned` on create. Status changes write a `RoadmapActivity` row visible via `roadmap_activities`. - Dates are ISO 8601 (`YYYY-MM-DD`). `due_on` must be on or after `starts_on` when both are set. - `due_on` is mandatory and stays mandatory — there's no open-ended state. If the work is genuinely ongoing, split it into time-boxed chunks (e.g. one entry per quarter) rather than picking a fake date. - `starts_on` may be null. An entry with no `starts_on` renders as a milestone (diamond marker on the timeline) at `due_on`. - `position` is a manual integer ordering inside the roadmap; smaller = earlier. Defaults to 0 on create. - `owner_id` accepts an active human workspace member. It defaults to the calling user on create. - Update semantics: fields you omit are left untouched. To attach projects, use `roadmap_entry_link_project` — this tool only manages the entry's own fields. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Entry prefix ID (rent_…). Omit to create. | | `roadmap_id` | string | Nein | Required on create. Roadmap prefix ID (rmap_…). | | `title` | string | Nein | Required on create. | | `description_markdown` | string / null | Nein | Markdown. Empty string clears, null leaves alone. | | `status` | string | Nein | Defaults to planned on create. | | `starts_on` | string / null | Nein | ISO date (YYYY-MM-DD). Null/omit → milestone-style entry. | | `due_on` | string / null | Nein | ISO date (YYYY-MM-DD). REQUIRED on create. Must be >= starts_on when set. | | `position` | integer | Nein | Manual ordering within the roadmap. Defaults to 0. | | `owner_id` | string | Nein | Owner user prefix ID or @handle. Defaults to the caller on create. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Entry prefix ID (rent_…). Omit to create." }, "roadmap_id": { "type": "string", "description": "Required on create. Roadmap prefix ID (rmap_…)." }, "title": { "type": "string", "description": "Required on create." }, "description_markdown": { "type": [ "string", "null" ], "description": "Markdown. Empty string clears, null leaves alone." }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done", "cancelled" ], "description": "Defaults to planned on create." }, "starts_on": { "type": [ "string", "null" ], "description": "ISO date (YYYY-MM-DD). Null/omit → milestone-style entry." }, "due_on": { "type": [ "string", "null" ], "description": "ISO date (YYYY-MM-DD). REQUIRED on create. Must be >= starts_on when set." }, "position": { "type": "integer", "description": "Manual ordering within the roadmap. Defaults to 0." }, "owner_id": { "type": "string", "description": "Owner user prefix ID or @handle. Defaults to the caller on create." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "entry": { "type": "object", "properties": { "id": { "type": "string", "description": "rent_…" }, "title": { "type": "string" }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done", "cancelled" ] }, "starts_on": { "type": [ "string", "null" ] }, "due_on": { "type": [ "string", "null" ] }, "position": { "type": "integer" }, "description_markdown": { "type": [ "string", "null" ] }, "owner": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] }, "projects": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "color": { "type": [ "string", "null" ] } }, "required": [ "id", "name" ] } }, "roadmap": { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "title" ] } }, "required": [ "id", "title", "status", "position", "owner", "projects", "roadmap" ] } }, "required": [ "entry" ], "type": "object" } ``` --- # roadmap_entry_unlink_project Unlink Project from Roadmap Entry ## Beschreibung Removes the link between a project and a roadmap entry. The underlying project is not affected — only the association row is dropped. Idempotent: unlinking an already-unlinked project returns `deleted: true` without error. Writes an `entry_project_unlinked` activity row when a real link was removed. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `roadmap_entry_id` | string | Ja | Entry prefix ID (rent_…). | | `project_id` | string | Ja | Project prefix ID (proj_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "roadmap_entry_id": { "type": "string", "description": "Entry prefix ID (rent_…)." }, "project_id": { "type": "string", "description": "Project prefix ID (proj_…)." } }, "required": [ "account_id", "roadmap_entry_id", "project_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "deleted": { "type": "boolean", "description": "Always true on success, regardless of whether a link actually existed." } }, "required": [ "deleted" ], "type": "object" } ``` --- # roadmap_get Get Roadmap ## Beschreibung Fetches a single roadmap with full Markdown description, every entry in display order, and each entry's linked projects. Use this when you need to read or diff a roadmap's contents. Pair with `roadmap_save` / `roadmap_entry_save` to write back — descriptions round-trip via Markdown ↔ Tiptap without loss. Errors with `not found or not accessible` when the roadmap doesn't exist OR the caller has no access (the message is ambiguous on purpose to prevent ID enumeration). ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Roadmap prefix ID (rmap_…). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Roadmap prefix ID (rmap_…)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "roadmap": { "type": "object", "properties": { "id": { "type": "string", "description": "rmap_…" }, "title": { "type": "string" }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done" ] }, "archived": { "type": "boolean" }, "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "key", "name" ] }, "entry_count": { "type": "integer" }, "updated_at": { "type": "string", "description": "ISO 8601." }, "created_at": { "type": "string", "description": "ISO 8601." }, "description_markdown": { "type": [ "string", "null" ] }, "entries": { "type": "array", "description": "All entries in display order (position asc, id asc).", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "rent_…" }, "title": { "type": "string" }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done", "cancelled" ] }, "starts_on": { "type": [ "string", "null" ], "description": "ISO date (YYYY-MM-DD) or null." }, "due_on": { "type": [ "string", "null" ], "description": "ISO date (YYYY-MM-DD)." }, "position": { "type": "integer", "description": "Manual ordering within the roadmap." }, "description_markdown": { "type": [ "string", "null" ] }, "owner": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "name" ] }, "projects": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "proj_…" }, "name": { "type": "string" }, "color": { "type": [ "string", "null" ] } }, "required": [ "id", "name" ] } } }, "required": [ "id", "title", "status", "position", "owner", "projects" ] } } }, "required": [ "id", "title", "status", "archived", "workspace", "entries" ] } }, "required": [ "roadmap" ], "type": "object" } ``` --- # roadmap_list List Roadmaps ## Beschreibung Lists roadmaps the caller can read in the current account. Visibility: admins and employers see every roadmap in the account. Other members see only roadmaps in workspaces they're a member of. Filters: - `workspace_id` accepts the workspace's prefix ID (`wsp_…`) or its short key (e.g. `ENG`). - `archived` defaults to false; set true to list archived roadmaps instead of active ones. - `query` is a case-insensitive substring match on `title`. Returns rows ordered by `updated_at` desc, capped at 250. Pass any row's `id` (rmap_…) to `roadmap_get` for the full payload including entries and linked projects. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `workspace_id` | string | Nein | Workspace prefix ID (wsp_…) or short key (e.g. ENG). | | `archived` | boolean | Nein | Default false. Set true to list archived roadmaps instead of active ones. | | `query` | string | Nein | Case-insensitive substring match on title. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "workspace_id": { "type": "string", "description": "Workspace prefix ID (wsp_…) or short key (e.g. ENG)." }, "archived": { "type": "boolean", "description": "Default false. Set true to list archived roadmaps instead of active ones." }, "query": { "type": "string", "description": "Case-insensitive substring match on title." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "roadmaps": { "type": "array", "description": "Up to 250 rows, sorted by updated_at desc.", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Roadmap prefix ID (rmap_…)." }, "title": { "type": "string" }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done" ], "description": "Editorial state of the roadmap." }, "archived": { "type": "boolean" }, "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "key", "name" ] }, "entry_count": { "type": "integer" }, "updated_at": { "type": "string", "description": "ISO 8601." }, "created_at": { "type": "string", "description": "ISO 8601." } }, "required": [ "id", "title", "status", "archived", "workspace", "entry_count", "updated_at", "created_at" ] } } }, "required": [ "roadmaps" ], "type": "object" } ``` --- # roadmap_save Create or Update Roadmap ## Beschreibung Linear-style upsert for a roadmap (the container, not its entries). Omit `id` to create, pass `id` to update. Create requires `title` AND `workspace_id`. Workspace is immutable after creation — `workspace_id` is silently ignored on update (entries are workspace-scoped, so switching workspaces would orphan them). Update semantics: - Fields you omit are left untouched (no silent clears). - `archived: true` archives, `false` unarchives, omitted leaves the state alone. Independent of `status`. - `status` is one of `planned` / `in_progress` / `done`. - Description accepts Markdown and round-trips via Tiptap JSON. Passing an empty string clears the description. To manage entries, use `roadmap_entry_save` / `roadmap_entry_destroy` — this tool doesn't touch them. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | Roadmap prefix ID (rmap_…). Omit to create. | | `workspace_id` | string | Nein | Required on create. Workspace prefix ID or short key (e.g. ENG). Ignored on update. | | `title` | string | Nein | Required on create. | | `status` | string | Nein | Editorial state. Defaults to planned on create; left alone on update when omitted. | | `description_markdown` | string / null | Nein | Markdown. Empty string clears the description; null leaves it alone. | | `archived` | boolean | Nein | true=archive, false=unarchive, omit=leave alone. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Roadmap prefix ID (rmap_…). Omit to create." }, "workspace_id": { "type": "string", "description": "Required on create. Workspace prefix ID or short key (e.g. ENG). Ignored on update." }, "title": { "type": "string", "description": "Required on create." }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done" ], "description": "Editorial state. Defaults to planned on create; left alone on update when omitted." }, "description_markdown": { "type": [ "string", "null" ], "description": "Markdown. Empty string clears the description; null leaves it alone." }, "archived": { "type": "boolean", "description": "true=archive, false=unarchive, omit=leave alone." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "roadmap": { "type": "object", "properties": { "id": { "type": "string", "description": "rmap_…" }, "title": { "type": "string" }, "status": { "type": "string", "enum": [ "planned", "in_progress", "done" ] }, "archived": { "type": "boolean" }, "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "name": { "type": "string" } }, "required": [ "id", "key", "name" ] }, "entry_count": { "type": "integer" }, "updated_at": { "type": "string", "description": "ISO 8601." }, "created_at": { "type": "string", "description": "ISO 8601." } }, "required": [ "id", "title", "status", "archived", "workspace", "entry_count", "updated_at", "created_at" ] } }, "required": [ "roadmap" ], "type": "object" } ``` --- # standup_list Get Standup Entries ## Beschreibung Reads daily standup entries (Yesterday / Today / Blockers). Unique per `(user, account, report_date)` — one per person per day. Admin / employer see all members' entries (filter via `user_id`); regular members see only their own. - `blocked` is derived from `blockers.present?` when the flag column is nil; when explicitly set, that value wins. - `submitted == completed_at.present?`. Drafts may be partial. - `previous_completed: false` on a submitted entry → carryover signal (yesterday's plan didn't finish). - Sorted `report_date DESC, user_id ASC`, capped at 500 rows. ## Zugriff Zugriffsprofil: `gated`. Module: `standups`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `user_id` | string | Nein | User prefix ID (user_…) or @handle / handle (e.g., 'sam' or '@sam'). Admin/employer only for foreign users — regular members may pass their own or omit. | | `start_date` | string | Nein | Inclusive lower bound on report_date (YYYY-MM-DD). Use alone for a single day. | | `end_date` | string | Nein | Inclusive upper bound on report_date. Defaults to start_date when only start_date is given — pair them for a range. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "user_id": { "type": "string", "description": "User prefix ID (user_…) or @handle / handle (e.g., 'sam' or '@sam'). Admin/employer only for foreign users — regular members may pass their own or omit." }, "start_date": { "type": "string", "format": "date", "description": "Inclusive lower bound on report_date (YYYY-MM-DD). Use alone for a single day." }, "end_date": { "type": "string", "format": "date", "description": "Inclusive upper bound on report_date. Defaults to start_date when only start_date is given — pair them for a range." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "standup_entries": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Standup prefix ID (sup_…). Unique per (user, account, report_date)." }, "user": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } } }, "report_date": { "type": "string", "format": "date" }, "previous": { "type": [ "string", "null" ], "description": "Yesterday's work / outcomes." }, "next": { "type": [ "string", "null" ], "description": "Today's plan." }, "blockers": { "type": [ "string", "null" ] }, "blocked": { "type": "boolean", "description": "Derived from blockers.present? when the flag column is nil; otherwise the stored value." }, "previous_completed": { "type": [ "boolean", "null" ], "description": "User confirmed yesterday's plan finished." }, "submitted": { "type": "boolean", "description": "True iff completed_at is set — otherwise it's a draft." }, "completed_at": { "type": [ "string", "null" ], "format": "date-time" } }, "required": [ "id", "user", "report_date", "blocked", "submitted" ] } } }, "required": [ "standup_entries" ], "type": "object" } ``` --- # standup_save Create or Update Standup Entry ## Beschreibung Linear-style upsert for a daily standup entry (Yesterday / Today / Blockers). Omit `id` to upsert by `(user, account, report_date)` — the same shape the web form uses. Pass `id` (sup_…) to update a specific entry. - `report_date` defaults to today. One entry per (user, date). - `submit: false` (the default) leaves the entry in draft (completed_at IS NULL) so a human can review in the UI before submitting. Set `submit: true` to submit immediately; on an already-submitted entry, `submit: true` is a no-op (completed_at is preserved). - At least one of `previous` / `next` / `blockers` must be non-blank across create + update combined (matches the model's `present_content` validation). - `previous_completed` is the "yesterday's plan finished?" carryover flag surfaced by `standup_list`. Pass `true` / `false` explicitly; omit to leave unchanged. ## Body format Bodies are stored as Markdown and rendered through the Standups account pipeline (ENG-1387). Write bullet lists; the renderer decorates each line with a coloured status pill when it ends with `result: `. Ticket keys like `ENG-1234` are autolinked automatically — do not wrap them in Markdown links yourself. Recognised status slugs (case-insensitive): `done` (also: ok, completed, shipped, landed), `in progress` (wip, ongoing, started, working), `in review` (review, reviewing, pr), `blocked` (blocker, waiting, stuck), `postponed` (on hold, paused, deferred, delayed, later), `cancelled` (canceled, dropped, abandoned, skipped). Anything else falls back to a neutral `planned` pill. Example `previous` body: - Wrapped up ENG-1387 rendering pipeline, result: done - Reviewed PR for ENG-1400, result: in review - Waiting on staging deploy for ENG-1234, result: blocked Plain paragraphs and lists without `result: …` render fine too — they just skip the pill decoration. ## Access (StandupEntryPolicy) - Regular members can only save their own entry — a `user_id` for someone else is silently forced back to the caller. - Admin / employer can `user_id` to any active member. ## Zugriff Zugriffsprofil: `gated`. Module: `standups`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | StandupEntry prefix ID (sup_…). Omit to upsert by (user, report_date). | | `user_id` | string | Nein | User prefix (user_…) or @handle. Admin / employer only; regular members always save their own row. | | `report_date` | string | Nein | YYYY-MM-DD. Defaults to today. | | `previous` | string / null | Nein | Yesterday's work / outcomes. | | `next` | string / null | Nein | Today's plan. | | `blockers` | string / null | Nein | Blockers. Non-blank flips derived `blocked` on. | | `previous_completed` | boolean / null | Nein | User confirmed yesterday's plan finished. | | `submit` | boolean | Nein | true = submit now; false (default) = leave as draft. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "StandupEntry prefix ID (sup_…). Omit to upsert by (user, report_date)." }, "user_id": { "type": "string", "description": "User prefix (user_…) or @handle. Admin / employer only; regular members always save their own row." }, "report_date": { "type": "string", "format": "date", "description": "YYYY-MM-DD. Defaults to today." }, "previous": { "type": [ "string", "null" ], "description": "Yesterday's work / outcomes." }, "next": { "type": [ "string", "null" ], "description": "Today's plan." }, "blockers": { "type": [ "string", "null" ], "description": "Blockers. Non-blank flips derived `blocked` on." }, "previous_completed": { "type": [ "boolean", "null" ], "description": "User confirmed yesterday's plan finished." }, "submit": { "type": "boolean", "description": "true = submit now; false (default) = leave as draft." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "id": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": "string" }, "handle": { "type": "string" }, "name": { "type": "string" } } }, "report_date": { "type": "string", "format": "date" }, "previous": { "type": [ "string", "null" ] }, "next": { "type": [ "string", "null" ] }, "blockers": { "type": [ "string", "null" ] }, "blocked": { "type": "boolean" }, "previous_completed": { "type": [ "boolean", "null" ] }, "submitted": { "type": "boolean" }, "completed_at": { "type": [ "string", "null" ], "format": "date-time" }, "created": { "type": "boolean", "description": "true iff this call inserted a fresh row (as opposed to updating an existing draft/submitted one)." } }, "required": [ "id", "user", "report_date", "blocked", "submitted", "created" ], "type": "object" } ``` --- # task_comment_save Comment on a Task ## Beschreibung Posts a Markdown comment on a task; the body is converted to Tiptap JSON for storage. Pair with `attachment_upload` + `attachment_ids` to ship screenshots / logs alongside the comment. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `task_id` | string | Ja | Task prefix or KEY-N. | | `body_markdown` | string | Nein | | | `parent_id` | string | Nein | Prefix ID (cmt_…) of the comment this is a reply to. One level only — replying to a reply re-roots at the original parent. | | `attachment_ids` | array | Nein | Attachment handles from `attachment_upload` — att_… ids or file_urls. Files appear under the comment in the task UI. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "task_id": { "type": "string", "description": "Task prefix or KEY-N." }, "body_markdown": { "type": "string" }, "parent_id": { "type": "string", "description": "Prefix ID (cmt_…) of the comment this is a reply to. One level only — replying to a reply re-roots at the original parent." }, "attachment_ids": { "type": "array", "items": { "type": "string" }, "description": "Attachment handles from `attachment_upload` — att_… ids or file_urls. Files appear under the comment in the task UI." } }, "required": [ "account_id", "task_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "comment": { "type": "object", "properties": { "id": { "type": "string" }, "body_markdown": { "type": "string" } }, "required": [ "id", "body_markdown" ] } }, "required": [ "comment" ], "type": "object" } ``` --- # task_get Get Task ## Beschreibung Fetches a single task by prefix id (`task_…`) or by issue key in the form `{WORKSPACE_KEY}-{number}` (e.g. `ENG-3`, `VSUP-1000`). Returns the full description as Markdown plus comments (chronological), parent/sub-issues, the Blocks / Blocked-by / Related / Duplicate relations, and — when `include_activity` is true — the activity timeline (status flips, assignee changes, comments, etc.) as humanised event rows. The payload's `url` field is the canonical web URL. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Task prefix ID (task_…) or issue key (ENG-3). | | `include_comments` | boolean | Nein | | | `include_relations` | boolean | Nein | | | `include_activity` | boolean | Nein | Include `activity[]` — chronological event log (created / status_changed / assignee_changed / commented / …). Comments also appear here as `commented` rows alongside the dedicated `comments[]` array (ENG-1146). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Task prefix ID (task_…) or issue key (ENG-3)." }, "include_comments": { "type": "boolean", "default": true }, "include_relations": { "type": "boolean", "default": true }, "include_activity": { "type": "boolean", "default": false, "description": "Include `activity[]` — chronological event log (created / status_changed / assignee_changed / commented / …). Comments also appear here as `commented` rows alongside the dedicated `comments[]` array (ENG-1146)." } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "task": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "key", "title" ] } }, "required": [ "task" ], "type": "object" } ``` --- # task_list List Tasks ## Beschreibung Lists tasks (issues) the caller can read in the account. Filters: project, workspace, status (configured TaskStatus name or symbolic key), priority, assignee, label, free-text search on the title. Sorted by `updated_at DESC`, capped at 250 rows. Each row carries a canonical `url` field (`/tasks/{WORKSPACE_KEY}-{number}`) that an agent can paste back to humans without inventing a path. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `project_id` | string | Nein | Project prefix ID or slug. | | `workspace_id` | string | Nein | Workspace prefix ID or key. | | `cycle_id` | string | Nein | Cycle prefix ID (cyc_…). Filters to tasks attached to that cycle. | | `status` | string | Nein | Task status name (e.g. 'In progress') or symbolic key (e.g. 'todo'). | | `priority` | string | Nein | Priority enum key (urgent / high / medium / low / no_priority). | | `assignee` | string | Nein | User prefix ID or @handle. 'me' resolves to the caller; 'none' filters unassigned. | | `label` | string | Nein | Label name or prefix ID. | | `subscribed` | boolean | Nein | Only tasks you are subscribed to. | | `series_id` | string | Nein | Recurring task series prefix ID (trs_…). Filters generated parent tasks. | | `query` | string | Nein | Substring match on title. | | `limit` | integer | Nein | Max rows (default 50, max 250). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "project_id": { "type": "string", "description": "Project prefix ID or slug." }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key." }, "cycle_id": { "type": "string", "description": "Cycle prefix ID (cyc_…). Filters to tasks attached to that cycle." }, "status": { "type": "string", "description": "Task status name (e.g. 'In progress') or symbolic key (e.g. 'todo')." }, "priority": { "type": "string", "description": "Priority enum key (urgent / high / medium / low / no_priority)." }, "assignee": { "type": "string", "description": "User prefix ID or @handle. 'me' resolves to the caller; 'none' filters unassigned." }, "label": { "type": "string", "description": "Label name or prefix ID." }, "subscribed": { "type": "boolean", "description": "Only tasks you are subscribed to." }, "series_id": { "type": "string", "description": "Recurring task series prefix ID (trs_…). Filters generated parent tasks." }, "query": { "type": "string", "description": "Substring match on title." }, "limit": { "type": "integer", "default": 50, "description": "Max rows (default 50, max 250)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "tasks": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "key", "title" ] } } }, "required": [ "tasks" ], "type": "object" } ``` --- # task_move_to_workspace Move Task To Workspace ## Beschreibung Moves a task to a different workspace. The task keeps its comments, attachments, history, assignee, due date, estimate and priority — but gets a fresh issue key on the target workspace (e.g. ENG-12 → DEV-5). Labels are stripped (labels are workspace-bound); the project is cleared unless you pass `project_id` of a project that belongs to the target workspace. Status is remapped to the equivalent column in the target workspace when one exists (by `symbolic_key`). Auth: moving an issue changes its identifier and outer access boundary, so only account admins can perform this operation. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `task_id` | string | Ja | Task prefix ID (task_…) or issue key (ENG-12). | | `workspace_id` | string | Ja | Target workspace — prefix ID (wsp_…) or short key (e.g. DEV). Legacy team_ links remain accepted during migration. | | `project_id` | string | Nein | Optional project prefix ID (proj_…). Must belong to the target workspace. Pass empty / omit to leave the task project-less after the move. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "task_id": { "type": "string", "description": "Task prefix ID (task_…) or issue key (ENG-12)." }, "workspace_id": { "type": "string", "description": "Target workspace — prefix ID (wsp_…) or short key (e.g. DEV). Legacy team_ links remain accepted during migration." }, "project_id": { "type": "string", "description": "Optional project prefix ID (proj_…). Must belong to the target workspace. Pass empty / omit to leave the task project-less after the move." } }, "required": [ "account_id", "task_id", "workspace_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "task": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "title": { "type": "string" }, "previous_key": { "type": "string" }, "cleared": { "type": "array", "items": { "type": "string" } } }, "required": [ "id", "key", "title", "previous_key", "cleared" ] } }, "required": [ "task" ], "type": "object" } ``` --- # task_relation_save Set Task Relation ## Beschreibung Add or remove a task relation within the same account. source_task watches target_task resumes the agent's source task when the target changes. Task delegation creates this relation automatically. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `source_task_id` | string | Ja | | | `target_task_id` | string | Ja | | | `kind` | string | Ja | | | `active` | boolean | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "source_task_id": { "type": "string" }, "target_task_id": { "type": "string" }, "kind": { "type": "string", "enum": [ "blocks", "related_to", "duplicate_of", "watches" ] }, "active": { "type": "boolean", "default": true } }, "required": [ "account_id", "source_task_id", "target_task_id", "kind" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "relation": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "source_task_id": { "type": "string" }, "target_task_id": { "type": "string" }, "kind": { "type": "string" }, "active": { "type": "boolean" } }, "required": [ "id", "source_task_id", "target_task_id", "kind", "active" ] } }, "required": [ "relation" ], "type": "object" } ``` --- # task_save Create or Update Task ## Beschreibung Linear-style upsert. Pass `id` (prefix or `KEY-N`) to update, omit it to create. On create the workspace is required (omit when updating). Description accepts Markdown and is converted to Tiptap JSON for storage; readers get Markdown back via `task_get` so the round-trip is symmetric. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `idempotency_key` | string | Nein | Stable unique key for this intended task. Reuse on retries. Required when delegating from a task session; creates a subscription that resumes your coordinating task. | | `id` | string | Nein | Task prefix ID or KEY-N. Omit to create. | | `workspace_id` | string | Nein | Workspace prefix ID or key. Required on create. | | `project_id` | string / null | Nein | Project prefix ID (proj_…) or slug. Pass null to detach the task from its project. | | `cycle_id` | string / null | Nein | Cycle prefix ID (cyc_…). Cycle must belong to the same workspace as the task; pass null to detach. | | `pinned_to_cycle` | boolean | Nein | ENG-1094. When true, the task stays on its current cycle when that cycle closes (excluded from carry-over). | | `parent_task_id` | string / null | Nein | Parent task prefix ID (task_…) or KEY-N. Pass null to make this a top-level task. | | `title` | string | Nein | | | `description_markdown` | string / null | Nein | | | `status` | string | Nein | TaskStatus name or symbolic key. | | `priority` | string | Nein | | | `assignee` | string / null | Nein | User prefix or @handle. 'none' clears. | | `start_on` | string / null | Nein | ISO date YYYY-MM-DD or null to clear. Optional, must be on or before due_on when both are set. | | `due_on` | string / null | Nein | ISO date YYYY-MM-DD or null to clear. | | `start_at` | string / null | Nein | ISO 8601 timestamp with UTC offset. Sets start_on in time_zone. Null removes only the time. Automatic agent work waits until this instant. | | `due_at` | string / null | Nein | ISO 8601 timestamp with UTC offset. Sets due_on in time_zone. Null removes only the time. | | `time_zone` | string | Nein | Task time zone, e.g. Europe/Berlin. Defaults to the creator's time zone. | | `estimate_points` | integer / null | Nein | | | `labels` | array | Nein | List of label names or prefix IDs. | | `attachment_ids` | array | Nein | Attachment handles from `attachment_upload` — att_… ids or file_urls. Files appear in the task's attachments list. Existing attachments are kept; pass an empty array to add nothing new (use the web UI to remove). | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "idempotency_key": { "type": "string", "description": "Stable unique key for this intended task. Reuse on retries. Required when delegating from a task session; creates a subscription that resumes your coordinating task." }, "id": { "type": "string", "description": "Task prefix ID or KEY-N. Omit to create." }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key. Required on create." }, "project_id": { "type": [ "string", "null" ], "description": "Project prefix ID (proj_…) or slug. Pass null to detach the task from its project." }, "cycle_id": { "type": [ "string", "null" ], "description": "Cycle prefix ID (cyc_…). Cycle must belong to the same workspace as the task; pass null to detach." }, "pinned_to_cycle": { "type": "boolean", "description": "ENG-1094. When true, the task stays on its current cycle when that cycle closes (excluded from carry-over)." }, "parent_task_id": { "type": [ "string", "null" ], "description": "Parent task prefix ID (task_…) or KEY-N. Pass null to make this a top-level task." }, "title": { "type": "string" }, "description_markdown": { "type": [ "string", "null" ] }, "status": { "type": "string", "description": "TaskStatus name or symbolic key." }, "priority": { "type": "string" }, "assignee": { "type": [ "string", "null" ], "description": "User prefix or @handle. 'none' clears." }, "start_on": { "type": [ "string", "null" ], "description": "ISO date YYYY-MM-DD or null to clear. Optional, must be on or before due_on when both are set." }, "due_on": { "type": [ "string", "null" ], "description": "ISO date YYYY-MM-DD or null to clear." }, "start_at": { "type": [ "string", "null" ], "description": "ISO 8601 timestamp with UTC offset. Sets start_on in time_zone. Null removes only the time. Automatic agent work waits until this instant." }, "due_at": { "type": [ "string", "null" ], "description": "ISO 8601 timestamp with UTC offset. Sets due_on in time_zone. Null removes only the time." }, "time_zone": { "type": "string", "description": "Task time zone, e.g. Europe/Berlin. Defaults to the creator's time zone." }, "estimate_points": { "type": [ "integer", "null" ] }, "labels": { "type": "array", "items": { "type": "string" }, "description": "List of label names or prefix IDs." }, "attachment_ids": { "type": "array", "items": { "type": "string" }, "description": "Attachment handles from `attachment_upload` — att_… ids or file_urls. Files appear in the task's attachments list. Existing attachments are kept; pass an empty array to add nothing new (use the web UI to remove)." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "task": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "title": { "type": "string" } }, "required": [ "id", "key", "title" ] } }, "required": [ "task" ], "type": "object" } ``` --- # task_series_delete Delete Recurring Task Series ## Beschreibung Delete a recurring series and stop future generation. All already created tasks and subtasks are kept. Requires creator, workspace manager or account admin and expected_version from task_series_get. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | | | `expected_version` | integer | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string" }, "expected_version": { "type": "integer" } }, "required": [ "account_id", "id", "expected_version" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "deleted": { "type": "boolean" }, "id": { "type": "string" }, "existing_tasks_kept": { "type": "boolean" } }, "required": [ "deleted", "id", "existing_tasks_kept" ], "type": "object" } ``` --- # task_series_get Get Recurring Task Series ## Beschreibung Read a recurring task template, schedule, version and occurrence history. Tasks are independent copies. The cursor uses planned due dates and is not changed by editing or completing a task. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Ja | Series prefix ID (trs_…). | | `before` | string | Nein | Occurrence prefix ID for older history. | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string", "description": "Series prefix ID (trs_…)." }, "before": { "type": "string", "description": "Occurrence prefix ID for older history." }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "account_id", "id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "series": { "type": "object" }, "occurrences": { "type": "array", "items": { "type": "object" } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "series", "occurrences", "next_cursor" ], "type": "object" } ``` --- # task_series_list List Recurring Task Series ## Beschreibung List accessible recurring task series, including paused and blocked schedules. Use task_series_get for the template and generated task history. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `workspace_id` | string | Nein | Workspace prefix ID or key. | | `paused` | boolean | Nein | | | `after` | string | Nein | Series prefix ID for the next page. | | `limit` | integer | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "workspace_id": { "type": "string", "description": "Workspace prefix ID or key." }, "paused": { "type": "boolean" }, "after": { "type": "string", "description": "Series prefix ID for the next page." }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "series": { "type": "array", "items": { "type": "object" } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "series", "next_cursor" ], "type": "object" } ``` --- # task_series_save Save Recurring Task Series ## Beschreibung Create or update a recurring task series. Creation immediately makes one task at the first scheduled due date on or after today. Later tasks are created at 00:01 in the series time zone the day after the previous PLANNED due date, regardless of completion. days/weeks/months/years, interval 1–12; month ends clamp. Missed historical dates are skipped. Create requires workspace_id, frequency, anchor_on and time_zone, plus template.title or source_task_id. source_task_id copies the task and its subtasks into a NEW series and NEW tasks; the source stays unchanged. Update requires id and expected_version from task_series_get. Omitted fields are preserved; template patches root fields, children replaces the entire child tree. Changing anchor_on creates an ADDITIONAL task immediately and resets the schedule. Content/interval edits preserve existing tasks and cursor. paused stops generation; resuming skips missed history. auto_start_agents defaults false: assigned agents wait for a status/assignment change. Every save makes the caller responsible for future generation; revoked workspace/feature access blocks it. Use a stable idempotency_key when creating to make retries safe. Do not use task_save to edit a series. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `id` | string | Nein | | | `expected_version` | integer | Nein | | | `workspace_id` | string | Nein | | | `source_task_id` | string | Nein | | | `idempotency_key` | string | Nein | | | `frequency` | string | Nein | | | `interval` | integer | Nein | | | `anchor_on` | string | Nein | ISO date YYYY-MM-DD. Changing this restarts the schedule and creates another task. | | `time_zone` | string | Nein | IANA zone, e.g. Europe/Berlin. | | `paused` | boolean | Nein | | | `auto_start_agents` | boolean | Nein | | | `start_time` | string / null | Nein | Optional local HH:MM start time on each planned date, e.g. 08:00 or 20:00. Automatic agent work waits until this time. | | `due_time` | string / null | Nein | Optional local HH:MM deadline on each planned date. Null removes the time. Must not be before start_time. | | `template` | object | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "id": { "type": "string" }, "expected_version": { "type": "integer" }, "workspace_id": { "type": "string" }, "source_task_id": { "type": "string" }, "idempotency_key": { "type": "string", "maxLength": 200 }, "frequency": { "type": "string", "enum": [ "days", "weeks", "months", "years" ] }, "interval": { "type": "integer", "minimum": 1, "maximum": 12 }, "anchor_on": { "type": "string", "description": "ISO date YYYY-MM-DD. Changing this restarts the schedule and creates another task." }, "time_zone": { "type": "string", "description": "IANA zone, e.g. Europe/Berlin." }, "paused": { "type": "boolean" }, "auto_start_agents": { "type": "boolean" }, "start_time": { "type": [ "string", "null" ], "description": "Optional local HH:MM start time on each planned date, e.g. 08:00 or 20:00. Automatic agent work waits until this time." }, "due_time": { "type": [ "string", "null" ], "description": "Optional local HH:MM deadline on each planned date. Null removes the time. Must not be before start_time." }, "template": { "type": "object", "properties": { "title": { "type": "string", "maxLength": 200 }, "description_markdown": { "type": "string", "maxLength": 100000 }, "priority": { "type": "string", "enum": [ "no_priority", "urgent", "high", "medium", "low" ] }, "status_id": { "type": "string", "description": "Workspace task status prefix ID (tst_…)." }, "assignee_id": { "type": [ "string", "null" ], "description": "User prefix ID (user_…), null to clear." }, "project_id": { "type": [ "string", "null" ], "description": "Project prefix ID (proj_…), null to clear." }, "estimate_points": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 999 }, "label_ids": { "type": "array", "items": { "type": "string" }, "maxItems": 50 }, "children": { "type": "array", "maxItems": 50, "items": { "type": "object", "description": "Child template with the same fields; nested children up to 5 levels, 50 total.", "properties": { "title": { "type": "string", "maxLength": 200 }, "description_markdown": { "type": "string", "maxLength": 100000 }, "priority": { "type": "string", "enum": [ "no_priority", "urgent", "high", "medium", "low" ] }, "status_id": { "type": "string", "description": "Workspace task status prefix ID (tst_…)." }, "assignee_id": { "type": [ "string", "null" ], "description": "User prefix ID (user_…), null to clear." }, "project_id": { "type": [ "string", "null" ], "description": "Project prefix ID (proj_…), null to clear." }, "estimate_points": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 999 }, "label_ids": { "type": "array", "items": { "type": "string" }, "maxItems": 50 }, "children": { "type": "array", "items": { "type": "object" } } } } } }, "additionalProperties": false } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "series": { "type": "object" } }, "required": [ "series" ], "type": "object" } ``` --- # task_wait Wait for Watched Tasks ## Beschreibung Yield your current task turn while waiting for subscribed tasks. No polling or empty progress comment is needed. Finish your response after calling; relevant changes resume this same task session automatically. Does not complete the task. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "waiting": { "type": "boolean" }, "pending_tasks": { "type": "array", "items": { "type": "object" } }, "task_id": { "type": "string" } }, "required": [ "waiting", "pending_tasks", "task_id" ], "type": "object" } ``` --- # task_watch Subscribe to Task ## Beschreibung Subscribe or unsubscribe yourself to task changes and Inbox notifications. Use task_relation_save with kind=watches for task-to-task coordination. Subscribing grants no additional access. ## Zugriff Zugriffsprofil: `gated`. Module: `projects_tasks`, `simple_projects_tasks`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | | | `task_id` | string | Ja | | | `active` | boolean | Nein | | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string" }, "task_id": { "type": "string" }, "active": { "type": "boolean", "default": true } }, "required": [ "account_id", "task_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "subscription": { "type": "object", "properties": { "id": { "type": "string" }, "active": { "type": "boolean" }, "task_id": { "type": "string" } }, "required": [ "id", "active", "task_id" ] } }, "required": [ "subscription" ], "type": "object" } ``` --- # timeclock_list Get Time Clocks ## Beschreibung Reads TimeClock entries (check-in / check-out records). One row per work/pause session, or a full sick/vacation day. Admin / employer see every member's entries (and may filter by `user_id`); regular members see only their own and can't pass a foreign `user_id`. - `checkin_out` is the real field name (not `checkout_at`). - `duration_seconds` is null on open entries (`is_open: true`) so sums stay safely additive without filtering. - `created_on` is a local-time date — may differ from `checkin_at.to_date` for late-night sessions. - Full-day sick/vacation still use 00:00–23:59 pair, `category: "work"`. - `comment == "auto closed"` flags nightly auto-close sweeps. - Sorted `checkin_at DESC`, capped at 500 rows. ## Zugriff Zugriffsprofil: `gated`. Module: `timeclock`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (e.g., acct_abc123). | | `user_id` | string | Nein | User prefix ID (user_…) or @handle / handle (e.g., 'sam' or '@sam'). Admin/employer only for foreign users. | | `start_date` | string | Nein | Inclusive lower bound on created_on (YYYY-MM-DD). Use alone for a single day. | | `end_date` | string | Nein | Inclusive upper bound on created_on. Defaults to start_date when only start_date is given — pair them for a range. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (e.g., acct_abc123)." }, "user_id": { "type": "string", "description": "User prefix ID (user_…) or @handle / handle (e.g., 'sam' or '@sam'). Admin/employer only for foreign users." }, "start_date": { "type": "string", "format": "date", "description": "Inclusive lower bound on created_on (YYYY-MM-DD). Use alone for a single day." }, "end_date": { "type": "string", "format": "date", "description": "Inclusive upper bound on created_on. Defaults to start_date when only start_date is given — pair them for a range." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "time_clocks": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "TimeClock prefix ID (clk_…)." }, "user": { "type": "object", "properties": { "id": { "type": [ "string", "null" ] }, "handle": { "type": [ "string", "null" ] }, "name": { "type": "string" } } }, "created_on": { "type": "string", "format": "date", "description": "Calendar day the entry belongs to (local-time assigned at check-in; may differ from checkin_at.to_date for late-night sessions)." }, "checkin_at": { "type": [ "string", "null" ], "format": "date-time" }, "checkin_out": { "type": [ "string", "null" ], "format": "date-time", "description": "Null when entry is still open. Field name is intentional — not a typo for checkout_at." }, "is_open": { "type": "boolean", "description": "True iff checkin_out is null." }, "category": { "type": "string", "enum": [ "work", "pause" ] }, "work_location_type": { "type": [ "string", "null" ], "enum": [ null, "remote", "on_site" ] }, "sick_day": { "type": "boolean" }, "vacation_day": { "type": "boolean" }, "comment": { "type": [ "string", "null" ], "description": "AUTO_CHECKOUT_COMMENT='auto closed' marks entries closed by the nightly sweep." }, "duration_seconds": { "type": [ "integer", "null" ], "description": "Null on open entries to keep sums safely additive." } }, "required": [ "id", "user", "created_on", "is_open", "category", "sick_day", "vacation_day" ] } } }, "required": [ "time_clocks" ], "type": "object" } ``` --- # whoami Who am I ## Beschreibung Returns your own identity and the account you act in. Call this FIRST in a session: every account-scoped tool requires an `account_id`, and this is where you get it — never invent or guess one. When you belong to exactly one account, `account_id` is that account and you can pass it to every other tool as-is. When you belong to several, `account_id` is null and you must choose from `accounts` (a channel or task you were asked about belongs to exactly one of them). No parameters. Read-only; safe to call at any time. ## Zugriff Zugriffsprofil: `basic`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter Dieses Tool benötigt keine Parameter. ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": {}, "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "current_user": { "type": "object", "properties": { "id": { "type": "string", "description": "User prefix ID (user_…)." }, "handle": { "type": "string" }, "name": { "type": "string" }, "is_agent": { "type": "boolean", "description": "True when you are a bot identity." }, "db_id": { "type": "integer", "description": "Integer PK — matches user.db_id in chat / time-clock / standup rows." } }, "required": [ "id", "handle", "name", "is_agent", "db_id" ] }, "account_id": { "type": [ "string", "null" ], "description": "The account to pass as account_id — set when you belong to exactly one, null when you must choose." }, "accounts": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "name": { "type": "string" }, "personal": { "type": "boolean" }, "roles": { "type": "array", "items": { "type": "string", "enum": [ "admin", "employer" ] }, "description": "Empty array = regular member." } }, "required": [ "id", "name", "personal", "roles" ] } } }, "required": [ "current_user", "account_id", "accounts" ], "type": "object" } ``` --- # workspace_list List Workspaces ## Beschreibung Lists visible active workspaces in navigation order. Each workspace carries the short `key` prefix used to compose issue keys (`{key}-{number}`, e.g. `ENG-128`) and the membership role of the calling user. Pass include_archived: true to include archived workspaces. Admins and employers can pass management: true to list all workspaces they can administer, including those they haven't joined. Agent workspace grants still apply. Use workspace_save to create, edit, archive or restore workspaces. ENG-1089 — each row also carries the workspace's `cycles` config block (enabled flag, duration in weeks or custom days, cooldown, start day, auto-create count, estimates_required). Useful when an agent needs to know how the workspace is set up before it talks about sprint windows or velocity. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `include_archived` | boolean | Nein | | | `management` | boolean | Nein | Admin/employer only: include workspaces you can administer without being a member. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "include_archived": { "type": "boolean", "default": false }, "management": { "type": "boolean", "default": false, "description": "Admin/employer only: include workspaces you can administer without being a member." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "workspaces": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "key": { "type": "string" }, "color": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "icon_emoji": { "type": [ "string", "null" ] }, "archived": { "type": "boolean" }, "general": { "type": "boolean" }, "key_editable": { "type": "boolean" }, "tasks_enabled": { "type": "boolean" }, "subtasks_enabled": { "type": "boolean" }, "recurring_tasks_enabled": { "type": "boolean" }, "projects_enabled": { "type": "boolean" }, "roadmaps_enabled": { "type": "boolean" }, "estimates_enabled": { "type": "boolean" }, "estimate_scale": { "type": "string" }, "role": { "type": [ "string", "null" ], "description": "manager / member / null when caller is not on the workspace." }, "cycles": { "type": "object", "description": "Per-workspace cycles config (ENG-1089). Most workspaces keep defaults; only meaningful once `enabled` is true.", "properties": { "enabled": { "type": "boolean" }, "duration_weeks": { "type": [ "integer", "null" ], "description": "1-4 weeks, or null when running on custom_days." }, "custom_days": { "type": [ "integer", "null" ], "description": "Cycle length in days when duration_weeks is null." }, "duration_days": { "type": [ "integer", "null" ], "description": "Collapsed day count — duration_weeks * 7 or custom_days, whichever is set." }, "cooldown_weeks": { "type": "integer", "description": "Gap between consecutive cycles, in weeks." }, "start_day": { "type": "integer", "description": "Date#wday-style: 0 = Sunday, 1 = Monday, …, 6 = Saturday." }, "auto_create_count": { "type": "integer", "description": "How many upcoming cycles the lifecycle scheduler keeps ahead." }, "estimates_required": { "type": "boolean", "description": "When true, tasks must carry an estimate before they can be added to a cycle (gates velocity metrics)." }, "carry_over_mode": { "type": "string" }, "carry_over_statuses": { "type": "array", "items": { "type": "string" } } }, "required": [ "enabled", "cooldown_weeks", "start_day", "auto_create_count", "estimates_required" ] } }, "required": [ "id", "name", "key", "color", "cycles", "archived", "general", "key_editable" ] } } }, "required": [ "workspaces" ], "type": "object" } ``` --- # workspace_save Create, Update or Archive Workspace ## Beschreibung Admins and employers can manage workspaces in their account. Omit id to create (name and key required); pass a wsp_… ID to update only the supplied fields. The creator becomes a workspace manager. Keys are normalized to uppercase and cannot change once the workspace has tasks. Set archived: true to archive or false to restore an existing workspace. Archiving preserves its contents; General cannot be archived. Use workspace_list(management: true, include_archived: true) to read settings and discover all workspaces you can administer. Workspace-scoped agents can only update already granted workspaces; a workspace tool grant cannot authorize creating a new workspace. ## Zugriff Zugriffsprofil: `gated`. Module: `none`. Die Freigabe im Profil ersetzt keine Account-, Workspace- oder Rollenberechtigung. ## Parameter | Name | Typ | Pflicht | Beschreibung | | --- | --- | --- | --- | | `account_id` | string | Ja | Account prefix ID (acct_…). | | `id` | string | Nein | Workspace prefix ID (wsp_…). Omit to create. | | `archived` | boolean | Nein | Existing workspaces only: true archives, false restores. | | `name` | string | Nein | Required on create; at most 80 characters. | | `key` | string | Nein | Required on create; 2–4 letters/digits. Editable only before any tasks exist. | | `color` | string | Nein | | | `description` | string / null | Nein | Plain text. Null or an empty string clears it. | | `icon_emoji` | string / null | Nein | Unicode emoji. Null or an empty string clears it. | | `tasks_enabled` | boolean | Nein | | | `subtasks_enabled` | boolean | Nein | | | `recurring_tasks_enabled` | boolean | Nein | | | `projects_enabled` | boolean | Nein | Requires tasks_enabled. | | `roadmaps_enabled` | boolean | Nein | Requires projects_enabled. | | `estimates_enabled` | boolean | Nein | | | `estimate_scale` | string | Nein | | | `cycles_enabled` | boolean | Nein | Disabling archives upcoming cycles; active cycles remain. | | `cycle_duration_weeks` | integer / null | Nein | 1–4 weeks; null selects cycle_custom_days. | | `cycle_custom_days` | integer / null | Nein | 1–365 days when cycle_duration_weeks is null. | | `cooldown_duration_weeks` | integer | Nein | | | `cycle_start_day` | integer | Nein | 0 = Sunday through 6 = Saturday. | | `auto_create_count` | integer | Nein | | | `carry_over_mode` | string | Nein | | | `carry_over_statuses` | array | Nein | Task status symbolic keys; only valid with carry_over_mode: by_status. | ## Eingabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "account_id": { "type": "string", "description": "Account prefix ID (acct_…)." }, "id": { "type": "string", "description": "Workspace prefix ID (wsp_…). Omit to create." }, "archived": { "type": "boolean", "description": "Existing workspaces only: true archives, false restores." }, "name": { "type": "string", "description": "Required on create; at most 80 characters." }, "key": { "type": "string", "description": "Required on create; 2–4 letters/digits. Editable only before any tasks exist." }, "color": { "type": "string", "enum": [ "emerald", "violet", "amber", "rose", "sky", "indigo", "slate", "gray" ] }, "description": { "type": [ "string", "null" ], "description": "Plain text. Null or an empty string clears it." }, "icon_emoji": { "type": [ "string", "null" ], "description": "Unicode emoji. Null or an empty string clears it." }, "tasks_enabled": { "type": "boolean" }, "subtasks_enabled": { "type": "boolean" }, "recurring_tasks_enabled": { "type": "boolean" }, "projects_enabled": { "type": "boolean", "description": "Requires tasks_enabled." }, "roadmaps_enabled": { "type": "boolean", "description": "Requires projects_enabled." }, "estimates_enabled": { "type": "boolean" }, "estimate_scale": { "type": "string", "enum": [ "fibonacci", "linear", "powers_of_two" ] }, "cycles_enabled": { "type": "boolean", "description": "Disabling archives upcoming cycles; active cycles remain." }, "cycle_duration_weeks": { "type": [ "integer", "null" ], "description": "1–4 weeks; null selects cycle_custom_days." }, "cycle_custom_days": { "type": [ "integer", "null" ], "description": "1–365 days when cycle_duration_weeks is null." }, "cooldown_duration_weeks": { "type": "integer" }, "cycle_start_day": { "type": "integer", "description": "0 = Sunday through 6 = Saturday." }, "auto_create_count": { "type": "integer" }, "carry_over_mode": { "type": "string", "enum": [ "off", "all", "by_status" ] }, "carry_over_statuses": { "type": "array", "items": { "type": "string" }, "description": "Task status symbolic keys; only valid with carry_over_mode: by_status." } }, "required": [ "account_id" ], "type": "object" } ``` ## Ausgabeschema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "workspace": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "key": { "type": "string" }, "color": { "type": "string" }, "description": { "type": [ "string", "null" ] }, "icon_emoji": { "type": [ "string", "null" ] }, "archived": { "type": "boolean" }, "general": { "type": "boolean" }, "key_editable": { "type": "boolean" }, "tasks_enabled": { "type": "boolean" }, "subtasks_enabled": { "type": "boolean" }, "recurring_tasks_enabled": { "type": "boolean" }, "projects_enabled": { "type": "boolean" }, "roadmaps_enabled": { "type": "boolean" }, "estimates_enabled": { "type": "boolean" }, "estimate_scale": { "type": "string" }, "role": { "type": [ "string", "null" ], "description": "manager / member / null when caller is not on the workspace." }, "cycles": { "type": "object", "description": "Per-workspace cycles config (ENG-1089). Most workspaces keep defaults; only meaningful once `enabled` is true.", "properties": { "enabled": { "type": "boolean" }, "duration_weeks": { "type": [ "integer", "null" ], "description": "1-4 weeks, or null when running on custom_days." }, "custom_days": { "type": [ "integer", "null" ], "description": "Cycle length in days when duration_weeks is null." }, "duration_days": { "type": [ "integer", "null" ], "description": "Collapsed day count — duration_weeks * 7 or custom_days, whichever is set." }, "cooldown_weeks": { "type": "integer", "description": "Gap between consecutive cycles, in weeks." }, "start_day": { "type": "integer", "description": "Date#wday-style: 0 = Sunday, 1 = Monday, …, 6 = Saturday." }, "auto_create_count": { "type": "integer", "description": "How many upcoming cycles the lifecycle scheduler keeps ahead." }, "estimates_required": { "type": "boolean", "description": "When true, tasks must carry an estimate before they can be added to a cycle (gates velocity metrics)." }, "carry_over_mode": { "type": "string" }, "carry_over_statuses": { "type": "array", "items": { "type": "string" } } }, "required": [ "enabled", "cooldown_weeks", "start_day", "auto_create_count", "estimates_required" ] } }, "required": [ "id", "name", "key", "color", "cycles", "archived", "general", "key_editable" ] } }, "required": [ "workspace" ], "type": "object" } ```