Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/agent0ai/space-agent/llms.txt

Use this file to discover all available pages before exploring further.

A Space is a persistent, named canvas of widgets that belongs to a single user. Unlike a route or a view, a Space survives page reloads and sessions — it is a real set of files stored under the authenticated user’s home directory. Each Space can contain multiple widgets, each with its own renderer, metadata, and optionally its own data files and shared scripts. The agent works with Spaces and widgets through a staged tool workflow, reading and patching widget source across turns rather than all at once.

Storage Layout

Every Space is stored under the current user’s ~/spaces/<spaceId>/ folder:
~/spaces/<spaceId>/
  space.yaml              ← manifest: title, icon, color, layout, minimized widgets, timestamps
  widgets/
    <widgetId>.yaml       ← widget metadata + renderer source string
  data/                   ← widget-owned structured files
  assets/                 ← widget-owned assets (fetched through /~/...)
  scripts/                ← shared JS modules (loaded via context.import("scripts/..."))
  thumbnail.webp          ← optional dashboard card background (experimental)
Widget source is YAML-first. Legacy widgets/*.js files are treated as migration input only. Widget IDs come from their filenames under widgets/.
The space.yaml manifest owns the space title, icon, color, agent instructions, layout grid state, and the list of minimized widgets. It should never contain invented or untitled widget names.

Runtime Namespaces

The _core/spaces module publishes two helper surfaces on globalThis.space:

space.current

Helpers for the currently open space: list, read, patch, render, reload, reposition, and remove widgets.

space.spaces

Helpers for cross-space CRUD: create, open, duplicate, remove spaces, and lower-level widget storage operations.
Frequently used space.current helpers:
space.current.listWidgets()
space.current.readWidget(widgetIdOrName)
space.current.seeWidget(widgetIdOrName, full?)
space.current.patchWidget(widgetId, { ... })
space.current.renderWidget({ id, name, cols, rows, metadata?, renderer })
space.current.reload(options?)
space.current.reloadWidget(widgetId)
space.current.reposition(options?)
space.current.removeWidget(...)
space.current.removeWidgets(...)
space.current.removeAllWidgets()
space.current.rearrange()
space.current.repairLayout()
space.current.toggleWidgets(...)
Frequently used space.spaces helpers:
space.spaces.listSpaces()
space.spaces.createSpace(...)
space.spaces.openSpace(spaceId, options?)
space.spaces.duplicateSpace(...)
space.spaces.removeSpace(...)
space.spaces.repositionCurrentSpace(options?)
space.spaces.reloadCurrentSpace(options?)
space.spaces.upsertWidget({ ..., metadata? })
space.spaces.upsertWidgets({ widgets, ... })
space.spaces.patchWidget(...)
space.spaces.renderWidget(...)
space.spaces.openShareModal(options?)

Skills for Space Work

The agent loads space-related guidance through two dedicated skills:
// Always auto-loaded: space selection, creating, removing, editing space.yaml
await space.skills.load("spaces");

// Auto-loaded only while space:open is active: widget authoring
await space.skills.load("space-widgets");
The spaces skill is top-level and auto-loaded unconditionally. The space-widgets skill is top-level and auto-loaded only while the page exports the space:open context tag — that is, while a Space is actively open in the route.

Context Tags

While a Space is open, the _core/spaces route exports hidden <x-context> elements that gate skill visibility and prompt context:
TagWhen present
space:openAny time a Space is mounted as the current route
space:id:<id>Identifies the specific open Space by ID
These tags flow into skill discovery at prompt-build time. The space-widgets skill becomes eligible only when space:open is in the current document’s tag union.

Agent Workflow

The spaces runtime is designed for staged turns — the agent reads before it writes, and each mutation happens after seeing the current state.
1

Discover

Call space.current.listWidgets() when the live widget catalog is unknown. The transient section Current Space Widgets also provides a compact id|name|col|row|cols|rows|state|render status table on every prompt turn.
2

Read

Call space.current.readWidget(widgetIdOrName) to load the latest numbered renderer source. Numbered line prefixes are display-only targets for patch operations — they are not stored source text.
3

Mutate

On the next turn, call space.current.patchWidget(...) for bounded edits or space.current.renderWidget(...) for a full renderer rewrite.
4

Verify

Call space.current.reloadWidget(widgetId) or another read on a later turn if needed. After any write, the runtime appends a Current Widget transient envelope with the rendered HTML and numbered source readback.
readWidget(...) and listWidgets() are discovery steps. The next dependent mutation should happen on the next turn, not in the same execution block as the read.

Widget Renderer Contract

The preferred widget renderer shape is a plain async function:
async (parent, currentSpace, context) => {
  // render content directly into `parent`
}
context exposes useful paths and a module loader:
context.paths.root      // space root path
context.paths.data      // data/ subfolder
context.paths.assets    // assets/ subfolder
context.paths.scripts   // scripts/ subfolder
context.paths.widget    // this widget's folder

// Load a shared module without hardcoding space IDs
const utils = await context.import("scripts/utils.js");
For website or browser-like surfaces that the agent needs to inspect or control, use <x-browser> rather than a plain iframe:
<x-browser src="google.com"></x-browser>
This registers the surface with space.browser and enables agent-driven navigation, DOM inspection, and interaction.

First Login: Big Bang Onboarding

On first login, _core/spaces uses the _core/login_hooks/first_login seam to copy or reuse the bundled onboarding space template. This space carries the Big Bang title, icon, color, and onboarding instructions. The router is rewritten to open that space as the initial route instead of the default dashboard.
Subsequent logins land on the dashboard. Users can create new spaces from the dashboard via the New Space button in the topbar, or from the spaces launcher at any time.

Share Modal

The Share button on an open Space opens a modal with local and optionally hosted sharing:
Always available. Exports the current ~/spaces/<spaceId>/ folder through the authenticated backend folder_download endpoint. The browser receives the archive as an attachment.
Always available. Validates through the backend import endpoint. If the current space already has content, the modal asks whether to overwrite it or import the archive as a new imported-N space.
When CLOUD_SHARE_URL resolves to a base URL, the modal shows a hosted-share panel first. It fetches the current Space ZIP, optionally encrypts it in the browser with a password using the share-crypto helper, uploads it to the receiver, and returns a shareable link in an inline copy field.
Local ZIP export and import remain available even when hosted sharing is disabled or the remote receiver rejects uploads.

Build docs developers (and LLMs) love