> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asteragents.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Apps Tool

> Give your agents the ability to create persistent dashboards, reports, and interactive views

## What it does

The Manage Apps tool lets agents create and manage persistent interactive pages inside Aster. When a user asks for a dashboard, report, or data visualization, the agent can build one that lives at a permanent URL — not just a one-time chat response.

See [Apps](/features/apps) for the full user-facing feature overview.

## When to use it

Add this tool to agents that:

* Analyze data from integrations (GA4, Salesforce, Snowflake, etc.) and need a way to present results beyond chat
* Build recurring reports that users want to bookmark and revisit
* Create multi-section views with charts, tables, KPIs, and tabs
* Need to update an existing view with fresh data

## Parameters

| Parameter       | Type    | Required              | Description                                                                                                                                                                                                                             |
| --------------- | ------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action`        | string  | Yes                   | The operation to perform (see Actions below)                                                                                                                                                                                            |
| `app_id`        | integer | Varies                | The app to read, update, delete, lock, or load                                                                                                                                                                                          |
| `version_id`    | integer | For `get_version`     | The historical version to fetch or load — ids come from `list_versions`. Also accepted by `load_to_sandbox` to load a historical version                                                                                                |
| `app_dir`       | string  | Varies                | Sandbox directory path for project-based workflows                                                                                                                                                                                      |
| `name`          | string  | For `create`          | Display name shown in the app listing and header                                                                                                                                                                                        |
| `description`   | string  | No                    | What the app shows — displayed in the listing                                                                                                                                                                                           |
| `source_tsx`    | string  | For `create`/`update` | The component source code. Must export a default component                                                                                                                                                                              |
| `snapshot_data` | object  | No                    | JSON data the app renders, accessed via `useAppData()`                                                                                                                                                                                  |
| `locked`        | boolean | For `set_lock`        | `true` to lock the app, `false` to unlock it                                                                                                                                                                                            |
| `app_params`    | string  | No                    | For `export_pdf`/`export_png`: URL params to render the app with (e.g. `region=West&tab=2`), so the export captures a filtered view rather than the default. Requires the app to read [`useAppParams()`](/features/apps#url-parameters) |
| `orientation`   | string  | No                    | For `export_pdf`: `landscape` (default) or `portrait`                                                                                                                                                                                   |
| `title`         | string  | No                    | For `export_pdf`/`export_png`: filename for the generated file — a timestamp and extension are appended. Defaults to the app's name                                                                                                     |
| `all_tabs`      | boolean | No                    | For `export_pdf`: `true` exports every tab of a multi-tab app into one combined PDF. Defaults to `false` (default view only). Only standard tab components are walked                                                                   |

## Actions

### create

Build and publish a new app in a single call.

**Required**: `name`, `source_tsx`. **Optional**: `description`, `snapshot_data`.

### update

Update an existing app's content, data, or metadata. A new version is created internally — the URL stays the same.

**Required**: `app_id`. **Optional**: `name`, `description`, `source_tsx`, `snapshot_data`.

### list

Returns all apps in the organization.

### get

Returns an app's metadata and current source code — but **not** its snapshot data. To read or edit an app's data (or faithfully rebuild it), use `load_to_sandbox`, which loads the full project (including `data/snapshot.json`) into the sandbox where `execute_python` can read it.

**Required**: `app_id`.

### delete

Removes an app.

**Required**: `app_id`.

### set\_lock

Locks or unlocks an app. While an app is locked, only its author or an org admin can update, delete, or unlock it — any other agent that attempts `update`, `delete`, or `set_lock` gets an error and should tell the user the app is locked rather than retry. Apps are unlocked by default. Only the app's author or an org admin can call `set_lock`.

**Required**: `app_id`, `locked` (`true` to lock, `false` to unlock).

### load\_to\_sandbox

Loads an existing app's source, data, and assets into the code execution sandbox for editing. After loading, the agent can use `execute_python` to modify files, then call `publish_from_sandbox` to publish the changes.

Pass a `version_id` to load a **historical version** instead of the current one — this hydrates that version's source *and* its snapshot data and assets, which is the full-fidelity restore path: load the old version, then `publish_from_sandbox` to republish it as a new version.

**Required**: `app_id`. **Optional**: `app_dir` (defaults to `/home/user/aster-apps/app-{app_id}`), `version_id` (defaults to the current version).

### publish\_from\_sandbox

Reads an app project from the sandbox, validates it, compiles it, and publishes it. An `aster-app.json` manifest is optional — omit it and the entry is inferred (preferring `src/App.tsx`) with an empty snapshot.

**Required**: `app_dir`. **Optional**: `app_id` (omit to create a new app, provide to update an existing one).

The response classifies the publish from facts the server already holds, so the agent doesn't
have to judge its own change:

* `changed_code` — whether the compiled bundle differs from the current version. `false` means a data-only publish, so the rendered layout cannot have changed and no render check is needed.
* `snapshot_diff` — an advisory shape diff against the previous snapshot, flagging dropped, renamed, reshaped, or emptied keys. This is the most common cause of a tab going silently blank after a refresh.

<Note>
  Before creating an app or changing its code or layout, the agent loads the
  `building-aster-apps` skill — it covers project structure, the snapshot data contract, and a
  render check that catches blank or crashed tabs before publishing. A data-only refresh
  (rebuilding `data/snapshot.json` with the source untouched) skips the skill.
</Note>

### list\_versions

Returns an app's version history — every publish creates a version, and all of them are preserved. Each entry includes the version id, when it was published, whether it's the current version, the bundle hash, source file list, and asset count. Returns the 50 most recent versions; older versions remain fetchable by id via `get_version`.

**Required**: `app_id`.

### get\_version

Returns a specific historical version's complete source code — the entry component plus the full source tree, but **not** its snapshot data. Use it to see how an app's code changed between versions. To **restore** a historical version, use `load_to_sandbox` with the `version_id` instead — for data-driven apps, versions often differ only in snapshot data, so a faithful restore needs the data, not just the source.

**Required**: `app_id`, `version_id`.

## Available libraries

Apps can use these libraries in their source code:

| Library                      | What it provides                                                                                                                    |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `@aster/sdk`                 | `useAppData()` — access the snapshot data; `useAppParams()` — read/write URL params; `useCitation()` — open a knowledge base source |
| `@aster/ui`                  | UI components (Card, Badge, Button, Table, Tabs, Progress, Separator, ScrollArea, Tooltip) and `cn()` utility                       |
| `recharts`                   | Charts — LineChart, BarChart, PieChart, AreaChart, ComposedChart, etc.                                                              |
| `lucide-react`               | Icons                                                                                                                               |
| `date-fns`                   | Date formatting and manipulation                                                                                                    |
| `d3-geo` + `topojson-client` | SVG geographic maps — choropleths, bubble/dot maps (no tile basemaps)                                                               |

All Tailwind CSS classes are supported, including arbitrary values.

<Note>
  `useAppData().data` is always present — no loading/null guard needed. Still guard arrays before `.map`/`.reduce` (e.g. `(data.rows || []).map(...)`) for empty refreshes.
</Note>

<Note>
  **Every published app has a native Export button** (top of the app) that produces a PDF or PNG — the current view, or, for tabbed apps, all tabs combined into one PDF. **Don't build your own PDF / print / download-image logic into an app** — the platform handles it.

  For tabbed apps, build the tabs with the `@aster/ui` `Tabs` component (not hand-rolled `useState` switching) so the all-tabs export can capture each tab; custom tab bars only export the view that's currently visible.
</Note>

## URL parameters and deep links

An app's query string belongs entirely to the app, so an agent can link a user straight to a
particular view — `https://www.asteragents.com/apps/216?region=West&tab=2`. Read it with
`useAppParams()`:

```tsx theme={null}
import { useAppParams } from '@aster/sdk';

const [params, setParams] = useAppParams();
const region = params.region ?? 'All';          // values are strings, and may be absent
<button onClick={() => setParams({ region: 'West' })}>West</button>   // null clears a key
```

`setParams` merges into the URL, so a user who filters in-app gets a link they can share — and the
Export button produces a PDF of that same filtered view. Agents can export a filtered view directly
via the `app_params` parameter.

<Warning>
  Use the hook, never `window.location.search`. A direct read works in the viewer but renders the
  app's unfiltered default in PDF/PNG exports. Params filter **within the published snapshot** — they
  can't fetch different data.
</Warning>

## Sandbox project workflow

For complex apps with multiple files, generated assets, or iterative editing:

1. Agent uses `execute_python` to build files in `/home/user/aster-apps/{slug}/`
2. Agent writes an `aster-app.json` manifest:
   ```json theme={null}
   {
     "name": "Pipeline Dashboard",
     "entry": "src/App.tsx",
     "snapshot": "data/snapshot.json",
     "description": "Weekly pipeline overview",
     "assetsDir": "assets"
   }
   ```
3. Agent calls `manage_apps` with `action: "publish_from_sandbox"`

To edit an existing app: call `load_to_sandbox` first, modify files with `execute_python`, then `publish_from_sandbox`.

## Common use cases

### Dashboard from live data

*"Pull our GA4 traffic data and build a dashboard with trends by channel, top pages, and device split"*

### Updating an existing app

*"Refresh the pipeline dashboard with this week's numbers"*

The agent re-queries the data source and calls `update` with new snapshot data.

### Complex multi-section app via sandbox

*"Build a detailed analytics app with separate sections for overview, queries, pages, and opportunities — include downloadable CSV exports"*

The agent builds multiple component files and data assets in the sandbox, then publishes the whole project.
