Skip to main content

files

artifacts.create​

Create Artifact

Effects: write

Host a self-contained HTML page at a stable, default-private, shareable URL — the Artifact experience, in-app.

Pass exactly one of:

  • html — the full page: your <body> plus any <style>/<script>. Unlike documents.create, the page is served live (JavaScript runs), so charts, interactivity, and small tools work.
  • file_id — a workspace file whose contents are already the HTML page.
  • analytics_card_ids — ids of saved analytics dashboard cards; the platform re-runs their queries and composes one designed report page (static charts, snapshot at build time). Best way to give someone a shareable analytics report.

The page runs in a locked-down sandbox: a dedicated origin + a strict CSP. That means it is fully self-contained — it CANNOT call out to the network (fetch/XHR/WebSocket are blocked) or load anything from a CDN. Inline all assets: CSS/JS inline, images/fonts as data: URIs. Draw charts yourself as inline SVG (no external chart library).

access_level defaults to 'private' (viewable only in-app). Set 'shared' to make the unguessable link itself the capability (anyone-with-link). You can flip this later with artifacts.set_access.

Returns {artifact_id, slug, url, app_url, version, access_level}. app_url always opens for workspace members, in the app. url is the public link and is set ONLY for a shared artifact (a private one has no public page: handed out bare, the public link answers "not available"). Republish with artifacts.update — both links stay the same.

Arguments​

ArgumentTypeRequiredDescription
access_levelstringno'private' (default, in-app only) or 'shared' (anyone-with-link). (one of private, shared; default private)
analytics_card_idsarraynoCompose saved analytics dashboard cards into one report page: each card's SQL re-runs through the guarded analytics engine and renders as a static chart. Data is a snapshot at build time. Mutually exclusive with html/file_id.
descriptionstringnoOptional one-line summary for the gallery card.
faviconstringnoOptional emoji used as the browser-tab icon (e.g. '📊').
file_idintegernoWorkspace file whose contents are the HTML page. Mutually exclusive with html.
htmlstringnoFull self-contained HTML page. Mutually exclusive with file_id.
templatestringnoOptional data-driven template: HTML with {{placeholder}} tokens. When set, later artifacts.refresh(data={...}) re-renders the page server-side from tiny data payloads (no HTML round-trip) — ideal for a scheduled agent that refreshes live numbers. The initial html you pass should be this template already rendered with today's values.
titlestringyesShort human-readable title (page <title> + gallery label).

artifacts.export_pdf​

Export Artifact to PDF

Effects: write

Snapshot an artifact's current version to a PDF saved in the workspace. NOTE: the PDF is a STATIC capture rendered with JavaScript disabled — interactive or JS-drawn content (charts on <canvas>, script-generated SVG) will not appear. Author charts as static SVG if they must show in the PDF. Returns the file_id; deliver it with messages.send(attachments=[file_id]).

Arguments​

ArgumentTypeRequiredDescription
artifact_idintegeryesThe artifact to snapshot (its latest version).

artifacts.get​

Get Artifact

Effects: read

Fetch an artifact's metadata by id or slug — title, access level, version, view count, URL. Set include_html=true to also return the latest HTML body (so you can read-then-edit before calling artifacts.update).

Arguments​

ArgumentTypeRequiredDescription
artifact_idintegernoThe artifact id. Pass this or slug.
include_htmlbooleannoIf true, include the latest version's HTML body.
slugstringnoThe artifact slug. Pass this or artifact_id.

artifacts.list​

List Artifacts

Effects: read

List the workspace's artifacts (most-recently-updated first): title, url, access level, version, view count. Soft-deleted artifacts are excluded.

Arguments​

No arguments.

artifacts.refresh​

Refresh Artifact

Effects: write

Publish a new version of an artifact at the SAME URL, without sending HTML. Two kinds of artifact: one built from saved analytics cards (artifacts.create/update with analytics_card_ids) is rebuilt by passing artifact_id alone — its cards' queries re-run and the charts are redrawn; one created/updated with a template (HTML with {{placeholder}} tokens) takes data, a flat map of placeholder -> value (e.g. {"leads": "3 200", "date": "15 июля 2026"}), and every placeholder must have a value. Ideal for a scheduled refresh of live numbers.

Arguments​

ArgumentTypeRequiredDescription
artifact_idintegeryesThe data-driven artifact to refresh.
dataobjectnoFlat map of {{placeholder}} name -> value. Every placeholder in the template must be present. Values are HTML-escaped.
labelstringnoOptional version label (e.g. 'daily refresh').

artifacts.set_access​

Set Artifact Access

Effects: write

Change an artifact's access level. 'shared' makes the unguessable link the capability (anyone-with-link); 'private' revokes that — the link 404s for anyone not signed into the workspace. Existing shared links keep the same URL when re-shared.

Arguments​

ArgumentTypeRequiredDescription
access_levelstringno'shared' (anyone-with-link) or 'private' (in-app only). OMIT to leave the access level unchanged — do that when the call only binds or unbinds a Telegram Mini App. (one of private, shared)
artifact_idintegeryesThe artifact to change.
telegram_web_app_account_idintegernoBind this artifact to a Telegram bot account (channel_account.id) so it can be opened as a Mini App from a web_app button and report verified events back. The artifact must already be shared (or be made shared in this same call). Pass together with telegram_web_app_agent_id. Pass 0 to UNBIND — the page stops being a Mini App and stops accepting events; telegram_web_app_agent_id is not needed to unbind. Setting access_level='private' also unbinds.
telegram_web_app_agent_idintegernoThe agent woken by events from this page. It must own exactly one enabled webhook trigger — that trigger is what the events target. Not needed when unbinding (telegram_web_app_account_id=0).

artifacts.update​

Update Artifact

Effects: write

Republish an existing artifact with new HTML. The slug and URL stay the SAME; a new version is stored (older versions are retained up to a cap). Use this to refresh a shared dashboard — anyone with the link sees the new snapshot.

Arguments​

ArgumentTypeRequiredDescription
analytics_card_idsarraynoIds of saved analytics dashboard cards to make this artifact's source, keeping its link: the cards are attached and the page is rebuilt from them now; afterwards artifacts.refresh(artifact_id) alone rebuilds it again. Mutually exclusive with html.
artifact_idintegeryesThe artifact to republish.
htmlstringnoThe new full self-contained HTML page (same contract as artifacts.create). Omit when passing analytics_card_ids.
labelstringnoOptional human name for this version (e.g. 'Q3 final').
templatestringnoOptional: attach/replace the data-driven template (HTML with {{placeholder}} tokens) on this existing artifact, so later artifacts.refresh(data={...}) can re-render it server-side. Pass the html rendered from this template. Omit to leave the template unchanged.

documents.create​

Create Document

Effects: write

Render a document (PDF / HTML / PPTX / DOCX) and save it to the workspace.

This tool has two input pipelines — pass exactly one of content_html or content_markdown.

Pipeline A — content_html (canonical for decks, proposals, designed pages)

You author full HTML+CSS. A baked-in design-system preamble ships first
(<style> with Inter/Manrope as data-URI fonts, CSS-variable palette tokens,
8px spacing scale, and pre-styled layout helpers); your markup and any of
your own <style> blocks land after the preamble so you can override
anything. Chromium renders the assembled document into a static PDF —
JavaScript is disabled and DNS is blackholed, so external font / image /
script fetches will fail by configuration.

Required when this pipeline is used:

  • title — human-readable, used for PDF metadata and the saved filename.
  • content_html — the <body> and any custom <style> blocks. The
    renderer wraps this in <html>…</html> and injects the preamble + a
    canonical <meta charset> + <title>. Do NOT emit <script>,
    <iframe>, <object>, <embed>, <meta>, <link>, <base>,
    <form>, or event handlers — the sanitizer strips them.
  • output_type — "pdf" or "html". ("pptx" and "docx" require
    content_markdown since they need structured markdown intermediates.)

Optional:

  • page_preset — "slide_16_9" (default for any deck), "a4" (default
    for flowing documents — used if omitted), "letter", or "none" (you
    declare your own @page rule). For a web-styled page (dark background,
    full-bleed sections) use "none" and declare @page { margin: 0 },
    set the background on html as well as body, and add
    print-color-adjust: exact — the a4/letter presets keep 24mm paper
    margins, which paint as a white frame around dark designs.
  • design_tokens — flat dict overriding the preamble's CSS variables.
    Whitelisted keys: brand_primary, accent, surface_dark (hex color),
    font_display, font_body (font name from ['Inter', 'Manrope', 'monospace', 'sans-serif', 'serif', 'system-ui', 'ui-monospace', 'ui-sans-serif', 'ui-serif']).
  • language — BCP-47 tag (default "en"). Drives <html lang>.

Slide structure (page_preset="slide_16_9")​

Each slide is <section class="slide …">…</section>. The base .slide
class is what sizes it to the viewport and forces the page break — do
not drop it. Composable variants (apply alongside .slide):

  • .slide-cover — gradient hero, big display title.
  • .slide-split — two equal columns, image + narrative.
  • .slide-stats — three-up KPI cards (use <div class="stat"> with
    .stat-value + .stat-label inside).
  • .slide-quote — centered pull quote + <cite> attribution.

Layout helpers (work in any preset): .grid-2, .grid-3, .split,
.stack, .cluster, .callout, .muted, .kbd.

Speaker notes​

<aside class="notes">…text…</aside> inside a <section class="slide">.
The sanitizer strips them from the rendered PDF and returns them as
slide_notes[] (parallel to slide order). Orphan notes outside any slide
are dropped with a warning.

Images​

Only these src schemes resolve:

  • file:NNN — workspace file_id.
  • data:image/...;base64,... — inline.
  • https://<host> where <host> ∈ DOCUMENTS_MEDIA_URL_ALLOWLIST.
    Other URLs are dropped and replaced with an HTML comment placeholder.

Pipeline B — content_markdown (invoice / contract only)

Required:

  • title, content_markdown, output_type.

Optional:

  • theme — "invoice" or "contract". Triggers the corresponding
    exemplar styling and (for invoices) the arithmetic validator that
    fail-closes on missing or mismatched totals.
  • language — BCP-47 (default "en").

Delivery contract (CRITICAL)

After this tool returns file_id, deliver the file with
messages.send(attachments=[file_id], text="<short caption>"). Embedding
the file_id in a markdown link, sandbox: URL, or /api/files/<id>/download
text will render as plain text on the recipient's channel — the
attachments parameter is the only way the file actually attaches.

Exemplars

INVOICE (English):

Invoice INV-{YYYYMMDD-HHMMSS}

From: {Issuer Legal Name}, {Address}, {Tax ID}
To: {Customer Name}, {Customer Address}, {Customer Tax ID}
Issue date: {YYYY-MM-DD} Due date: {YYYY-MM-DD}

| Description | Qty | Unit price | Total |
|---|---:|---:|---:|
| {Service 1} | 1 | 1500.00 | 1500.00 |
| {Service 2} | 2 | 500.00 | 1000.00 |

Subtotal: USD 2500.00
Tax (20%): USD 500.00
Total: USD 3000.00

Payment: {bank details OR crypto wallet — never both}

INVOICE (Russian):

Счёт-фактура № INV-{YYYYMMDD-HHMMSS}

От: {Юридическое название организации}, {Адрес}, ИНН {Tax ID}
Кому: {Название клиента}, {Адрес клиента}, ИНН {Tax ID}
Дата: {YYYY-MM-DD} Срок оплаты: {YYYY-MM-DD}

| Описание | Кол-во | Цена | Сумма |
|---|---:|---:|---:|
| {Услуга 1} | 1 | 1500.00 | 1500.00 |
| {Услуга 2} | 2 | 500.00 | 1000.00 |

Подытог: USD 2500.00
НДС (20%): USD 500.00
Итого: USD 3000.00

Реквизиты: {банковские реквизиты ИЛИ криптокошелёк — не оба сразу}

CONTRACT (English):

Service Agreement

Between: {Provider Legal Name}, {Address} ("Provider")
And: {Client Legal Name}, {Address} ("Client")
Effective date: {YYYY-MM-DD}

1. Scope of services​

{Concise description of what Provider agrees to deliver.}

2. Term​

This Agreement begins on the Effective date and continues until {termination
condition or end date}.

3. Compensation​

Client pays Provider {amount and currency} according to {payment schedule}.

4. Confidentiality​

Both parties agree to keep proprietary information of the other party
confidential during and after the term of this Agreement.

5. Termination​

Either party may terminate with {N} days' written notice.

6. Governing law​

{Jurisdiction}.


Provider: ____________________ Client: ____________________
{Provider signatory name} {Client signatory name}

CONTRACT (Russian):

Договор оказания услуг

Между: {Юридическое название Исполнителя}, {Адрес} ("Исполнитель")
И: {Юридическое название Заказчика}, {Адрес} ("Заказчик")
Дата вступления в силу: {YYYY-MM-DD}

1. Предмет договора​

{Краткое описание услуг, которые Исполнитель обязуется оказать.}

2. Срок действия​

Договор вступает в силу с указанной даты и действует до {условие прекращения
или дата окончания}.

3. Стоимость и порядок оплаты​

Заказчик оплачивает услуги Исполнителя в размере {сумма и валюта} в порядке
{график платежей}.

4. Конфиденциальность​

Стороны обязуются сохранять конфиденциальность сведений, полученных в ходе
исполнения настоящего Договора, в течение срока его действия и после его
прекращения.

5. Расторжение​

Любая из сторон вправе расторгнуть Договор, направив письменное уведомление
не менее чем за {N} дней.

6. Применимое право​

{Юрисдикция}.


Исполнитель: ____________________ Заказчик: ____________________
{ФИО подписанта Исполнителя} {ФИО подписанта Заказчика}

Arguments​

ArgumentTypeRequiredDescription
content_htmlstringnoFull HTML body (with optional <style> blocks) for the canonical Chromium pipeline. Mutually exclusive with content_markdown.
content_markdownstringnoMarkdown body for the invoice/contract pipeline. Mutually exclusive with content_html.
design_tokensobjectnoFlat dict of CSS-variable overrides for content_html. Whitelisted keys: brand_primary, accent, surface_dark (hex color), font_display, font_body (Inter|Manrope|system-ui|ui-sans-serif|ui-serif|ui-monospace|sans-serif|serif|monospace). Unknown keys / invalid values are dropped with a warning. Rejected with content_markdown.
languagestringnoBCP-47 language tag (e.g. 'en', 'ru', 'zh', 'ja'). Drives <html lang> and (markdown path) font fallback for non-Latin scripts. (default en)
output_typestringyesRenderer target: 'pdf' | 'pptx' | 'docx' | 'html'. PPTX/DOCX require content_markdown. (one of pdf, pptx, docx, html)
page_presetstringnoPage geometry for content_html. 'slide_16_9' = 1280x720 deck, 'a4'/'letter' = flowing document, 'none' = LLM declares its own @page. Defaults to 'a4' inside the html branch when omitted. Rejected with content_markdown. (one of slide_16_9, a4, letter, none)
themestringnoInvoice or contract styling for content_markdown. Rejected with content_html (use design_tokens + your own CSS instead). OMIT for default (unthemed) styling. (one of invoice, contract)
titlestringyesShort human-readable title for the document.

files.complete_upload​

Complete Upload

Effects: write

Finish an upload started with files_create_upload_url, after the bytes have been PUT to the upload_url.

Verifies the object actually landed and matches the size (and sha256, when one was declared), then makes the file usable: from here file_id works in messages_send, messages_send_email attachments, documents.create, and the rest.

Returns: file_id, status, byte_size, mime_type.

Arguments​

ArgumentTypeRequiredDescription
file_idintegeryesfile_id returned by files_create_upload_url

files.create_upload_url​

Create Upload URL

Effects: write

Get a URL to upload a local file DIRECTLY to storage, without passing its bytes through this conversation.

Use this for any file you already have on disk — it is the only way to send one without spending tokens on its contents, and the only way to send anything above ~50 KB at all.

Three steps:

  1. files_create_upload_url(filename, mime_type, size_bytes, sha256)
  2. curl -X PUT --data-binary @/path/to/file <upload_url> (send every header from headers verbatim)
  3. files_complete_upload(file_id) -> the file is ready

Pass sha256 when you can: if the workspace already holds that exact file you get its file_id back immediately with deduplicated=true and no upload at all.

Returns: file_id, upload_url, method, headers, expires_at.

Arguments​

ArgumentTypeRequiredDescription
filenamestringyesFilename with extension (e.g. 'photo.jpg')
mime_typestringnoMIME type (e.g. 'image/jpeg'). Guessed from the filename when omitted.
sha256stringnoHex sha256 of the file (sha256sum <path>). Optional but recommended: enables dedup and verifies the upload arrived intact.
size_bytesintegeryesEXACT byte length of the file (stat -c %s <path>). Checked before anything is transferred, so an oversize file is refused here rather than after the upload. Limit: 100 MB.
titlestringnoOptional display title

files.delete​

Files Delete

Effects: delete

Permanently delete files from this workspace by their IDs (generated documents, uploads, screenshots, etc.).

IRREVERSIBLE: removes the DB record, detaches every reference (knowledge collections, thread pins, message attachments), and deletes the stored blob. There is no undo.

Use to clean up leftover / superseded generated files. Only files that belong to this workspace are touched; unknown or other-workspace ids are returned under not_found. Max 20 per call.

Arguments​

ArgumentTypeRequiredDescription
file_idsarrayyesList of file IDs to permanently delete (max 20).

files.get_base64​

Get File as Base64

Effects: read

Download one or more files server-side and return their content as base64-encoded strings. Use this to inspect images, PDFs, or any binary file attached to messages when you cannot access presigned S3 URLs directly. Supports up to 5 files per call, max 15 MB each. For large files batch in groups of 1-2 to avoid oversized responses. For images, pass variants to get processed copies instead of the original: rotate (clockwise) a photo taken sideways or upside down, enhance a faded print, or crop and enlarge a region with small text. Ask for both rotate 90 and 270 in one call when the text runs vertically and you cannot tell which way is up. An MCP client shows at most 5 images per response; the rest are listed, not shown.

Arguments​

ArgumentTypeRequiredDescription
file_idsarrayyesList of file IDs to fetch as base64 (max 5). Get IDs from files.info or message attachment_file_ids.
variantsarraynoImages only, optional. Each variant is applied to every requested image and returned as its own entry (max 4 variants). Keys: rotate (0, 90, 180, 270; clockwise), enhance (true = grayscale + auto-contrast), crop ([x0, y0, x1, y1], fractions 0..1 of the image after rotation; the region is enlarged). Example: [{"rotate": 90, "enhance": true}, {"rotate": 270, "enhance": true}].

files.info​

Files Info

Effects: read

Get metadata and download URLs for files by their IDs.

When to use:

  • After messages_read_history returns attachment_file_ids
  • To get a presigned download URL to read a received file

Returns: filename, mime_type, byte_size, download_url (1-hour presigned URL).

Arguments​

ArgumentTypeRequiredDescription
file_idsarrayyesList of file IDs (max 20)

files.ingest​

Ingest File

Effects: write

Save and index a file into the knowledge base. Use this when the user asks to save, store, or remember a document. The file will be processed (OCR if needed) and indexed for future search.

Arguments​

ArgumentTypeRequiredDescription
descriptionstringnoOptional description of the file contents.
file_idintegeryesID of the file to ingest (from attachment_file_ids in context).
tagsarraynoOptional list of tags for categorization (e.g., ['presentation', 'dextrade']).
thread_idintegernoOptional thread ID to associate the file with. If not provided, uses context thread.
titlestringnoHuman-readable title for the file (e.g., 'Project Presentation', 'Q1 Report'). If not provided, uses original filename.

files.read​

Read File Contents

Effects: read

Read text content of an attached file. Works for: .txt, .md, .json, code files, and documents (PDF, .docx, .xlsx, .pptx, .odt, .rtf); a document still being indexed is awaited briefly. DO NOT call on binary files — for IMAGES use files.get_base64, for AUDIO/VIDEO use files.transcribe (transcript + key frames). Calling on a binary mime-type returns an error — saves you a turn to read the routing hint before deciding.

Arguments​

ArgumentTypeRequiredDescription
encodingstringnoText encoding to use (default: utf-8). (default utf-8)
file_idintegeryesID of the file to read (from attachment_file_ids in context).
max_charsintegernoMaximum characters to return (default: 10000). Use smaller values for large files. (default 10000; min 100.0; max 50000.0)
summarizebooleannoIf true, generate AI summary instead of returning raw content. Use for 'summary', 'summarize', 'краткое содержание' requests. OMIT to return raw content (the default).

files.transcribe​

Transcribe Audio/Video File

Effects: read

Understand an AUDIO or VIDEO file (voice note, recording, clip): returns the spoken text as a transcript and, for video, a few evenly spaced key frames as images, so you can describe what the video shows and says. Max duration 30 minutes (longer files are refused). The transcript is cached, a second call is free. If partial is true the transcript covers only the beginning of the file. For images use files.get_base64, for text and documents files.read.

Arguments​

ArgumentTypeRequiredDescription
file_idintegeryesID of an audio or video file (from attachment_file_ids or files.search).
max_charsintegernoMaximum transcript characters to return (default 50000). (default 50000; min 100.0; max 200000.0)
max_framesintegernoKey frames to return for a video (0-4, default 4). 0 = transcript only. (default 4; min 0.0; max 4.0)

files.upload​

Upload File

Effects: write

Upload a file to DialogBrain and get a file_id for use in messages_send.

When to use:

  • User wants to send a file/image to a contact
  • Before calling messages_send with an attachment

For a file that already exists on disk, use files_create_upload_url instead: content here travels through the conversation twice (once read, once written back), so it is only sensible up to about 50 KB. source_url is fine at any size — the fetch happens server-side.

Returns: file_id (integer) to pass to messages_send attachments parameter.

Arguments​

ArgumentTypeRequiredDescription
contentstringnoBase64-encoded file bytes. Suitable up to ~50 KB — above that the encoded bytes cost more context than the task; use files_create_upload_url for a local file, or source_url for a remote one. Either content OR source_url is required.
filenamestringnoFilename with extension (e.g. 'photo.png') (default upload)
mime_typestringnoMIME type (e.g. 'image/png', 'application/pdf') (default application/octet-stream)
source_urlstringnoPublic URL to fetch file from. Either content OR source_url is required.
titlestringnoOptional display title