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
| Argument | Type | Required | Description |
|---|---|---|---|
access_level | string | no | 'private' (default, in-app only) or 'shared' (anyone-with-link). (one of private, shared; default private) |
analytics_card_ids | array | no | Compose 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. |
description | string | no | Optional one-line summary for the gallery card. |
favicon | string | no | Optional emoji used as the browser-tab icon (e.g. '📊'). |
file_id | integer | no | Workspace file whose contents are the HTML page. Mutually exclusive with html. |
html | string | no | Full self-contained HTML page. Mutually exclusive with file_id. |
template | string | no | Optional 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. |
title | string | yes | Short 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
| Argument | Type | Required | Description |
|---|---|---|---|
artifact_id | integer | yes | The 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
| Argument | Type | Required | Description |
|---|---|---|---|
artifact_id | integer | no | The artifact id. Pass this or slug. |
include_html | boolean | no | If true, include the latest version's HTML body. |
slug | string | no | The 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
| Argument | Type | Required | Description |
|---|---|---|---|
artifact_id | integer | yes | The data-driven artifact to refresh. |
data | object | no | Flat map of {{placeholder}} name -> value. Every placeholder in the template must be present. Values are HTML-escaped. |
label | string | no | Optional 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
| Argument | Type | Required | Description |
|---|---|---|---|
access_level | string | no | '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_id | integer | yes | The artifact to change. |
telegram_web_app_account_id | integer | no | Bind 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_id | integer | no | The 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
| Argument | Type | Required | Description |
|---|---|---|---|
analytics_card_ids | array | no | Ids 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_id | integer | yes | The artifact to republish. |
html | string | no | The new full self-contained HTML page (same contract as artifacts.create). Omit when passing analytics_card_ids. |
label | string | no | Optional human name for this version (e.g. 'Q3 final'). |
template | string | no | Optional: 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_markdownsince 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@pagerule). For a web-styled page (dark background,
full-bleed sections) use"none"and declare@page { margin: 0 },
set the background onhtmlas well asbody, 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-labelinside)..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— workspacefile_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
| Argument | Type | Required | Description |
|---|---|---|---|
content_html | string | no | Full HTML body (with optional <style> blocks) for the canonical Chromium pipeline. Mutually exclusive with content_markdown. |
content_markdown | string | no | Markdown body for the invoice/contract pipeline. Mutually exclusive with content_html. |
design_tokens | object | no | Flat 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. |
language | string | no | BCP-47 language tag (e.g. 'en', 'ru', 'zh', 'ja'). Drives <html lang> and (markdown path) font fallback for non-Latin scripts. (default en) |
output_type | string | yes | Renderer target: 'pdf' | 'pptx' | 'docx' | 'html'. PPTX/DOCX require content_markdown. (one of pdf, pptx, docx, html) |
page_preset | string | no | Page 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) |
theme | string | no | Invoice 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) |
title | string | yes | Short 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
| Argument | Type | Required | Description |
|---|---|---|---|
file_id | integer | yes | file_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:
- files_create_upload_url(filename, mime_type, size_bytes, sha256)
- curl -X PUT --data-binary @/path/to/file <upload_url> (send every header from
headersverbatim) - 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
| Argument | Type | Required | Description |
|---|---|---|---|
filename | string | yes | Filename with extension (e.g. 'photo.jpg') |
mime_type | string | no | MIME type (e.g. 'image/jpeg'). Guessed from the filename when omitted. |
sha256 | string | no | Hex sha256 of the file (sha256sum <path>). Optional but recommended: enables dedup and verifies the upload arrived intact. |
size_bytes | integer | yes | EXACT 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. |
title | string | no | Optional 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
| Argument | Type | Required | Description |
|---|---|---|---|
file_ids | array | yes | List 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
| Argument | Type | Required | Description |
|---|---|---|---|
file_ids | array | yes | List of file IDs to fetch as base64 (max 5). Get IDs from files.info or message attachment_file_ids. |
variants | array | no | Images 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
| Argument | Type | Required | Description |
|---|---|---|---|
file_ids | array | yes | List 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
| Argument | Type | Required | Description |
|---|---|---|---|
description | string | no | Optional description of the file contents. |
file_id | integer | yes | ID of the file to ingest (from attachment_file_ids in context). |
tags | array | no | Optional list of tags for categorization (e.g., ['presentation', 'dextrade']). |
thread_id | integer | no | Optional thread ID to associate the file with. If not provided, uses context thread. |
title | string | no | Human-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
| Argument | Type | Required | Description |
|---|---|---|---|
encoding | string | no | Text encoding to use (default: utf-8). (default utf-8) |
file_id | integer | yes | ID of the file to read (from attachment_file_ids in context). |
max_chars | integer | no | Maximum characters to return (default: 10000). Use smaller values for large files. (default 10000; min 100.0; max 50000.0) |
summarize | boolean | no | If 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
| Argument | Type | Required | Description |
|---|---|---|---|
file_id | integer | yes | ID of an audio or video file (from attachment_file_ids or files.search). |
max_chars | integer | no | Maximum transcript characters to return (default 50000). (default 50000; min 100.0; max 200000.0) |
max_frames | integer | no | Key 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
| Argument | Type | Required | Description |
|---|---|---|---|
content | string | no | Base64-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. |
filename | string | no | Filename with extension (e.g. 'photo.png') (default upload) |
mime_type | string | no | MIME type (e.g. 'image/png', 'application/pdf') (default application/octet-stream) |
source_url | string | no | Public URL to fetch file from. Either content OR source_url is required. |
title | string | no | Optional display title |