Skip to main content
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 for the full pattern. These node types share the same names as the 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.
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:
rowNumber: Workflows.OutcomeSchema.number().title("Row number")

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

FactoryTypeScript typeDescription
OutcomeSchema.string()WorkflowOutcomeDataStringNodeFree-form text
OutcomeSchema.number()WorkflowOutcomeDataNumberNodeNumeric value
OutcomeSchema.boolean()WorkflowOutcomeDataBooleanNodeTrue/false
OutcomeSchema.stringEnum(values)WorkflowOutcomeDataStringEnumNodeOne value from a fixed list of strings
richText() is available in the Config schema but not in the Outcome schema.

Date and time nodes

FactoryTypeScript typeDescription
OutcomeSchema.date()WorkflowOutcomeDataDateNodeCalendar date without time
OutcomeSchema.timestamp()WorkflowOutcomeDataTimestampNodePoint in time (date + time + timezone)
OutcomeSchema.duration()WorkflowOutcomeDataDurationNodeLength of time

Contact and identity nodes

FactoryTypeScript typeDescription
OutcomeSchema.emailAddress()WorkflowOutcomeDataEmailAddressNodeEmail address
OutcomeSchema.phoneNumber()WorkflowOutcomeDataPhoneNumberNodePhone number
OutcomeSchema.personalName()WorkflowOutcomeDataPersonalNameNodeFirst and last name
OutcomeSchema.domain()WorkflowOutcomeDataDomainNodeWeb domain (e.g. attio.com)
OutcomeSchema.location()WorkflowOutcomeDataLocationNodeGeographic location
OutcomeSchema.currency()WorkflowOutcomeDataCurrencyNodeMonetary value with currency code

Attio object nodes

FactoryTypeScript typeDescription
OutcomeSchema.attioRecord()WorkflowOutcomeDataAttioRecordReference to an Attio record
OutcomeSchema.attioObject()WorkflowOutcomeDataAttioObjectReference to an Attio object type
OutcomeSchema.attioList()WorkflowOutcomeDataAttioListReference to an Attio list
OutcomeSchema.attioActor()WorkflowOutcomeDataAttioActorReference to an Attio actor
OutcomeSchema.attioAttribute()WorkflowOutcomeDataAttioAttributeReference to an attribute on an Attio object
OutcomeSchema.attioSelect()WorkflowOutcomeDataAttioSelectSelect value from an Attio attribute
OutcomeSchema.attioSequence()WorkflowOutcomeDataAttioSequenceReference to an Attio sequence
OutcomeSchema.attioTask()WorkflowOutcomeDataAttioTaskReference 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.
configurator.tsx
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.
execute.ts
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