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
| 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
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
| Argument | Type | Required | Description |
|---|---|---|---|
artifact_id | integer | yes | The data-driven artifact to refresh. |
data | object | yes | 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 |
|---|---|---|---|
artifact_id | integer | yes | The artifact to republish. |
html | string | yes | The new full self-contained HTML page (same contract as artifacts.create). |
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.
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. |
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 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
| 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.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 |