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, version}. url is the live link when the public origin is configured; until then the artifact is hosted and versioned but url is null. Republish with artifacts.update — the URL stays 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

Re-render a data-driven artifact from a small data payload and publish a new version at the SAME URL. The artifact must have been created/updated with a template (HTML containing {{placeholder}} tokens). Pass data as a flat map of placeholder -> value (e.g. {"leads": "3 200", "date": "15 июля 2026"}); the server substitutes them into the stored template — you do NOT send any HTML. Ideal for scheduled refreshes of live numbers. Every template placeholder must have a value in data, or the call fails.

Arguments

ArgumentTypeRequiredDescription
artifact_idintegeryesThe data-driven artifact to refresh.
dataobjectyesFlat 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
artifact_idintegeryesThe artifact to republish.
htmlstringyesThe new full self-contained HTML page (same contract as artifacts.create).
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.

Arguments

ArgumentTypeRequiredDescription
file_idsarrayyesList of file IDs to fetch as base64 (max 5). Get IDs from files.info or message attachment_file_ids.

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 PDFs (after files.ingest extracts text). DO NOT call on binary files — for IMAGES use files.get_base64, for AUDIO/VIDEO it cannot be transcribed via this tool, and for non-PDF DOCUMENTS run files.ingest first, THEN files.read. 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.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