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

# Use Flow actions

> Read and update Flow data safely from an automation.

## Flow actions

Flow actions let automation code work with tickets, assets, people, teams, knowledge, and access records. Import each family from its exact `@flow/actions/<domain>` path.

Flow checks the current execution identity, team permissions, and product access on every call. References such as `{ kind: "primary" }`, `{ kind: "run_team" }`, and `{ kind: "run_beneficiary" }` keep organization, team, and person identifiers out of author code.

Each step can contain at most one Flow action or integration action. Keep data preparation in a separate local step when one privileged call depends on another.

## Update a ticket and notify the requester

This example loads the primary ticket, updates it with a revision precondition, adds a team-only note, and sends a run-bound in-app update.

```ts theme={null}
import * as messaging from "@flow/actions/messaging";
import * as tickets from "@flow/actions/tickets";
import { defineAutomation, schema } from "@flow/automations";

export const prioritizeRequest = defineAutomation({
  name: "prioritizeRequest",
  displayName: "Prioritize Request",
  description: "Prioritize a request and record the reason.",
  triggers: ["direct"],
  tags: ["tickets"],
  input: schema.object({ reason: schema.string() }),
  output: schema.object({ ticketId: schema.string() }),
  run: async (input, _ctx) => {
    /**
     * @step loadTicket
     * @description Load the ticket attached to this automation run.
     */
    const ticketResult = await tickets.get({ ticket: { kind: "primary" } });
    if (ticketResult.outcome === "failed") throw new Error(ticketResult.error.message);
    const ticket = ticketResult.data;

    /**
     * @step prioritizeTicket
     * @description Mark the ticket urgent if it has not changed since it was read.
     */
    const updatedResult = await tickets.update(
      {
        ticket: { kind: "id", id: ticket.id },
        expectedRevision: ticket.revision,
        changes: { priority: "urgent", status: "pending" },
      },
    );
    if (updatedResult.outcome === "failed") throw new Error(updatedResult.error.message);
    const updated = updatedResult.data;

    /**
     * @step recordReason
     * @description Add the prioritization reason for the service team.
     */
    const noteResult = await tickets.addInternalNote(
      { ticket: { kind: "id", id: updated.id }, body: input.reason },
    );
    if (noteResult.outcome === "failed") throw new Error(noteResult.error.message);

    /**
     * @step notifyRequester
     * @description Tell the requester that the ticket was prioritized.
     */
    const notificationResult = await messaging.sendNotification(
      {
        audience: { kind: "requester" },
        message: "Your request was prioritized.",
      },
    );
    if (notificationResult.outcome === "failed") {
      throw new Error(notificationResult.error.message);
    }

    return { ticketId: updated.id };
  },
});
```

Use `expectedRevision` when a ticket mutation depends on a value read earlier. Asset field and assignment updates require the revision returned by the read action.

Asset actions use organization-scoped `assetKey` and `assetTypeKey` values instead of internal IDs. Use run-relative references or email for people, and `{ kind: "run_team" }` or a team key for management teams. Operator asset results expose `assetKey`; asset action results never expose internal UUIDs.

## Available actions

| Import | Helper | Purpose | Required product area | Stable ID |
| - | - | - | - | - |
| `@flow/actions/access` | `getGrant` | Get a visible access grant. | Access management | `flow.access.get-grant@2.0.0` |
| `@flow/actions/access` | `getRequest` | Get a visible access request. | Access management | `flow.access.get-request@2.0.0` |
| `@flow/actions/access` | `searchGrants` | Search access grants visible to the execution identity. | Access management | `flow.access.search-grants@2.0.0` |
| `@flow/actions/ai` | `generateText` | Generate text with Flow's managed inference service. | Automations | `flow.ai.generate-text@2.0.0` |
| `@flow/actions/ai` | `summarize` | Summarize text with Flow's managed inference service. | Automations | `flow.ai.summarize@2.0.0` |
| `@flow/actions/approvals` | `getRequest` | Get the status of a visible approval request and its linked access request, when present. | None | `flow.approvals.get-request@2.0.0` |
| `@flow/actions/approvals` | `requestAndAwaitDecision` | Request and await a decision through a publication-pinned approval procedure. | None | `flow.approvals.request-and-await-decision@2.0.0` |
| `@flow/actions/assets` | `addComment` | Add a comment to an organization asset. | Assets | `flow.assets.add-comment@3.0.0` |
| `@flow/actions/assets` | `assign` | Assign or unassign an organization asset. | Assets | `flow.assets.assign@3.0.0` |
| `@flow/actions/assets` | `create` | Create an organization asset with optional management-team authorization metadata. | Assets | `flow.assets.create@3.0.0` |
| `@flow/actions/assets` | `get` | Get a visible organization asset. | None | `flow.assets.get@3.0.0` |
| `@flow/actions/assets` | `getPrimaryComputer` | Find the primary computer for a run-related person. | None | `flow.assets.get-primary-computer@3.0.0` |
| `@flow/actions/assets` | `listTypes` | List organization asset types available to the automation. | None | `flow.assets.list-types@3.0.0` |
| `@flow/actions/assets` | `search` | Search visible organization assets with bounded filters and paging. | None | `flow.assets.search@3.0.0` |
| `@flow/actions/assets` | `updateFields` | Update organization asset fields with a required revision precondition. A null value clears a field. Clearing is refused for a required field and for a field a connected source owns; overwriting such a field is allowed and pins it against later synchronization. The field the org-wide asset key is derived from cannot be written here. | Assets | `flow.assets.update-fields@3.0.0` |
| `@flow/actions/catalog` | `get` | Get a published catalog entry by reference. | None | `flow.catalog.get@2.0.0` |
| `@flow/actions/knowledge` | `search` | Search knowledge visible to the execution identity. | Knowledge | `flow.knowledge.search@2.0.0` |
| `@flow/actions/messaging` | `requestResponse` | Request authenticated free text from one trusted person and wait for the response. | None | `flow.messaging.request-response@2.0.0` |
| `@flow/actions/messaging` | `sendNotification` | Queue one automation update for a trusted person through their enabled channels. | None | `flow.messaging.send-notification@2.0.0` |
| `@flow/actions/people` | `get` | Get a person's details by principal ID or email address. | None | `flow.people.get@2.0.0` |
| `@flow/actions/people` | `search` | Search the organization directory when the execution identity permits it. | None | `flow.people.search@2.0.0` |
| `@flow/actions/teams` | `get` | Get a visible team by reference. | None | `flow.teams.get@2.0.0` |
| `@flow/actions/teams` | `list` | List teams visible to the automation. | None | `flow.teams.list@2.0.0` |
| `@flow/actions/tickets` | `addInternalNote` | Add a team-only note to a ticket. | Conversations | `flow.tickets.add-internal-note@2.0.0` |
| `@flow/actions/tickets` | `create` | Create a Flow ticket through the canonical ticket command. | Conversations | `flow.tickets.create@2.0.0` |
| `@flow/actions/tickets` | `get` | Get a visible ticket by reference. | Conversations | `flow.tickets.get@2.0.0` |
| `@flow/actions/tickets` | `resolve` | Resolve a ticket with an optional revision precondition. | Conversations | `flow.tickets.resolve@2.0.0` |
| `@flow/actions/tickets` | `search` | Search tickets visible to the automation. | Conversations | `flow.tickets.search@2.0.0` |
| `@flow/actions/tickets` | `update` | Update ticket fields with an optional revision precondition. | Conversations | `flow.tickets.update@2.0.0` |

Result lists are paged and bounded. Use the returned cursor unchanged, with the same filters and automation run, to request the next page. Cursors expire after 30 days. If a cursor expires, restart the list without it. Flow rejects hidden resources without confirming whether they exist.

## Errors and testing

Flow actions return the same exact result envelope as integration actions. Check `result.outcome` immediately. A definitive business failure is returned as `outcome: "failed"`; a platform or indeterminate failure throws `ActionSystemError` with a support reference.

```ts theme={null}
import * as tickets from "@flow/actions/tickets";

const result = await tickets.get({ ticket: { kind: "primary" } });
if (result.outcome === "failed") {
  throw new Error(result.error.message);
}
return { ticketId: result.data.id };
```

Automation tests provide mocks by stable ID. A mocked test fails when a declared Flow action has no fixture, so tests cannot silently call live product data.

## Automation updates

Use `messaging.sendNotification(input)` from `@flow/actions/messaging` to send one update. Flow chooses the recipient's enabled channels: in-app, browser toast, email, and the connected chat provider. Slack delivers a direct message; Microsoft Teams delivers a personal message. Add `delivery: { channels: ["teams"] }` to limit delivery to Teams. Add `onNoEligibleChannel: "error"` inside `delivery` if the automation must fail when none of the selected channels is configured and eligible for the recipient. Flow queues notifications during a temporary chat connection failure and retries delivery a limited number of times. The older `deliveryMethod` field still selects exactly one channel, subject to the recipient's preferences.

Supported audiences come from the automation run: `requester`, `opener`, or an explicitly selected `team_member`. The API does not accept an arbitrary recipient. Chat delivery sends a private message to that person. Teams requires the recipient to have a verified Teams identity and an active personal Flow installation. Without a connected chat provider, Flow uses the eligible in-app, browser toast, and email channels. An accepted request can still fail later during provider delivery.

`message` accepts up to 8,192 UTF-8 bytes. Messages selected for Slack delivery must also fit within 2,900 characters. This limit also applies while the Slack connection is temporarily unavailable. Teams shows a preview with up to 256 characters in the title and 4,000 in the body. Flow retains the full notification content.

`messaging.requestResponse` remains a single-channel interaction. Its required `deliveryMethod` is `"email"` or `"slack"`. If the recipient has disabled that channel for automation input requests, the action fails before the automation begins waiting for a reply.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.