Skip to main content
Creates a hook that can be used to suspend and resume a workflow run with a payload from an external system. Hooks allow external systems to send arbitrary serializable data into a workflow. Each hook has a unique token that external systems use to send data.

Signature

function createHook<T = any>(options?: HookOptions): Hook<T>

Parameters

options
HookOptions
Configuration options for the hook.

Returns

Hook<T>
Hook<T>
A hook object that can be awaited or iterated over to receive payloads.

Usage

Basic Hook

Create a hook and await a single payload:
export async function workflowWithHook() {
  "use workflow";

  const hook = createHook<{ message: string }>();
  console.log('Hook token:', hook.token);

  const payload = await hook;
  console.log('Received:', payload.message);
}

Hook with Custom Token

Use a predictable token that external systems can reconstruct:
export async function slackBot(channelId: string) {
  "use workflow";

  // One workflow run per channel
  const hook = createHook<SlackMessage>({
    token: `slack_webhook:${channelId}`,
  });

  for await (const message of hook) {
    console.log('Received message:', message);
  }
}

Hook with Metadata

Attach additional context to the hook:
export async function workflowWithMetadata() {
  "use workflow";

  const hook = createHook<{ name: string }>({
    metadata: {
      type: "cat",
      color: "orange",
    },
  });

  const payload = await hook;
}

Iterate Over Multiple Payloads

Receive multiple payloads using async iteration:
export async function workflowWithMultiplePayloads() {
  "use workflow";

  const hook = createHook<{ message: string }>();

  for await (const payload of hook) {
    console.log('Received:', payload.message);
    if (payload.message === 'done') {
      break;
    }
  }
}

Explicit Resource Management

Use the using keyword for automatic disposal:
export async function workflowWithUsing() {
  "use workflow";

  {
    using hook = createHook<{ message: string }>();
    const payload = await hook;
    // hook is automatically disposed when the block exits
  }
}

Manual Disposal

Release the token early:
export async function workflowWithDisposal() {
  "use workflow";

  const hook = createHook<{ message: string }>({
    token: 'my-token'
  });

  for await (const payload of hook) {
    if (payload.message === 'done') {
      hook.dispose(); // Release the token early
      break;
    }
  }
}

Notes

  • Can only be called inside a workflow function (with "use workflow")
  • Hooks implement AsyncIterable and can be used with for await...of
  • Hooks implement the TC39 Explicit Resource Management proposal
  • The token must be unique across all active hooks in your workflow runs
  • Disposing a hook allows another workflow to register a hook with the same token

Build docs developers (and LLMs) love