Skip to main content

Artifacts

An artifact is a standalone page, app, diagram, document, or source-code view published by an Agent or Assistant. Its content, versions, data, and share settings are stored in AstraBox's database. You can reopen it after the Session ends or its sandbox is destroyed; persistent workspace storage is not required.

Artifacts are private personal resources. The user the creating conversation runs for owns them. Administrators do not gain access to another user's artifacts.

Artifact writes require a transaction-capable store. PostgreSQL (the default) and SQLite support them. MongoDB requires a replica set or sharded cluster; artifact writes on standalone MongoDB fail with ARTIFACT_STORE_UNAVAILABLE.

Create an artifact​

Ask an Agent or Assistant to publish substantial, reusable output as an artifact:

Create an HTML artifact titled “Project checklist”, with a checklist I can use in the browser. Publish it with the artifacts tool.

The built-in artifacts tools are available to Agent and Assistant conversations unless the Agent's Artifacts switch is off or the Session was started by a messaging channel. create_artifact accepts a title, kind, and either content or a workspace file_path that the platform copies. Reading a workspace file during publication does not make subsequent viewing depend on that file or sandbox.

To keep an Agent from publishing artifacts, turn off Artifacts in the Agent's MCP, Skills and Plugins settings, or send "artifacts_enabled": false when creating or updating it. An Agent created without the field has the tools. The next conversation starts without them, including one that takes a prepared sandbox, and calls from the Agent's existing conversations are refused. Artifacts the Agent already published stay viewable and keep their share links.

KindWhat opens
htmlAn HTML page with scripts
reactA React component with a default export; JSX and TypeScript are supported
svgA vector graphic
markdownA document rendered by the console, without page scripts
mermaidA diagram
codeSource code with the supplied language, without execution

React pages can import react, react-dom, lucide-react, recharts, lodash, d3, papaparse, mathjs, three, xlsx, and the supported @/components/ui/* controls: button, card, input, label, textarea, select, checkbox, switch, tabs, badge, alert, separator, progress, slider, and dialog. Tailwind is available. These runtime libraries are served by AstraBox; unknown imports display an error with the available modules.

Open and use the panel​

A published artifact appears as a card in the conversation, outside folded tool work. Its title, kind, and version identify the page. A new artifact opens the Artifacts tab beside the conversation; use Open on a card to return to it. Agent panels list artifacts published by that Session, while Assistant panels list the Assistant's artifacts.

Use Full page for more space, Copy source to copy the viewed version, or Download source to save it. The Artifacts navigation entry opens your gallery at /artifacts; a full page has the address /artifacts/<id>. The full page links to its origin conversation or Assistant and offers deletion. Deleting an artifact removes its versions, data, and share link.

Page errors appear over the viewer. In the conversation panel, Ask the Agent to fix prepares a message containing the artifact id, version, and error. Review and send that message to request a repair.

Versions and later updates​

Every content publication creates a new immutable version. Ask the Agent to rewrite the content or make exact string replacements with update_artifact. An ambiguous or missing replacement fails without publishing; a stale base_version is a conflict. Use Version history when more than one version exists.

Open viewers following the latest version refresh when a new version is published. Viewing a historical version grants no runtime capabilities. Restoring a version through the API creates a new version; it does not alter history. Artifact data is separate from versioned content and survives content updates.

A later conversation of the same user and the same Agent or Assistant can use list_artifacts, get_artifact, and update_artifact to find and refresh the same page. A scheduled Deployment of that Agent can do the same. These tools cannot reach artifacts from another Agent or Assistant. Schedule, webhook and manual runs retain the tools unless the Agent's Artifacts switch is off; messaging-channel Sessions do not.

Sharing​

Open Share artifact and choose the link's access, audience, version, and optional expiry, then Save. Copy the displayed link. Revoke link closes it; revoked, expired, and deleted artifacts cannot be opened through that link.

SettingMeaning
ViewRead content and use capabilities permitted at View level by the current manifest
InteractSigned-in viewers may write data and send room events where the manifest permits it
Anyone with the linkAnonymous visitors are admitted with View access, even when the link says Interact
Signed-in viewers onlyVisitors must sign in before using the link
Follow the latest versionThe shared page follows subsequent publications
Pin versionThe link serves selected page content; capabilities and live data rules follow the current version, and republishing is unavailable

Only the owner can publish versions, change sharing, or delete an artifact. An Interact link does not transfer ownership. Shared pages show Content is user-generated and unverified. Anonymous visitors see no author identity.

The current version's sample or agent declaration requires signed-in viewers, including on a pinned link. Anyone with the link is refused with ARTIFACT_SHARE_AUDIENCE_RESTRICTED. Adding either capability to an existing shared artifact requires anonymous visitors to sign in on subsequent runtime requests (ARTIFACT_SIGN_IN_REQUIRED). The share dialog uses the current policy even while you view history.

Model requests and Agent runs also require authorization to use the origin Agent, including for the artifact owner. For Assistant artifacts, both are restricted to the owner. sample permits signed-in View viewers with that authorization; agent requires Interact or Owner access.

Live page capabilities​

Declare capabilities in create_artifact or update_artifact, for example {"db": {}, "user": {}, "room": {"topics": {"ping": "interact"}}}. Omitting capabilities on an update preserves them; {} clears them. Inside a scripted page, await window.astrabox.use(name) resolves to a namespace or null. Check for null before use. A declaration alone does not grant access: the viewer's level and the current manifest govern each call. Pins keep selected content while capability declarations, data rules and room topics use current policy. Historical views have no runtime capabilities. Reload a pinned page to obtain newly declared capabilities; server operations revalidate current policy while an existing frame stays open.

The examples below belong inside an async page script and assume the named capability is granted. permissions is built in and needs no declaration.

Republish: artifact​

Declare {"artifact": {}}. Only the owner can publish. The viewed version is the base version, so simultaneous edits can return conflict. Pinned share views do not grant this capability, including when the owner opens the link.

const artifact = await window.astrabox.use('artifact');
if (artifact) await artifact.publish('<html><body>Updated page</body></html>');

Store data: db​

Declare {"db": {}}. Documents use even-segment paths such as live/status; collections use odd-segment paths such as notes. The API supports doc, collection, get, set, update, delete, add, where, orderBy, limit, and live onSnapshot subscriptions.

const db = await window.astrabox.use('db');
if (db) {
db.collection('notes').onSnapshot(snapshot => {
document.querySelector('#notes').textContent =
snapshot.docs.map(doc => doc.data().text).join('\n');
});
await db.collection('notes').add({text: 'A shared note'});
}

Default access is View for reads and Interact for writes. A manifest may provide rules with path, read, and write levels. Deeper prefix rules override inherited levels; write must be at least read. The data/users/{self} subtree is private to that viewer by default, including against the owner; {self} expands to their opaque per-artifact id. Store a document at data/users/{self}/profile, for example. Anonymous viewers have no private {self} path and cannot write. Explicit {self} rules also create private subtrees. A rule at a private prefix such as data/users can open it by setting both read and write. There can be at most 64 rules; {self} is allowed only as the final segment of a rule path. A rule with write: 'view' permits signed-in View viewers to write; anonymous viewers cannot write at any rule level.

Ask the model: sample​

Declare {"sample": {}}. The shell asks for consent once per page load. Requests use the origin Agent's or Assistant's configured model. Review the page before allowing requests, which consume model usage. Requests use the configured server model credential. The bundled model gateway receives attribution headers identifying the viewer and artifact.

const model = await window.astrabox.use('sample');
if (model) {
const answer = await model.sample('Suggest one checklist item.', {maxTokens: 100});
document.querySelector('#answer').textContent = answer.text;
}

Options include streamed onText updates, page-provided tools, and caching. sample.json parses a JSON answer. modelTier is accepted but does not choose another model.

Each server request has a 60-second deadline, a 256 KiB JSON limit, and at most 8,192 output tokens (default 4,096). Each viewer can have two concurrent requests and start 30 requests per minute across artifacts and backend replicas. Page-provided tools can use up to eight model rounds; each round counts toward these limits. Optional caching lasts five minutes within the page load.

Identify viewers: user​

Declare {"user": {}}. Ids are opaque and scoped to this artifact; they are not platform account ids. Guests are identified by me().guest; their ids are scoped to the share link and page load.

const user = await window.astrabox.use('user');
if (user) document.querySelector('#role').textContent =
user.isOwner() ? 'Owner' : (user.canEdit() ? 'Interactor' : 'Viewer');

id, me, can, and profiles provide viewer state and permitted profiles. Profiles contain opaque ids and display names; guests receive empty display names for signed-in users. Account ids and email addresses are not exposed.

Presence and events: room​

Declare {"room": {"topics": {"ping": "interact"}}}. Presence is available to all viewers. Sending an event requires Owner unless the topic declares another level. join(name) selects a named room.

const room = await window.astrabox.use('room');
if (room) {
room.onPeers(peers => { document.querySelector('#count').textContent = peers.length; });
room.on('ping', data => { document.querySelector('#message').textContent = data.text; });
await room.presence({viewing: true});
await room.emit('ping', {text: 'Hello'});
}

Room events are visible for ten minutes. Presence expires 45 seconds after the last heartbeat; the page runtime sends heartbeats while present. Use leave() to leave explicitly. Events and presence share a per-viewer write budget of 10/second with a burst of 20 across artifacts and backend replicas.

Save a file: downloads​

Declare {"downloads": true}. The shell confirms every save; page-initiated browser downloads are blocked.

const downloads = await window.astrabox.use('downloads');
if (downloads) await downloads.save({filename: 'notes.txt', data: 'A shared note'});

Refresh through the Agent: agent​

Declare {"agent": {}, "db": {}} to run the origin Agent and observe its data updates. The shell displays the page's exact prompt and asks for consent on every call. A run starts a new conversation owned by the viewer, with the viewer's artifact access and data rules. It uses the Agent's configured MCP servers, credentials, and network policy.

The run's artifacts tools reach only this artifact, even if the viewer owns others, and cannot create another artifact. Only the artifact owner can publish versions. A shared viewer's tool access is revalidated against the link's enabled state, token, expiry, audience, current access and served version; revocation or expiry removes access, and a downgrade reduces the acting level. Owner runs require current ownership and do not depend on a share link.

const agent = await window.astrabox.use('agent');
if (agent) {
const run = await agent.run({prompt:
'Use artifact_data to write the latest project status to live/status on this artifact.'});
agent.watch(run.runId, status => {
document.querySelector('#state').textContent = status.state;
});
}

run returns runId, sessionId, and url; open the conversation when the Agent needs input. When the origin Agent's Artifacts switch is off, run fails with unavailable (ARTIFACT_AGENT_UNAVAILABLE) because the run could not reach the artifact. status and watch report running, waiting_input, completed, or failed. Data written by the run arrives through the page's db subscriptions. There is one active run per viewer per artifact and a limit of 10 runs per viewer per hour across artifacts and backend replicas. Waiting for input counts as active.

Manage grants: permissions​

Grants apply to the current page load. A viewer can remove and restore eligible capabilities, but cannot gain access beyond the manifest or their level.

const permissions = await window.astrabox.use('permissions');
if (permissions) await permissions.manage();

state(name) inspects a grant and request(names) asks for eligible grants.

Security and limits​

Scripted content runs in an opaque-origin sandboxed iframe. It cannot read console cookies, storage, or parent.document. It has no direct network data access; server-backed runtime calls use the shell's message bridge and are checked again by the server. The shell also validates paths and confines requests to this artifact's runtime routes. External images and nested frames are blocked. Inline scripts and styles, bundled runtime libraries, and the supported script/font CDN hosts are allowed. Do not put secrets into page source or shared data.

The runtime supplies per-artifact, per-viewer localStorage, limited to 5 MiB; share-token views also isolate storage by token. sessionStorage lasts for the page load. These stores do not expose the console's storage.

Artifact tool results in conversation history contain the artifact marker and URL; get_artifact adds content, description, manifest and the acting viewer's opaque identity. Data operations return their data result and marker. Tool metadata contains no owner id, origin or share state. Sharing is managed through the owner console and API.

LimitMaximumAPI error
Content per version4 MiB of UTF-8ARTIFACT_CONTENT_TOO_LARGE
Versions per artifact1,000ARTIFACT_VERSION_LIMIT
Title200 charactersARTIFACT_TITLE_LIMIT
Data document256 KiB of JSONARTIFACT_DATA_LIMIT
Documents per artifact10,000ARTIFACT_DATA_COUNT_LIMIT
Room payload16 KiB of JSONARTIFACT_ROOM_LIMIT
Sample request JSON, including raw HTTP bytes256 KiBARTIFACT_SAMPLE_TOO_LARGE
Sample output tokens per request8,192 (default 4,096)ARTIFACT_SAMPLE_TOKEN_LIMIT
Concurrent sample requests per viewer2 across artifacts and replicasARTIFACT_SAMPLE_RATE_LIMITED
Sample starts per viewer30/minute across artifacts and replicasARTIFACT_SAMPLE_RATE_LIMITED
Room/presence writes per viewer10/second, burst 20 across artifacts and replicasARTIFACT_LIVE_RATE_LIMITED
Live streams per viewer per backend replica8 across artifactsARTIFACT_LIVE_RATE_LIMITED
Active Agent runs per viewer per artifact1, including waiting for inputARTIFACT_AGENT_RUN_LIMITED
Agent-run starts per viewer10/hour across artifacts and replicasARTIFACT_AGENT_RUN_LIMITED

Sandbox file access (files) is unavailable because artifacts must remain usable without a sandbox. Direct viewer connectors (mcp) are unavailable; use agent so calls follow the Agent's credentials and network policy. assets and comments resolve to null: blob storage and comment threads are not supported. Templates, remixing, email invitations, and an editor role are not supported. Artifacts are platform-hosted output, not a general application hosting service with arbitrary network access or package installation.

Runtime errors​

Page calls reject with code and message: not_granted, not_writer, conflict, invalid_argument, not_found, rate_limited, unavailable, too_large, or cancelled. Handle failures visibly; model failures may include partial text. Runtime endpoints map artifact API errors to data.runtime_code; live and sample SSE error events use runtime codes.

For example, stale base_version returns ARTIFACT_VERSION_CONFLICT (conflict), denied data reads return ARTIFACT_DATA_DENIED (not_granted), and requests to an undeclared capability return ARTIFACT_CAPABILITY_NOT_DECLARED (not_granted). Missing or foreign owner resources return ARTIFACT_NOT_FOUND; invalid share links return ARTIFACT_SHARE_NOT_FOUND (both not_found).