applyAgentTemplate
ChatGPTUpdate an agent created from a code template to the template's current config. Run readAgentTemplate with the agentUri first and show the user the drift report before applying. The applied configuration comes verbatim from the template registry in code — body, tools, and skills. Behavior by state: - outdated-pristine (untouched since the template last wrote it): applied immediately, in place. The agent keeps its URI and routines. Refused when the URI is a proposal copy, or while this chat has a pending proposal for the agent; approve or reject the proposal first. - edited: the update is created as a proposal replacing the user's changes; the user reviews the diff and approves or rejects it. Warn the user before calling: approving replaces their edits, rejecting keeps the current body. - unmanaged with content exactly matching a template: only writes the stamp; the content is untouched. - unmanaged with only the title matching a template: the update is created as a proposal, as for edited. - up-to-date: no changes. The agent's title and description are not part of the template config. The update never changes them.
approveProposals
ChatGPTApprove pending proposals from a session. Approved proposals are applied: creates become visible, updates are merged, deletes take effect. Omit proposalUris to approve all pending proposals. IMPORTANT: DO NOT call this tool automatically after write operations. After using write tools, you MUST present the proposed changes to the user and wait for their explicit approval before calling this tool. Never auto-approve proposals.
completeImageUpload
ChatGPTComplete an image attachment after its bytes have been uploaded to GCS. Pass uploadId from prepareImageUpload. The result includes embedMarkdown for createItems or updateItems. Repeating completion with the same uploadId is safe within the 24-hour completion window.
contextRetrieval
ChatGPTRetrieve documents with their content and structured fields in a single step. Combines search with content loading — use this when you need document text as context for answering questions or generating content. Values left behind by a type change or field removal are returned separately as leftoverFields. They are read-only but remain valid source information for answering and extraction. Never treat them as writable current fields, restore their origin type, or recreate a removed field without an explicit user request. Example — find and read documents about a topic: { "query": "quarterly planning goals and OKRs" } Returns document titles, content (truncated to maxContentLength), current fields, leftover fields, and relevance scores. Use searchItems or readItems for more control over search vs. read separately.
createAgent
ChatGPTPropose a new Agent document in Tana: its title, a short description, its instructions (the Markdown body) and the skills it can use. Fails if an Agent with the same title already exists. The agent is created as a pending proposal that the user reviews in Tana, unless autoApprove is set. Its skills decide what it can do when it runs in Tana, which can include the user's connected integrations such as Slack or GitHub. Workspace capabilities are selected by name in capabilities (Read, Create, Update); Read is the default, including when workflow skills are supplied. Pass capabilities: [] to omit that default. Custom MCP servers are named in systems, and each binds to the connection of whoever runs the agent. The user can change its skills and tools later in Tana.
createEvent
ChatGPTCreate a new calendar event. Use ownerUri only when the event should be explicitly placed under a specific owner; omit it to use the current chat placement. To "set up a meeting", provide title, schedule, and (optionally) description, participants, and attendeeEmails. participants invites workspace members by user-profile URI: each goes on the calendar invite under their Tana email and gets access to the meeting's notes, as inviting them from the meeting does. attendeeEmails adds people outside the workspace as calendar invitees, without Tana access. Use only email addresses the user explicitly supplied — never guess or autocomplete them. Approval may send real calendar invitations. To change Tana access after creation, use manageAccess. This tool does not accept tagline or summary (post-meeting wrap-up artifacts produced by the wrap-up flow — refine via updateEvent), nor organizer or meeting links (calendar-sourced). startTime is required — an event with no start time never appears on the calendar, so ask the user for one instead of guessing. This tool creates timed events only: an all-day (date-only) schedule cannot be created from here, so do not imitate one with midnight-to-midnight times; explain the limitation and ask for explicit start/end times. Pass startTime/endTime as local ISO 8601 wall times without UTC offsets (for example, 2026-08-21T14:00:00) and copy the exact IANA timezone from the chat's date/time context into timezone. The server resolves daylight-saving offsets; never calculate an offset or Unix timestamp yourself — a Unix timestamp or an offset-bearing value is rejected, and you will have to retry with a wall time. If the tool pauses with a daylight-saving question, wait for the user's answer before retrying. Use a different timezone only when the user explicitly names one. For the optional fields, passing null or omitting leaves the field unset on the new event. endTime cannot be before startTime. Events reach Google/Outlook only when Tana has edit access to the user's calendar connection and one of their calendars is marked "Default for new events"; with either one missing the event stays in Tana. The result names whichever one is missing when that happens, so relay it to the user, including the step it points to. Prefer an explicit endTime: when it is omitted, the external copy defaults to a 30-minute duration.
createItems
ChatGPTCreate doc items with types, field values, and optional task properties. For an independent document copy, use duplicateDocument, then edit the returned id. Never reconstruct the source through Markdown or substitute a live embed. If duplicateDocument is unavailable, explain that an exact independent copy cannot be made here. The source stays intact; pending copies are proposals. The tool preserves current content and fields, not history, comments or source permissions. IMPORTANT: This tool rejects items whose titles match existing items, except when creating a plain task whose only matches are completed plain tasks. For a new occurrence of a completed task (such as a recurring reminder), reuse the original title; do not add a date just to avoid a duplicate title. Open tasks, pending creation proposals, typed records, and other documents still block duplicate titles. Search first with searchItems to find existing items, then use updateItems when modifying the same work. The Types section in the system prompt shows available types and their fields. Use those exact field names. For assignedTo: Use user profile URIs from Team Members. NEVER search for users. IMPORTANT - Tasks: - A plain task is an untyped document with a state; use state="In Progress" unless the user requests another state. - Omit state for untyped documents that are not tasks, such as notes or write-ups. - NEVER create a type named "Task" - this is a built-in concept. Parameters: - "id": Temp ID for referencing this item in other items. - "content": Body text. Use  to embed, [text](#id) to mention other items. - "fields": Field values. Use [Title](#id) to reference other items created in same call. - "state": A plain task is an untyped document with a state; use "In Progress" unless the user requests another state. Omit state for untyped documents that are not tasks. Use UI labels only: "Inbox", "In Progress", "Completed", "Later", or a custom workflow state. Typed items default to Inbox when omitted. - "assignedTo": Only when user explicitly asks to assign someone. - "due": Only when the user states a deadline. A day ({ "at": "2026-10-16" }) or a day and time ({ "at": "2026-10-16T15:00" }), resolved from relative phrases ("friday", "tomorrow 3pm") with the chat's current date and time. An item shows its due date only once it has a state, so a deadline usually comes with one. Temp ID syntax: - Content embeds:  - Content mentions: [text](#id) - Field references: [Title](#id) (plain #id not supported to avoid hashtag ambiguity) Attachment handling: - When an attachment supports a document the user asks you to create, embed the existing attachment URI directly in that document's content in the initial createItems call, unless the user specifies a different treatment. - Do not create a separate wrapper item or a follow-up update merely to attach it. Create a separate attachment document only when explicitly requested. Image syntax: - Existing image:  (use URI from chat attachments or readItems) - From CID:  (use CID from readScreenShareScreenshots, copied exactly — all 64 hex characters; auto-creates image document) Video syntax: - Attached video:  (use URI from chat attachments). Renders as an inline video player. BLOCK-LEVEL: must be on its own line. Audio syntax: - Attached audio:  (use URI from chat attachments). Renders as an inline audio player. BLOCK-LEVEL: must be on its own line. File attachment syntax: - Attached file:  (use URI from chat attachments or readItems). Renders as a clickable card showing the file's title — use this when the user wants to attach a file to a doc. Do NOT call readPdfContent unless the user explicitly asks to read, summarize, or extract content from the PDF — attaching and reading are different intents. BLOCK-LEVEL: must be on its own line. Embed syntax: - Document embed:  — embeds are BLOCK-LEVEL, must be on their own line, never inline within headings or paragraphs. Mermaid diagrams: - Fenced `…
createSkill
ChatGPTCreate a new Skill document (as a proposal). Fails if a Skill with the same title already exists. Read the "Skill authoring" skill (readSkill) first for full guidance on writing good skills. Body format: Do NOT start the body with a title heading (# Title). The title is stored separately — a heading in the body just duplicates it. Start with ## Goal or the first content section.
deleteItems
ChatGPTDelete items by ID. Important: Only use this tool when the user explicitly requests deletion or cancellation of a pending creation. This deletes an entire item or document. To remove a heading, paragraph, list item, or copied source subtree inside a document, use updateItems with a blockOperations delete operation and that block's ID. A request to move or delete one list item does not authorize deleting its containing document. Cancel a pending creation: If the user asks to cancel an item you just proposed creating, pass its proposed item ID to deleteItems. This cancels the pending creation immediately. After the tool confirms cancellation, you can create a replacement proposal if requested. Delete a single document: { "items": [{ "id": "tana:text:abc123" }] } Delete multiple documents: { "items": [{ "id": "tana:text:abc123" }, { "id": "tana:text:def456" }] } Delete supported document types — including skills, agents, canvases, artifacts, chats, media, transcripts, calls, saved searches, and types: { "items": [{ "id": "tana:skill:abc123" }, { "id": "tana:agent:def456" }] } For spaces, use manageSpace with action: "delete" so the user receives the dedicated space-deletion warning. For meetings, delete one occurrence and its Tana content. Synced meetings require your writable organizer calendar and request calendar cancellation; the provider may notify attendees. Tana sends no separate email. Whole-series deletion is unsupported. For a past meeting, clarify an ambiguous "cancel" request as deletion of the saved meeting and its content, including recordings, before proposing. An explicit request to delete needs no extra confirmation. For workflows, use manageTypes with workflow action "remove" so the owning type and its items are updated too. Deleting an existing item is proposed to the user for approval before taking effect. Cancelling a pending creation takes effect immediately.
duplicateDocument
ChatGPTDuplicate a text document as a new independently editable proposal without rebuilding Markdown. Preserves native body structure, rich tables and layout, formatting, links/embeds, type, stored fields, task state/assignees and appearance. The source stays intact. History, comments, source permissions, sharing links and external identities are not copied; normal creation placement and access rules apply. Embedded documents remain references. Use this for document copies, then edit the returned id with updateItems.
generateImageDocuments
ChatGPTGenerate and persist image documents from prompts. Generated images are automatically displayed as message attachments. Each image result includes a documentUri for embedding in other documents.
getCurrentUser
ChatGPTReturn the user this MCP connection acts on behalf of: their user-profile URI and display name. This is who "me", "I", and "my" refer to. Use the URI for assignedTo, participants, and access grants — never search for it.
getItemInfo
ChatGPTRead item metadata/status by URI without loading document body content. Use this before changing access or location, or when the user asks about permissions, owners, timestamps, proposal state, external IDs, or graph-index metadata. Returns proposal-aware access and location: pending ACL or move proposals are treated as the effective state until approved or dismissed. Use readItems when you need document content/editable blocks. Use listEdges when you need relationships/backlinks.
getShareLink
ChatGPTBuild shareable https:// web links for Tana documents from their URIs. Use when the user wants a link that works OUTSIDE this chat — to paste into an external tool (CRM, email, issue tracker, calendar note, a Slack/GitHub message body) or to send to a teammate. For a meeting, pass its tana:event:... URI to link the meeting view. Supported content document URIs (tana:text:..., tana:transcript:..., tana:chat:..., etc.) link directly to that document. Pending create proposals and URI kinds with dedicated navigation surfaces (spaces, types, organizations, and profiles) are not shareable through this tool. Do NOT use this for references within this chat — [Title](tana:...) markdown chips already render as clickable references here. The returned links open the Tana web app and require the viewer to be a logged-in member of this workspace. They are not public links.
getTypes
ChatGPTLook up the full definition for one or more types — what they apply to (documents or meetings), description, fields, workflow states, and AI instructions. Use this when: - You are about to create or update a document and your candidate type appears in the system prompt only by name + short description (under "Other types:"). Fetch its full details before committing — the AI instructions on a type often contain routing rules that change which type is correct (e.g. "if the report isn't actionable, use Feedback instead"). - You see a type name mentioned by the user or in another document and want to confirm its shape before acting. - You are choosing between similar-sounding types (e.g. an actionable-engineering type vs a user-observation type) and need each one's AI instructions to decide. Pass specific names in types to load only those (cheap) — this also attaches each bounded reference field's selectable {name, uri} options (e.g. the existing Product areas or Statuses), which you can pass as values to searchItems fieldFilters or when creating items. Omit types to fetch every type in the workspace (use sparingly; option enrichment is skipped on that path).
listCalendars
ChatGPTList the user's subscribed calendars. Shows which external calendars (Google Calendar, Outlook) are connected and syncing events to Tana. Returns subscription details including provider, calendar ID, access role, and last sync time. When known, connectionAccess reports whether the connection can carry writes back to the provider: "read-only" means events created or edited in Tana stay in Tana until the user enables edits in Tana's calendar settings. isDefaultWriteTarget marks the calendar new Tana events are added to; when no calendar has it, events created in Tana stay in Tana.
listEdges
ChatGPTFind relationships (edges) between documents in the knowledge graph. Primary use case: finding which documents mention or reference a given node (backlinks). Example — find all documents that mention a person: { "nodeIds": ["tana:text:01ABC..."], "direction": "incoming", "edgeTypes": ["LINKS_TO"] } Example — find all documents a doc links to: { "nodeIds": ["tana:text:01ABC..."], "direction": "outgoing", "edgeTypes": ["LINKS_TO"] } Edge types: LINKS_TO (@ mentions), ATTRIBUTE_LINKS_TO (field references), ASSIGNED_TO, INSTANCE_OF, CREATED_IN, BELONGS_TO, CREATED_BY, EDITED_BY. Results include "typeLabel" (human-friendly, e.g. "Created by") — always use typeLabel when presenting results to the user. The "type" field is the raw enum name for use in follow-up edgeTypes queries. Use readItems on returned IDs for full content.
listEvents
ChatGPTList events within a date range. Returns both calendar-synced events (Google Calendar, Outlook) and Tana-native events where the user is a participant. Shows the same events as the calendar page. Each row includes compact time/status, people, location when present, and email domains when the participant list is truncated. Use these fields to distinguish internal planning meetings from customer or external sessions; a title keyword like "onboarding" is not enough by itself. When the user asks about a full week and wants already-happened meetings only, list the full requested week first, then use the status prefix in the time field to exclude upcoming events. Do not silently shorten the range to today. Use eventUri as the canonical event identifier. Call readEvent when you need full event details or transcript follow-up URIs. Use the user's IANA timezone from the chat context by default for accurate local day boundaries; use another zone only when the user explicitly specifies one for the requested range. Never calculate a UTC offset. Example - find today's meetings: { "startDate": "2026-03-25", "endDate": "2026-03-25", "timezone": "America/New_York" } Example - search for a specific meeting: { "startDate": "2026-03-20", "endDate": "2026-03-30", "query": "standup", "timezone": "Europe/Oslo" }
listOrgMembers
ChatGPTList the members of the current organization with their user-profile URIs and display names, sorted by name. Use these URIs to resolve a person's name when assigning tasks, inviting participants, or granting access. Includes the current user.
listProposals
ChatGPTList pending proposals from a session. Returns proposal details including operation type, URIs, and status. Use after write tools to see what changes are pending approval.
manageAccess
ChatGPTChange access control for an existing non-space item by URI. This is the agent equivalent of the document's share menu (the "Access", "People", and "Guest link" sections). Use searchItems first to find the item URI, and getItemInfo to inspect current access when needed. Works for regular items such as text documents, skills, artifacts, canvases, media, chats, events, types, and workflows. Do not use this for spaces; use manageSpace for space access changes. Do not use this to invite someone to a meeting: it shares the meeting's notes but puts nobody on the calendar invite. Invite with updateEvent's addMemberUris (or createEvent's participants), which also grants their access. Types cannot have their own access restriction. Do not set restricted=true on a type; manage its placement with moveItems instead. You can set restricted=false to lift an existing restriction, subject to the organization's access policy. The "Access" mode in the UI maps as follows: "Everyone" → restricted=false (open / inherits from the owner space). "Only me" → restricted=true with just the current user. "Only selected people" → restricted=true with multiple participants. Use the participants array to add or remove explicit user profile or group grants (a group grant reaches all of the group's members). Guest Link sharing (the guestLink field) is a separate, orthogonal axis: when enabled, anyone on the public internet with the document URL can view the doc without signing in. It does not change who has authenticated access. Only text documents and artifacts support Guest Link. This creates an approval proposal unless the current agent is running in direct mode.
manageSpace
ChatGPTCreate, rename, re-describe, delete, or change access to a Tana space. Each change is a pending proposal that the user reviews in Tana, unless autoApprove is set. - create: needs title and ownerUri (the parent space's URI, or "top-level" for a space for the whole organization). A new space is open to everyone who can use its parent unless restricted is true; restricted and participants can be set in the same call. To change a create that is still pending, pass its proposalId as spaceUri. - rename: needs spaceUri and title. - update_description: needs spaceUri and description. - delete: deletes the space. Needs spaceUri. - set_access: needs spaceUri. restricted=true limits the space to its participants, and participants adds or removes people; removing someone, or restricting the space, takes away their access. The user making the change always stays a participant.
manageTypes
ChatGPTCreate or update type definitions in the workspace schema. This tool changes the definition itself; to assign, change, or remove the type on an individual document, use updateItems for documents or updateEvent for meetings. Type names must be unique. Type target (CREATE only): pass "appliesTo": "events" to create a type for meetings. Omit it (or use "docs") for ordinary document types. Existing types cannot be converted between documents and meetings through this tool. Field types: - "text": Free text (default) - "date": Date values - "reference": Link to another type - MUST specify referenceType. Set "cardinality": "multiple" to allow multiple references. - "member": Link to a space member. Set "cardinality": "multiple" to allow multiple members. - "options": A fixed set of short values for classifying or rating something - MUST specify "options" with the values, in the order they should be offered: Priority P0-P3, Severity, Confidence, Sentiment, Customer tier. Use it for values that will rarely change, that nobody needs a page for, and that no other type needs to point at. If the values are things in their own right (a product area, a customer segment, a team, a theme), if several types would share them, or if the list is likely to grow, make them a type and use a "reference" field instead; a reference can be simplified to options later. Options vs workflow: an options field describes what something IS, a workflow tracks where it HAS GOT TO. If the user wants to follow work through stages, give the type a workflow instead - that renders as a real status chip, kanban columns, and an AI-assignable state, which an options field does not. A workflow's states are Inbox, In Progress, Completed and Later, plus any custom statuses the type defines; name those rather than inventing stage names the product does not have. Placement (CREATE only, REQUIRED): every type needs a per-type "ownerUri" — a space URI so everyone in that space can use it, or "top-level" to make it available to the entire organization. Event, chat, and parent-doc owners are not supported for types. Ask the user which they want when they have not said — never guess. Don't create-then-moveItems — pass ownerUri at create time. To move an EXISTING type to a different space (or to top-level), use moveItems — manageTypes "update" REJECTS ownerUri with an error. Create in a specific space: { "operation": "create", "types": [{ "name": "Recipe", "ownerUri": "tana:space:01abc..." }] } Create a meeting type with shared AI instructions: { "operation": "create", "types": [{ "name": "Weekly standup", "appliesTo": "events", "instructions": "Keep updates concise and call out blocked work." }] } Create with reference, date, and member fields: { "operation": "create", "types": [{ "name": "Book", "fields": [ { "name": "Author", "type": "reference", "referenceType": "Person" }, { "name": "Genres", "type": "reference", "referenceType": "Genre", "cardinality": "multiple" }, { "name": "Title", "type": "text" }, { "name": "Published", "type": "date" }, { "name": "Reviewer", "type": "member" } ] }] } Create with an options field: { "operation": "create", "types": [{ "name": "Bug", "fields": [ { "name": "Priority", "type": "options", "options": ["P0", "P1", "P2", "P3"] }, { "name": "Confidence", "type": "options", "options": ["Low", "Medium", "High"] } ] }] } Update (rename type, rename/add/remove fields): { "operation": "update", "types": [{ "name": "Meeting", "newName": "Team Meeting", "renameFields": [{ "name": "Notes", "newName": "Summary" }], "addFields": [{ "name": "Priority", "type": "text" }], "removeFields": ["OldField"] }] } Change which values an options field offers (replaces the whole list, so include the ones you keep): { "operation": "update", "types": [{ "name": "Bug", "setFieldOptions": [{ "name": "Priority", "options": ["P0", "P1", "P2", "P3", "P4"] }] }] } Removing a value from that list does NOT change documents that already carry it: they keep the value, and it stays visible and removable on each document. Say so rather than implying the old value disappears ev…
manipulateTable
ChatGPTManipulate a table's cells, rows, and columns. IMPORTANT - Cell IDs vs Paragraph IDs: - readItems shows PARAGRAPH IDs inside cells (e.g., "ag9rcdtb") - These are NOT the cell IDs - they're nested inside cells - You MUST call readTable first to get actual cell blockIds - Cell IDs from readTable are REQUIRED for this tool WORKFLOW: 1. readItems → get the table's blockId (type: "table") 2. readTable → get all CELL blockIds (different from paragraph IDs!) 3. manipulateTable → use cell blockIds from step 2 If the user asks to read back the table after an edit, call readTable on the proposed document and include the entire returned grid in your final reply. Confirming only the changed cell is not a full table readback. Operations (all use cell blockIds for CRDT safety): - updateCell: Change a cell's text content (single paragraph with inline markdown) - addImageToCell: Add an image to a cell (by tana:image: URI) - removeImageFromCell: Remove an image from a cell (by tana:image: URI from readTable) - insertRowBefore/After: Add a row relative to a cell's row - deleteRow: Remove the row containing a cell - insertColumnBefore/After: Add a column relative to a cell's column - deleteColumn: Remove the column containing a cell - moveRowUp/Down: Swap with adjacent row (1 position per op). To move 3 rows, use 3 separate moveRowUp ops. - moveColumnLeft/Right: Swap with adjacent column (1 position per op). To move 2 columns, use 2 separate ops. updateCell inline markdown support: - bold, italic, code, ~~strikethrough~~, ++underline++ - link text — external links - [Name](tana:user-profile:id) — user mentions - [Title](tana:<type>:id) — Tana references - Does NOT support multiple paragraphs or block-level content Examples: Update a cell and add an image: { "operations": [ { "op": "updateCell", "cellBlockId": "cell1", "content": "Assigned to [Ingrid](tana:user-profile:xyz)" }, { "op": "addImageToCell", "cellBlockId": "cell2", "imageUri": "tana:image:screenshot1" } ]} Insert a row with content (contents is a flat string array): { "operations": [ { "op": "insertRowAfter", "cellBlockId": "cell1", "contents": ["Alice", "Engineer", "New York"] } ]} Insert a column with header + values: { "operations": [ { "op": "insertColumnAfter", "cellBlockId": "cell1", "contents": ["Status", "Active", "Inactive", "Active"] } ]} moveItems
ChatGPTMove existing items so they are owned by a space, or to top-level (no owner) when targetOwnerUri is null. Supported items: text items and tasks, meetings and events, spaces, types, agents, skills, chats, canvases, saved searches, transcripts, artifacts, widget definitions, and files/media (assets, images, audio, and video). Transcripts created for a meeting must stay owned by that event; move the event to relocate them. Standalone transcripts can be moved. Calls cannot be moved by this tool, including standalone calls. For event-linked calls, move their owning event instead; its attached documents stay owned by the event. This has the same access behavior as the standard Move UI: it changes only the item's location. It preserves restricted/private status, participants, roles, and guest-link access. Items with open/inherited access inherit from the new owner, so their audience can change when they move. When the user explicitly asks to change access settings, use manageAccess for non-space items or manageSpace for spaces. Only space owners are accepted as targets. Use searchItems with { "targets": [{ "target": "space" }] } to find a space, or pass null for top-level. Example: { "targetOwnerUri": "tana:space:abc123", "items": [ { "itemId": "tana:event:def456" }, { "itemId": "tana:text:ghi789" } ] } Type-scope rules: - Items typed with a space-scoped type cannot move outside that type's home space. - Type documents can only be moved to top-level or a space owner. - A type document cannot move to a space while any existing instances live outside that target; top-level is always valid. This creates a proposal. The move is applied only after approval.
pinItem
ChatGPTPin or unpin documents on a calendar event (meeting), a space, a day on the user's own calendar, or the user's private sidebar. Pins apply immediately, without a proposal. Event pins show on the meeting page for everyone who can see the event, space pins on the space's home page, date pins on the user's own calendar/Today view, and sidebar pins in the user's private sidebar. Unpinning removes the pin, never the document. Pinning an item the user had hidden on a day unhides it there. A document whose creation is still a pending proposal cannot be pinned until it is approved.
prepareImageUpload
ChatGPTPrepare an image attachment and return a GCS upload URL. PUT the unmodified file bytes to uploadUrl with the returned uploadHeaders, then call completeImageUpload with uploadId. The URL is a bearer credential; do not share it. Complete within 24 hours.
readAgentTemplate
ChatGPTRead the code-defined agent template registry, or check whether an agent created from a template has drifted from it. Use when the user asks whether an agent (e.g. their daily brief) is outdated, drifted, or differs from the predefined/stock configuration — pass agentUri and relay the returned drift report. The state and the tools/skills changes are computed deterministically; relay them as given. When both bodies are returned, summarize the body differences for the user. States: unmanaged (no template stamp; if the content exactly matches a template, the report names it and applyAgentTemplate can stamp it; if only the title matches, applyAgentTemplate offers the template as a proposal), up-to-date (matches the current template), outdated-pristine (untouched since the template last wrote it, but the template moved on — applyAgentTemplate updates it immediately), edited (the user changed the copy — applyAgentTemplate proposes the update for approval). Without agentUri: pass templateId for one template's canonical config, or nothing to list all templates.
readEvent
ChatGPTRead a calendar event by URI (tana:event:...). If a user pastes a canonical browser URL like https://home.tana.inc/o/<org>/e/tana%3Aevent%3A<id>, extract and URL-decode the tana%3Aevent%3A<id> segment first. Also accepts a Tana meeting link or bare short code (meet.tana.inc/xhq-dckf-dxx, /m/<code>, or xhq-dckf-dxx) — pass it through verbatim as eventUri and it resolves server-side. Use this whenever someone hands you a meeting link; generated codes keep resolving after a meeting ends, and a series code opens its most recent occurrence. Returns everything you need to understand a meeting in one call: - Core metadata: title, time (allDay: true marks a date-only event whose startTime/endTime are UTC-midnight day edges, end exclusive — read them as dates; updateEvent cannot reschedule it), location, attendees (who was invited — present on Tana-created meetings too, not only calendar-synced ones; a workspace member ends in {member tana:user-profile:…}, the URI updateEvent's addMemberUris/removeMemberUris take), participants (who joined the call), organizer, tagline, summary (the event's one-sentence wrap-up line, not the Summary panel's content) - summaryUri: the Summary document the meeting's Summary panel shows, present once wrap-up has written one. When asked to change the Summary, read and edit this document with readItems/updateItems, not summary via updateEvent - meetingType: the meeting's assigned type URI and name, when it has one. unavailable: true means the type could not be read, so fields is missing rather than empty — say so instead of reporting the meeting as unfilled - listenKind: the kind of meeting the live engine judged at its first tick (Standup, 1:1, …), absent before that. Not the same as meetingType, which is the Tana type someone assigned - fields: values for the assigned meeting type's fields - leftoverFields: retained values from earlier types or removed fields, with their original names and exact attribute URIs. Read-only; do not restore a type or recreate fields without an explicit user request. - Deterministic companion URIs: agendaUri, callUri, transcriptUri, chatUri and orgChannelUri — returned even when those documents do not exist, so their presence is never evidence that a call, transcript, or agenda happened. chatUri is the chat the meeting shares with everyone in it, guests included; orgChannelUri is the organization's own channel about the meeting, which some organizations use instead and guests are not in - recordings: present only when the meeting was actually video-recorded — its absence means it was not, and a transcript or callUri never implies a recording; once status is "ready", link [Recording](tana:video:…) for playback or embed  - screenshots: wrap-up screenshots selected for the event grid (CID + caption) - pinnedItems: URIs a human explicitly pinned to the grid - relatedDocs: every document attached to the event via BELONGS_TO — artefacts (recap, storyboard, customer-journey, slides, etc.), ad-hoc chats, and auto-generated image documents. Each entry has {uri, type, title} so you can pick what to fetch without a separate discovery call. Derived companions (call/transcript/screen-share/agenda/the two shared chats/suggestion-log) are excluded from this list; the ones with their own fields are surfaced above. For a recurring occurrence, also returns isRecurring: true, the series recurrenceId, and the immediately previousInstance/nextInstance occurrence URIs — use these to hop between meetings in a series without a date-range scan. Neighbour startTime values are UTC instants explicitly labelled with timezone: "UTC"; they do not borrow the current occurrence's timezone. To list the whole series, call listEvents({ recurrenceId }). Follow-ups: readTranscript with { id: callUri, task: "…" } for task-aware transcript extraction (or readFullTranscript with the callUri for the verbatim transcript), readItems for any artefact or doc in relatedDocs, readScreenShareScreenshots for the full per-screenshot list with timing and AI descriptions. No…
readFullTranscript
ChatGPTRead the FULL formatted text of a call transcript. Accepts a call URI (tana:call:...), transcript URI (tana:transcript:...), or event URI (tana:event:...). If given a call or event URI, automatically resolves to and loads the transcript — no extra readEvent call needed. Call, transcript, and event URIs all share the same ULID, so given an event you can pass its URI directly (or derive tana:call:<eventId> / tana:transcript:<eventId> yourself). Returns formatted transcript with "[Ns] speaker: text" lines, where N is the integer number of seconds since call start. Use startSec/endSec to read only a specific time range (segments overlapping the range are included). When citing a moment back to the user, render the citation as [mm:ss](tana:call:...) by converting the [Ns] anchor (e.g. [2646s] → [44:06]). For most cases, prefer `readTranscript` instead. That variant takes a task and uses a cheap LLM to extract just the relevant content (~3 KB vs ~50 KB raw), which saves substantial cost over multi-iteration chats. Use this full variant only when you genuinely need every word — e.g., generating a complete verbatim summary or feeding the whole transcript into another extractor.
readItems
ChatGPTRead documents by URI. Returns title, content, type, fields, and block structure. Task-focused reading — normally pass `task` for substantial documents: Use task both for targeted information-finding and for multi-document synthesis. A fast reader produces a compact, faithful extract from each document before the main agent answers, avoiding large raw bodies in the chat context. Describe the actual end task and required dimensions, for example task: "Synthesize product decisions, owners, dates, metrics, and unresolved risks across these updates" or task: "Each issue's status, assignee, and blocker". This is especially important when reading several documents or any large document. Omit `task` only when complete source text is required: rewriting or editing the source, quoting it verbatim, returning its full contents, or reading before the needed details are known. Use forEditing for edits. Small documents and structured fields (title, fields, taskProperties) always come back in full even when task is set. Leftover fields: Values left behind by a type change, or by a field being removed from the current type, are returned separately as leftoverFields, with their original field/type names when available, value, and exact attributeUri. They are read-only: never try to update them through fields. A request to edit a leftover field is not permission to restore its origin type or recreate a removed field; either action is a separate schema change, so ask the user before doing it. If the current type has a suitable field, update that current field and leave the leftover value unchanged unless the user also asks to clean it up. Leftover values may only be removed with updateItems.removeLeftoverFields. For document cleanup, first move each useful value to a suitable field on the current type, or into document content when no suitable field exists; remove the leftover value only after preserving it or when the user wants it discarded. Linking in chat replies: When you reference a document you just read in your chat reply, write it as [Title](id) using the id field from the result verbatim (it is already the full URI, e.g. tana:text:abc123 — do NOT prepend tana:text: again). The chat client renders this as a clickable chip. Bold or plain text for a known document name is a UX bug. If the user asks to "pull up", "show", or "open" a doc, lead with the link and tell them to click it; there is no inline-open action. forEditing=true (recommended before updateItems): Returns nested editableBlocks: [[id, "text"], [id, "text", [children...]]] Markdown prefixes indicate block type (include in updateItems content to preserve/change): - # ## ### = headings - - = bullet list item - 1. = ordered list item - - [ ] / - [x] = unchecked/checked task - ``lang = code block (`mermaid renders as a diagram; the fence body is the diagram source) **Block IDs:** All IDs are strings. Container blocks (bulletList, orderedList, blockquote) use prefixed IDs like "bulletList/xyz" to mark structural containers. **Block structure:** Content is in nested paragraph blocks within containers. For editing individual items, target listItem or paragraph IDs. Checkable list items use listItem with a checked attribute. For operations on whole containers, pass the full prefixed ID from readItems directly into updateItems block operation fields. **Document comments:** Text documents can return commentThreads. These are anchored discussions, not accepted document text. Match each thread to the document through anchor.quote and its block/offset range. A comment, reply, reaction, or suggested wording does not change the document and must not be reported or copied into an edit as accepted content unless the user explicitly asks to apply it. For edits, editableBlocks` remains the only canonical document body; comment metadata is read-only context. TABLE CONTENT: For documents containing tables: - Tables appear as type "table" with nested paragraph blocks inside cells - The paragraph IDs shown are …
readScreenShareScreenshots
ChatGPTRead screen share screenshots from a call. Accepts a call URI (tana:call:...) or screen-share URI (tana:screen-share:...). The screen-share URI shares the same ULID as the call and the parent event. If given a call URI, automatically follows the link to load the screen share document. Returns a flat list of screenshots sorted by capture time, deduplicated by scene. Each screenshot includes: - cid: content-addressed hash of the image blob - capturedAtSec, visibleUntilSec: timing within the call - title: short label (e.g. "ChatGPT Interface with Arabic Text") - summary: 1–2 sentence overview - details: paragraph-length AI-generated description covering UI layout, visible text, interface elements, and subject matter — usually enough to answer "what was on screen" questions (app, content, UI state, text shown) without needing to see the image itself Use startSec/endSec to read only a specific time range. Returns descriptions, not pixels. When details does not settle the question — exact colours, text too small to have been described, a visual match against a mockup — call readScreenshotImages with this call's URI and the specific cids you want to look at.
readScreenshotImages
ChatGPTFetch the actual images for screen share screenshots, so you can look at them rather than read a description. First call readScreenShareScreenshots to list a call's frames and read their details. That text answers most questions about what was on screen. Call this tool only for the frames where seeing the pixels matters — exact colours, text too small for the description to have captured, a visual match against a mockup. Pass the call or screen-share URI you listed from, plus up to 10 cid values from that listing. A cid that does not belong to that call is rejected.
readSkill
ChatGPTReturn the full instructions of a Tana skill, looked up by title or URI. Read-only: nothing in the workspace changes.
readTable
ChatGPTRead a table's structure to get all cell blockIds for editing. Returns a grid of cells with: - blockId: Unique identifier for each cell (use in manipulateTable) - content: Cell text as inline markdown (preserves bold, italic, [mentions](tana:user-profile:...), links) - isHeader: Whether this is a header cell - rowIndex/colIndex: Position in the grid - images: Array of {tanaUri, blockId} for any images in the cell (omitted if none) Example response: { "rows": [ [{"blockId": "abc", "content": "Owner", "isHeader": true}, {"blockId": "def", "content": "Status"}], [{"blockId": "ghi", "content": "[Ingrid](tana:user-profile:xyz)"}, {"blockId": "jkl", "content": "Done", "images": [{"tanaUri": "tana:image:abc", "blockId": "img1"}]}] ] } Use the cell blockIds with manipulateTable to make edits. rejectProposals
ChatGPTReject specific proposals from a session. Rejected proposals are discarded and their changes will not take effect.
rename
ChatGPTRename entities by setting their titles. Works for text, skill, transcript, asset, image, audio, video, call, canvas, artifact, chat, type, and workflow. To rename an event, use updateEvent. Takes an array — batch every rename into ONE call (10 renames = one call with 10 items, never 10 calls). Produces a focused "title changed" proposal per item. Text/skill documents and artifacts also accept title through updateItems/updateArtifact (for combined rename + content edits in a single call). Entity type definitions also accept newName through manageTypes (for combined rename + schema changes). For spaces: use manageSpace (action: "rename"). Not supported (external sources or system-managed): calendar-subscription, screen-share, agent.
searchItems
ChatGPTSearch for documents using full-text search. Supports multiple queries in one call - always batch your searches instead of calling multiple times. Example - search text documents of a user-defined type: { "queries": ["Alice", "Bob", "Project Alpha"], "targets": [{ "target": "text", "type": "Person" }] } Example - list all user-defined skills: { "queries": [""], "targets": [{ "target": "skill" }] } Example - find a custom agent by name or purpose: { "queries": ["customer research"], "targets": [{ "target": "agent" }] } Example - find open tasks assigned to a user: { "queries": [""], "targets": [{ "target": "text", "state": ["In Progress"], "assignedTo": ["tana:user-profile:XXXX"] }] } Example - find open tasks with no assignee: { "queries": [""], "targets": [{ "target": "text", "state": ["In Progress"], "unassigned": true }] } Example - find what is overdue, soonest deadline first: { "queries": [""], "targets": [{ "target": "text", "due": { "preset": "overdue" }, "dueTimeZone": "Europe/Oslo" }], "sortOptions": [{ "field": "due", "direction": "asc" }] } The due date is built in, like state and assignee: the deadline an item (usually a task) must be done by, either a day (YYYY-MM-DD) or a day and time (YYYY-MM-DDThh:mm). Filter it with the text target's due — a preset (overdue, today, tomorrow, thisWeek (Monday to Sunday), nextWeek, next7Days (next{N}Days for another count), unset for no due date) or inclusive days (onOrAfter/onOrBefore) — never with fieldFilters, which is for a type's own fields. Overdue means the deadline has passed and the item is not done; done items never match it. Set dueTimeZone to the user's zone from the chat context so "today" is their today. Each text result carries due (at, timezone when the time names one instant, and overdue unless the item is done) — answer "when is X due" from that rather than reading the document. Example - filter a typed entity by its field values (reference + date fields): { "queries": ["*"], "targets": [{ "target": "text", "type": "Outcome", "fieldFilters": [ { "field": "Product area", "matchAny": ["<Product area option uri from getTypes>"] }, { "field": "Reported", "after": "2026-01-01" } ] }] } Use fieldFilters to filter instances of a user-defined type by the values in its fields (e.g. "Outcomes in Product area X", "Tasks whose Owner is Alice", "Bugs reported this month", "Deals worth over 10000"). It requires a single type, since field names are resolved against that type's schema. First call getTypes for that type: it returns each field's name and kind, and — for bounded reference fields — the selectable option {name, uri} pairs. Pass the chosen option URIs in matchAny (or user-profile URIs from the team-members list for member fields). If getTypes lists no options for a reference field (its target vocabulary is too large to inline), resolve the specific value before filtering — and use the matched id in matchAny; prefer this targeted lookup over listing every instance, which a large vocabulary will truncate. When you know the value by name, keyword-search the referenced type (searchItems with type set to that type and queries: ["Globex"]). When the value is described conceptually rather than by its exact name (e.g. picking the category that best fits a fuzzy theme), use semanticSearchItems with the same type to find the closest-matching instance. For date fields use after/before — local YYYY-MM-DD for a floating calendar day (matches that day for everyone), or YYYY-MM-DDThh:mm plus timeZone for a wall-clock instant; use the user's IANA zone from the chat context unless they explicitly ask for another timezone. Bounds are inclusive. For free-form fields use equals/startsWith (case-insensitive text) or min/max (inclusive numeric window, for fields holding a number). Across entries the filters AND; within an entry they OR. Tasks are built-in — filter their workflow with state, not fieldFilters. Example - search spaces: { "queries": ["Engineering"], "targets": [{ "target": "space" }…
semanticSearchItems
ChatGPTSearch for documents using semantic (meaning-based) search. Finds conceptually related content even without exact keyword matches. Example - find documents about a concept: { "query": "quarterly planning goals and OKRs" } Example - find conceptually related documents of a user-defined type: { "query": "login problems and failed sign-ins", "type": "Bug" } Use this when looking for conceptually related content. Use searchItems for exact keyword matches or target/state/assignee-based listing/filtering. Returns document IDs for use with readItems and, when available, the immediate structural owner URI in ownerUri. An owner may be a space, event, chat, or another document; only treat it as a space when the URI starts with tana:space:. Never change the URI kind.
updateArtifact
ChatGPTUpdate artifact documents (storyboards, customer journeys, slides) by URI. Use readItems first to see item IDs. - itemUpdates: Update specific items by ID: [{ id: "scene-3", fields: { title: "New Title", description: "..." } }] - addItems: Add new items: [{ fields: { title: "...", description: "..." }, afterItemId: "scene-2" }] - removeItemIds: Permanently delete items by ID: ["scene-5", "scene-6"] - excludeItemIds: Move items to "Probably Not Relevant" section (storyboard only): ["scene-3"] — use when the user wants to set aside scenes, not delete them - reorderItems: Reorder items: ["scene-3", "scene-1", "scene-2"] — pass all IDs in desired order. Preserves all data including images. Use this instead of remove+re-add when moving items. - topLevelFields: Update top-level fields or nested objects like hero: { hero: { ...complete object with ALL fields... } } (shallow merge — include all existing fields to avoid data loss). Also use for replacing arrays like takeaways, actionItems, goldenRules, followUp. - artifactData: Full data replacement (mutually exclusive with above) - regenerateImage: Set true on an itemUpdate to generate or regenerate its image from imagePrompt. Images are NEVER auto-generated for existing items — only new items (addItems) get auto-generated images. To update an image, change the imagePrompt and set regenerateImage: true. Slides artifacts: When users reference slides by number, count through top-level data entries in order — section number fields are internal IDs, not slide positions. Use itemUpdates/removeItemIds for sections (by their number field). Use topLevelFields for hero, takeaways, and other top-level fields (send complete objects/arrays).
updateEvent
ChatGPTUpdate a calendar event. Use readEvent first to get the current event details. Accepts an event URI (tana:event:...). The core event fields mirror createEvent: title, description, startTime, endTime, timezone, location, and mode. To invite or remove a workspace member, use addMemberUris/removeMemberUris: that puts them on (or takes them off) the calendar invite and gives (or takes back) their access to the meeting, as the meeting's own invite list does. Never use manageAccess to invite someone to a meeting — it only shares the notes and sends no invitation. Use addAttendeeEmails/removeAttendeeEmails for people outside the workspace. Use only exact addresses supplied by the user or returned by readEvent — never guess or autocomplete them. These do not grant Tana access. Approval may send real invitations or cancellation notices. The organizer, the current user, and anyone who may currently be live in the call cannot be removed. Per-field semantics: - title: set-only. Omit or pass null to leave unchanged. Blank titles are rejected. - Optional-field nulls mean omission and leave the existing value unchanged, matching strict tool callers that emit filler nulls for fields they did not choose. To clear a value, pass "" for it; null never clears. - description / timezone / location: replace when a non-empty value is provided; "" clears the value. - mode: replace when a non-null value is provided. It cannot be cleared: "video-call" is the default, so set that to reset it. - startTime / endTime: replace when a non-null local ISO 8601 wall time without a UTC offset is provided (for example, 2026-08-21T14:00:00). An all-day (date-only) schedule cannot be written from here: readEvent reports allDay: true on such an event, and a startTime/endTime edit on it is rejected — explain that all-day events are rescheduled in the source calendar. Never imitate an all-day event with midnight-to-midnight times. Use the user's IANA timezone from the chat's date/time context in inputTimezone by default; use another zone only when the user explicitly names one for these times. inputTimezone is used only to resolve the user's wall time and is never persisted. The separate timezone field changes the event's stored timezone and should be set only when the user explicitly requests that change. The server resolves daylight-saving offsets; never calculate an offset or Unix timestamp yourself — a Unix timestamp or an offset-bearing value is rejected, and you will have to retry with a wall time. If the tool pauses with a daylight-saving question, wait for the user's answer before retrying. An endTime cannot exist without a startTime, and endTime cannot be before startTime. Pass "" to remove a time: clearing startTime needs endTime: "" in the same call, and times on an event synced with an external calendar cannot be cleared. - tagline / summary: refinement only. The event MUST already have a tagline / summary set (by the wrap-up flow after a call) — this tool will reject the call if either field is empty when you try to set it. The chat-LLM is not allowed to invent post-meeting narrative from nothing. "" clears an existing tagline / summary. Neither field is the Summary panel's content, which is the document at readEvent's summaryUri, edited with updateItems. When asked for the summary in another language, translate that document, and tell the user that Meeting language in the meeting page's ⋮ menu offers Regenerate after wrap-up. - typeName: set or change an event-only type. Existing field values from the previous type are preserved as leftovers. Use the exact type name returned by getTypes; use manageTypes with appliesTo: "events" first when the user asks to create a new meeting type. - removeType: set true to remove the type while preserving its field values as read-only leftovers. Cannot be combined with typeName or fields. Null and false leave the type unchanged. - fields: replace values on fields belonging to the resulting meeting type. Pass typeName in the same call when assigning or changing the type. Use an empty string or empty array to clear a …
updateItems
ChatGPTUpdate items by URI. ⚠️ id = item URI (tana:text:..., tana:skill:..., tana:agent:..., or tana:action:... for a drafted action's title and body) from searchItems/readItems/readSkill. Block IDs belong only in blockOperations.blockId and position fields. Choose ONE per item: appendContent (append at end), blockOperations (targeted edits), OR content (full replacement). Fields/task properties work with any of them. appendContent (safest for append-only updates): { "id": "tana:text:...", "appendContent": "## Status New notes..." } Use this when adding a section, status update, meeting note, or follow-up to the end of a document. It preserves existing structure and does not require block IDs. Mermaid diagrams: Fenced mermaid code blocks render as diagram previews in documents (Preview/Source toggle) and in chat replies. Supported types: graph/flowchart, stateDiagram, sequenceDiagram, classDiagram, erDiagram, xychart, gantt, pie, mindmap, timeline, gitGraph, quadrantChart. Stick to these. Prefer a document for diagrams the user will want to keep, edit, or share; inline chat is fine for quick one-off visualizations. Block operations (preferred—use readItems forEditing=true first): { "op": "update", "blockId": "id", "content": "New text" } { "op": "delete", "blockId": "id" } { "op": "insert", "content": "Text", "position": { "relativeTo": "last" } } { "op": "insert", "items": ["## Heading", "- Item 1"], "position": { "relativeTo": "id" } } { "op": "move", "blockId": "id", "position": { "relativeTo": "otherId", "placement": "before" } } { "op": "copy", "sourceId": "tana:text:source", "blockId": "sourceListItemId", "position": { "relativeTo": "destinationListItemId", "placement": "after" } } Container IDs from readItems are strings like "bulletList/abc123". Pass the full prefixed ID directly. ⚠️ Siblings vs Children: - position.relativeTo = SIBLING (same level) - position.parent = CHILD (nested under) To nest under a block: { "position": { "parent": "parentId" } } Nested lists: Indented items preserve hierarchy when inserting a new list outside an existing list: ["- Parent", " - Child 1", " - Child 2"]. Under a heading section, insert the whole nested list relative to the heading. When position.relativeTo is an existing list item, every items entry becomes its sibling; indented entries are rejected. Insert the parent item first, then insert children with position.parent set to its returned list item ID. Read back each immediate parent-child relationship before deleting a source subtree. Copy a list subtree between documents: Use copy with the source document URI and enclosing listItem block ID from readItems. It preserves that item's descendants and excludes siblings. Place it beside an existing destination list item with position.relativeTo, or inside one with position.parent only when requested. Read back the proposed destination and check its hierarchy. A copy-only request leaves the source intact. For a move, wait until the destination copy is accepted before proposing deletion of the source listItem in a later turn. Use blockOperations delete for that step; deleteItems would delete the whole source document. If no destination list item can anchor the copy, report that limitation instead of claiming the transfer succeeded. List items: listItem (wrapper) → paragraph (text). Target the PARAGRAPH blockId to edit text. To move or delete an entire list item, especially one with nested children, target its enclosing listItem blockId so its descendants stay attached. A paragraph-only move from an item with nested children is rejected and returns the correct listItem blockId. Block ID chaining: Insert returns createdBlockIds in order for follow-up ops. List inserts return the list container ID before item IDs, so follow-up sibling inserts can anchor after the whole list. To chain WITHIN one call (the createdBlockIds aren't yet available), tag the first insert with tempId and reference it from a later op's position. The tempId resolves to the newest outermost block crea…
uploadImageFile
ChatGPTUpload an image file supplied by the MCP host and attach it to a Tana chat. In ChatGPT, use this for an image attached to the conversation; ChatGPT supplies the file parameter automatically. Returns embedMarkdown for createItems or updateItems.
approveProposals
ClaudecontextRetrieval
ClaudecreateAgent
ClaudecreateArtifact
ClaudecreateEvent
ClaudecreateItems
ClaudecreateSkill
ClaudedeleteItems
ClaudegenerateImageDocuments
ClaudegetItemInfo
ClaudegetShareLink
ClaudegetTypes
ClaudelistCalendars
ClaudelistEdges
ClaudelistEvents
ClaudelistProposals
ClaudemanageAccess
ClaudemanageSpace
ClaudemanageTypes
ClaudemanipulateTable
ClaudemoveDocuments
ClaudepinItem
ClaudereadEvent
ClaudereadFullTranscript
ClaudereadItems
ClaudereadScreenShareScreenshots
ClaudereadSkill
ClaudereadTable
ClauderejectProposals
Clauderename
ClaudesearchItems
ClaudesemanticSearchItems
ClaudeupdateArtifact
ClaudeupdateEvent
ClaudeupdateItems
Claude