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

# Outcome schema

> Node types for typing outcome data returned from workflow block handlers

The outcome schema node types describe the shape of data that an outcome branch exposes to downstream steps. They are used in the `Outcome` component's `schema` prop inside `configurator.tsx` via `Workflows.OutcomeSchema.*`, and they inform the typed variables the workflow editor makes available.

The actual `data` value returned by handlers (`execute`, `trigger`, `finish`) is a plain JS object whose shape must match the declared schema, not a schema node itself. See [Configurator](./configurator) for the full pattern.

These node types share the same names as the [Config schema](./config-schema) but use the `WorkflowOutcomeData*` TypeScript prefix. `richText()` is not available in the outcome schema.

Every outcome data object must be rooted in a `struct` node.

<Note>
  Use snake\_case for outcome schema field keys. Outcome data is serialized and exposed as variables
  in the workflow editor, so field keys become the variable names downstream steps see. If you don't
  use snake\_case, chain `.title()` on the node to provide a readable display name:

  ```ts theme={"system"}
  rowNumber: Workflows.OutcomeSchema.number().title("Row number")
  ```
</Note>

## Composite nodes

### `OutcomeSchema.struct(fields)`

Root of every outcome data object.

### `OutcomeSchema.array(element)`

A list of values of the given node type.

## Primitive nodes

| Factory                            | TypeScript type                     | Description                            |
| ---------------------------------- | ----------------------------------- | -------------------------------------- |
| `OutcomeSchema.string()`           | `WorkflowOutcomeDataStringNode`     | Free-form text                         |
| `OutcomeSchema.number()`           | `WorkflowOutcomeDataNumberNode`     | Numeric value                          |
| `OutcomeSchema.boolean()`          | `WorkflowOutcomeDataBooleanNode`    | True/false                             |
| `OutcomeSchema.stringEnum(values)` | `WorkflowOutcomeDataStringEnumNode` | One value from a fixed list of strings |

<Note>
  `richText()` is available in the [Config schema](./config-schema) but **not** in the Outcome
  schema.
</Note>

## Date and time nodes

| Factory                     | TypeScript type                    | Description                            |
| --------------------------- | ---------------------------------- | -------------------------------------- |
| `OutcomeSchema.date()`      | `WorkflowOutcomeDataDateNode`      | Calendar date without time             |
| `OutcomeSchema.timestamp()` | `WorkflowOutcomeDataTimestampNode` | Point in time (date + time + timezone) |
| `OutcomeSchema.duration()`  | `WorkflowOutcomeDataDurationNode`  | Length of time                         |

## Contact and identity nodes

| Factory                        | TypeScript type                       | Description                       |
| ------------------------------ | ------------------------------------- | --------------------------------- |
| `OutcomeSchema.emailAddress()` | `WorkflowOutcomeDataEmailAddressNode` | Email address                     |
| `OutcomeSchema.phoneNumber()`  | `WorkflowOutcomeDataPhoneNumberNode`  | Phone number                      |
| `OutcomeSchema.personalName()` | `WorkflowOutcomeDataPersonalNameNode` | First and last name               |
| `OutcomeSchema.domain()`       | `WorkflowOutcomeDataDomainNode`       | Web domain (e.g. `attio.com`)     |
| `OutcomeSchema.location()`     | `WorkflowOutcomeDataLocationNode`     | Geographic location               |
| `OutcomeSchema.currency()`     | `WorkflowOutcomeDataCurrencyNode`     | Monetary value with currency code |

## Attio object nodes

| Factory                          | TypeScript type                     | Description                                  |
| -------------------------------- | ----------------------------------- | -------------------------------------------- |
| `OutcomeSchema.attioRecord()`    | `WorkflowOutcomeDataAttioRecord`    | Reference to an Attio record                 |
| `OutcomeSchema.attioObject()`    | `WorkflowOutcomeDataAttioObject`    | Reference to an Attio object type            |
| `OutcomeSchema.attioList()`      | `WorkflowOutcomeDataAttioList`      | Reference to an Attio list                   |
| `OutcomeSchema.attioActor()`     | `WorkflowOutcomeDataAttioActor`     | Reference to an Attio actor                  |
| `OutcomeSchema.attioAttribute()` | `WorkflowOutcomeDataAttioAttribute` | Reference to an attribute on an Attio object |
| `OutcomeSchema.attioSelect()`    | `WorkflowOutcomeDataAttioSelect`    | Select value from an Attio attribute         |
| `OutcomeSchema.attioSequence()`  | `WorkflowOutcomeDataAttioSequence`  | Reference to an Attio sequence               |
| `OutcomeSchema.attioTask()`      | `WorkflowOutcomeDataAttioTask`      | Reference to an Attio task                   |

## Example

This example models an action block that sends an email and exposes two variables to downstream steps: the provider's message ID and the time the email was sent.

**Step 1: declare the schema in the configurator.** Render an `<Outcome>` component whose `schema` prop maps field keys to `Workflows.OutcomeSchema.*` nodes. The workflow editor reads this to build the variable picker for downstream steps; `message_id` and `sent_at` become available as typed variables once a workflow run produces this outcome.

```tsx configurator.tsx theme={"system"}
import {Workflows} from "attio/client"
import block from "./block"

export default Workflows.defineConfigurator(block, (workflowBlock) => {
  const {Outcome} = Workflows.useConfigurator(workflowBlock)
  return (
    <Outcome
      id="email-sent"
      schema={{
        message_id: Workflows.OutcomeSchema.string(),
        sent_at: Workflows.OutcomeSchema.timestamp(),
      }}
    />
  )
})
```

**Step 2: return matching data from the handler.** The `data` object in the return value must be a plain JS object whose keys and value types match the declared schema. The `id` ties the return value back to the `<Outcome>` declared above; that is how the workflow engine knows which branch to follow and which variables to populate.

```ts execute.ts theme={"system"}
import {Workflows} from "attio/server"
import block from "./block"

export default Workflows.defineWorkflowBlockExecute(block, async ({config, metadata}) => {
  const response = await fetch("https://api.example.com/emails", {
    method: "POST",
    body: JSON.stringify({to: config.recipient_email}),
  })
  const result = (await response.json()) as {id: string}

  return {
    type: "outcome",
    id: "email-sent",
    data: {message_id: result.id, sent_at: new Date()},
  }
})
```

## See also

* [Configurator](./configurator): the `Outcome` component and `Workflows.OutcomeSchema.*` namespace
* [Config schema](./config-schema): all available schema field types
* [Executing a step](./define-workflow-block-execute): step execute handler
* [Receiving a trigger event](./define-workflow-block-on-trigger-callback): trigger event handler
