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

# @arg/actions

> Discover, validate, run, batch, and inspect Arg Actions from a live TSX or JSX workspace app.

`@arg/actions` is the typed Action API for a `.tsx` or `.jsx` app running inside Arg. It delegates to the authenticated preview bridge, so your source never receives an API key and never chooses the workspace or audit surface.

There is nothing to install:

```tsx theme={null}
import { actions } from "@arg/actions";
```

The package is a facade over `window.arg.actions`. HTML apps use that injected namespace directly; React apps should use the typed import.

## Enable Actions for a preview

Actions are off by default. They are available only for an editable React preview in a cloud workspace.

<Steps>
  <Step title="Open Permissions">
    On web and desktop, open the `.tsx` or `.jsx` file and click **Permissions** in the preview
    toolbar. On iOS and Android, open the **...** file menu and choose **Permissions**.
  </Step>

  <Step title="Enable Actions">
    Turn on **Actions**, then review **Allow Actions for this preview?** and click **Allow
    Actions**.
  </Step>

  <Step title="Choose whether to remember it">
    Leave **Remember for this file** off for a one-time grant. Turn it on to restore the choice for
    this file on the current device after the file opens or its code changes.
  </Step>
</Steps>

The grant is separate from **Workspace access**. Actions can reach the whole workspace, spend credits, and use the viewer's connected services, so a folder-scoped file grant never implies Action access.

## Check availability

Wait for the preview handshake before reading `enabled`:

```tsx theme={null}
import { actions } from "@arg/actions";

async function actionAccessAvailable() {
  try {
    await actions.ready;
    return actions.enabled && !actions.readOnly;
  } catch {
    return false;
  }
}
```

Importing the package is safe during static or headless rendering. Calls reject when the app is not inside an authenticated Arg preview with Action access enabled.

## API

| Member                           | Returns                             | Purpose                                                  |
| -------------------------------- | ----------------------------------- | -------------------------------------------------------- |
| `ready`                          | `Promise<Actions>`                  | Resolves after the preview receives its Action context   |
| `enabled`                        | `boolean`                           | Whether this source currently has an active grant        |
| `readOnly`                       | `boolean`                           | Whether the host prevents Action execution               |
| `list(options?)`                 | `ActionCatalogEntry[]`              | Search and filter the current Action catalog             |
| `schema(actionId)`               | `{ id, inputSchema, outputSchema }` | Read one Action's JSON Schemas                           |
| `describe(actionId, options?)`   | `DescribeActionResult`              | Resolve dynamic fields, choices, and conditional schemas |
| `run(actionId, input, options?)` | `RunActionResponse<TOutput>`        | Run one Action                                           |
| `runBatch(calls)`                | `ActionBatchResponse`               | Run up to 50 independent Actions in one request          |
| `getRun(runId)`                  | `ActionRunDescriptor<TOutput>`      | Read one durable run                                     |
| `listRuns(options?)`             | `ActionRunDescriptor<TOutput>[]`    | List recent durable runs in the workspace                |

The default export is the same facade, so `import actions from "@arg/actions"` also works.

## Discover an Action

Action ids and their inputs come from the live registry. Search and reflect instead of guessing them.

```tsx theme={null}
import { actions } from "@arg/actions";

await actions.ready;

const catalog = await actions.list({
  query: "generate image",
  category: "image",
  includeSchema: true,
});

const selected = catalog[0];
const { inputSchema, outputSchema } = await actions.schema(selected.id);
const modelChoices = await actions.describe(selected.id, {
  field: "model",
  limit: 50,
});
```

### `list` filters

| Option          | Type                 | Effect                                                                                         |
| --------------- | -------------------- | ---------------------------------------------------------------------------------------------- |
| `query`         | `string`             | Search ids, titles, and descriptions                                                           |
| `category`      | `ActionCategory`     | Filter by `image`, `video`, `audio`, `3d`, `document`, `web`, `data`, `integration`, or `file` |
| `runtime`       | `"cloud" \| "local"` | Filter by where the Action can run                                                             |
| `backend`       | `string`             | Filter by the catalog's backend identifier                                                     |
| `includeSchema` | `boolean`            | Include input and output schemas on catalog entries                                            |

`describe` accepts `field`, `value`, `query`, `category`, and `limit`. Use `field` to list a dynamic field's current options. Add `value` to resolve the conditional schema for one selected option. `limit` must be from 1 to 200.

## Run one Action

```tsx theme={null}
import { actions } from "@arg/actions";

type ImageOutput = { output_path: string };

const run = await actions.run<ImageOutput>(
  "image_generate",
  {
    prompt: "A red bicycle on a beach at sunset",
    output_path: "/images/bicycle.png",
  },
  { idempotencyKey: "bicycle-cover-v1" },
);

if (run.status === "succeeded") {
  console.log(run.output?.output_path);
}
```

`input` must be an object and must match the current Action schema. `idempotencyKey` is optional, but use a stable value before retrying anything that writes, spends credits, or calls a connected service. A key can contain up to 200 characters.

Run status is `queued`, `running`, `succeeded`, `failed`, or `canceled`. A synchronous Action returns its output immediately. If an asynchronous Action is still queued or running, inspect the durable run:

```tsx theme={null}
if (run.status === "queued" || run.status === "running") {
  const current = await actions.getRun<ImageOutput>(run.runId);
  console.log(current.status, current.progress, current.output);
}
```

<Note>
  Do not poll a succeeded synchronous read. Its `runId` can identify an audit event without a
  durable run record, so `getRun` may return not found even though the output already arrived
  successfully.
</Note>

## Batch independent calls

Use `runBatch` when a screen needs several independent results. It accepts from 1 to 50 calls.

```tsx theme={null}
import { actions } from "@arg/actions";

const { results } = await actions.runBatch([
  { actionId: "file_read", input: { path: "/brief.md" } },
  { actionId: "file_read", input: { path: "/data/summary.json" } },
  {
    actionId: "image_generate",
    input: {
      prompt: "A red bicycle",
      output_path: "/images/bicycle.png",
    },
    idempotencyKey: "dashboard-bicycle-v1",
  },
]);

for (const result of results) {
  if (result.ok) console.log(result.run.output);
  else console.error(result.actionId, result.error.message);
}
```

A batch is not a transaction. Results stay in request order, each call reports its own success or failure, and one failed call does not roll back its siblings. Later calls cannot use earlier outputs. An unknown Action id rejects the request before any call runs.

Give every write, billable, or connected-service call its own stable `idempotencyKey` before retrying a batch after a transport failure.

## Inspect run history

```tsx theme={null}
const failed = await actions.listRuns({
  actionId: "image_generate",
  status: "failed",
  limit: 20,
});
```

`listRuns` accepts `actionId`, `status`, and a `limit` from 1 to 200. Run records include status, progress, output, error, timestamps, and cost when available.

## Handle errors

Bridge and API failures reject with an `Error`. When the bridge supplies a machine-readable reason, it adds a `code` property.

```tsx theme={null}
try {
  await actions.run("file_write", { path: "/result.txt", content: "Done" });
} catch (error) {
  const code =
    error instanceof Error && "code" in error
      ? String((error as Error & { code: unknown }).code)
      : "unknown";

  if (code === "disabled") {
    console.log("Turn on Actions in the preview Permissions menu.");
  } else if (code === "read_only") {
    console.log("This preview cannot run write Actions.");
  } else {
    console.error(error);
  }
}
```

Common bridge codes include `disabled`, `read_only`, `bad_request`, `action_request_failed`, and `http_<status>`. Timeouts and an unavailable bridge can reject without a `code`, so always keep a general fallback.

## Exported types

The package exports the runtime types used above, including `Actions`, `ActionCatalogEntry`, `ActionSchemaResult`, `DescribeActionResult`, `ActionRunDescriptor`, `RunActionResponse`, `ActionBatchCall`, `ActionBatchResult`, `ActionBatchResponse`, `ActionRunStatus`, `ActionProgress`, and the option types for each method. It also exports `ACTION_BATCH_MAX_CALLS`, currently `50`.

Use `ActionCatalogEntry.inputSchema` and `outputSchema` for registry-driven interfaces. Use the generic output parameter on `run`, `getRun`, and `listRuns` when your app already knows one selected Action's output shape.

## Security and scope

* Calls run as the signed-in viewer and stay fixed to the current cloud workspace.
* The preview never receives an API key or session token.
* The viewer's workspace permissions and the current Action schema are checked on every call.
* Connected-service Actions use the viewer's selected connection and its existing permissions.
* A source change revokes the one-time grant. **Remember for this file** is the explicit opt-in to restore it on this device.
* Public previews, read-only previews, local-folder workspaces, and deployed Sites cannot use the viewer-authorized bridge.

## Related

* [React app SDKs](/guides/apps/react-apps)
* [Build with `@arg/ui`](/guides/apps/ui-sdk)
* [Actions over HTTP](/guides/actions)
* [Actions API reference](/api-reference/actions/list-actions)
