Skip to main content
import { Signal } from "smithers-orchestrator";

type SignalProps = {
  id: string; // signal name and node id
  schema: z.ZodObject; // typed payload + output target
  correlationId?: string;
  timeoutMs?: number;
  onTimeout?: "fail" | "skip" | "continue"; // default "fail" (applied by the underlying <WaitForEvent>)
  async?: boolean;
  skipIf?: boolean;
  dependsOn?: string[];
  needs?: Record<string, string>;
  label?: string;
  meta?: Record<string, unknown>;
  key?: string;
  smithersContext?: React.Context<SmithersCtx | null>; // advanced: inject a custom Smithers context
  children?: (data) => ReactNode; // mounts only after payload arrives
};
import { Signal, Task, Workflow, createSmithers } from "smithers-orchestrator";
import { z } from "zod";

const { smithers, outputs } = createSmithers({
  feedback: z.object({ rating: z.number(), comment: z.string() }),
  summary: z.object({ upper: z.string() }),
});

export default smithers(() => (
  <Workflow name="signal-demo">
    <Signal id="user-feedback" schema={outputs.feedback} async>
      {(feedback) => (
        <Task id="summarize" output={outputs.summary}>
          {{ upper: feedback.comment.toUpperCase() }}
        </Task>
      )}
    </Signal>
  </Workflow>
));

Notes

  • Renders <WaitForEvent event={id} output={schema}> internally.
  • Async waits show in smithers_external_wait_async_pending{kind="event"}.
  • Delivering a signal does not resume a suspended run on its own. From the CLI, send the payload with bunx smithers-orchestrator signal RUN_ID user-feedback --data '{...}' (the second argument is the signal name, which equals the <Signal> id), then resume the run with bunx smithers-orchestrator up workflow.tsx --run-id RUN_ID --resume true. This is the keeper-loop pattern from the CLI overview.
  • Run both commands from the workspace root, the directory that holds .smithers/. The CLI resolves the run database (smithers.db) from the nearest .smithers/ anchor walking up from the current directory, so a different working directory points at a different (or missing) database.