Skip to main content

Documentation Index

Fetch the complete documentation index at: https://deepline.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

SDK Reference

Generated from SDK source comments by scripts/generate-play-sdk-reference.ts. Do not edit this file manually.
Generated from SDK source comments by scripts/generate-play-sdk-reference.ts. Do not edit this file manually. This reference covers the play-authoring SDK surface: definePlay, runtime ctx.* primitives, PlayDataset, and tool result accessors. Use .sdk-skills/deepline-sdk/SKILL.md for agent workflow guidance and this page for exact signatures and return shapes.

Runtime Primitives

definePlay

Define a play — a composable TypeScript workflow for the Deepline platform. The returned value is both:
  1. A callable function — invoked by the Temporal worker with a runtime context
  2. A named play handle — with .run(), .versions(), .get(), .publish(), etc. for remote lifecycle management
Plays are the primary abstraction for building repeatable data pipelines. They run on Temporal for durable execution with automatic retries and timeouts.
export function definePlay<TInput, TOutput extends PlayReturnObject>(
  config: DefinePlayConfig<TInput, TOutput>,
): DefinedPlay<TInput, TOutput>;

export function definePlay<TInput, TOutput extends PlayReturnObject>(
  name: string,
  fn: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>,
  bindings?: PlayBindings,
): DefinedPlay<TInput, TOutput>;

Overload 1

Parameters

NameTypeRequiredDescription
configDefinePlayConfig<TInput, TOutput>YesObject-form play config.

Returns

DefinedPlay<TInput, TOutput>

Overload 2

Parameters

NameTypeRequiredDescription
namestringYesPlay name.
fn(ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>YesPlay function.
bindingsPlayBindingsNoTrigger bindings.

Returns

DefinedPlay<TInput, TOutput>

DefinePlayConfig

Object-form play definition accepted by definePlay(config). Use this form when the input contract should be explicit at definition time through defineInput<T>(schema), or when configuration reads clearer as one object. The shorthand definePlay(name, fn, bindings?) is equivalent for simple file-backed plays.
export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = {
  id: string;
  input: PlayInputContract<TInput>;
  run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>;
  bindings?: PlayBindings;
  billing?: PlayBindings['billing'];
};

Fields

NameTypeRequiredDescription
idstringYesPlay id/name.
inputPlayInputContract<TInput>YesInput schema.
run(ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>YesPlay function.
bindingsPlayBindingsNoTrigger bindings.
billingPlayBindings['billing']NoBilling options.

PlayBindings

Optional trigger bindings for a play. Plays can be triggered by webhooks (with HMAC signature verification) or cron schedules. Bindings are declared as the third argument to definePlay.
export type PlayBindings = {
  billing?: {
    maxCreditsPerRun?: number;
  };
  webhook?: {
    hmac?: {
      algorithm?: 'sha256';
      header?: string;
      secretEnv: string;
    };
  };
  cron?: {
    schedule: string;
    timezone?: string;
  };
};

Fields

NameTypeRequiredDescription
billing{ maxCreditsPerRun?: number; }NoOptional per-run billing controls enforced by the runtime.
webhook{ hmac?: { algorithm?: 'sha256'; header?: string; secretEnv: string; }; }NoWebhook trigger with optional HMAC signature verification.
cron{ schedule: string; timezone?: string; }NoCron schedule trigger.

ctx.csv(path, options)

Load a staged CSV file as a durable dataset handle. Use this when a play receives a CSV path from the CLI or API and row work should continue through DeeplinePlayRuntimeContext.map. The path is normally an input field such as input.csv, populated by deepline plays run my.play.ts --csv rows.csv. Each CSV row becomes an object keyed by canonical column names. Use options.columns / options.rename to map user headers such as "Company Domain" to stable code fields such as domain.
csv<T = Record<string, unknown>>(
    path: string,
    options?: CsvOptions,
  ): Promise<PlayDataset<T>>;

Parameters

NameTypeRequiredDescription
pathstringYesStaged CSV path.
optionsCsvOptionsNoCSV load options.

Returns

Promise<PlayDataset<T>>

CsvOptions

Options for loading a staged CSV with ctx.csv(...).
export type CsvOptions = {
  description?: string;
  columns?: CsvRenameMap;
  rename?: CsvRenameMap;
  required?: readonly string[];
};

Fields

NameTypeRequiredDescription
descriptionstringNoHuman-readable description for runtime logs and inspection.
columnsCsvRenameMapNoCanonical field-to-header aliases, e.g. { domain: ['domain', 'Company Domain'] }.
renameCsvRenameMapNoHeader rename map; use columns for new code.
requiredreadonly string[]NoCanonical fields that must be present after header normalization.

ctx.map(key, items)

Create a persisted row dataset/table from input rows. ctx.map is Deepline’s row-work primitive. It records row identity, progress, retries, table output, and idempotency for a collection of rows. Use .step(name, resolver) on the returned builder to define output columns, then .run(...) to execute the row program. The key identifies the logical dataset/table. Renaming it is a persistence migration: existing rows may no longer be reused. Row identity is derived automatically from input row content unless .run({ key: ... }) overrides it with stable business fields such as domain, email, or linkedin_url. By default, ctx.map is row-preserving: one input row produces one output row, with original fields merged with the columns produced by .step(...). If one input entity must become many output rows, use the documented expand/flatten recipe instead of assuming ctx.map changes row cardinality.
map<TItem extends object>(
    key: string,
    items: PlayDatasetInput<TItem>,
  ): MapStepBuilder<TItem, TItem>;

Parameters

NameTypeRequiredDescription
keystringYesDataset/table name.
itemsPlayDatasetInput<TItem>YesInput rows.

Returns

MapStepBuilder<TItem, TItem>

.map(...).step(name, resolver).run(options)

Define one output column for every row in this map dataset. The name becomes a field on each output row. For example, .step('contact', ...) creates row.contact in later map stages; it does not spread returned object fields such as contact.email into row.email. Add a later column resolver when you want a top-level export field: .step('email', row => row.contact?.email ?? null).
step<Name extends string, Value>(
    name: Name,
    resolver: MapStepResolver<OutputRow, Value>,
  ): MapStepBuilder<InputRow, OutputRow & Record<Name, Value>>;

run(options?: {
    description?: string;
    staleAfterSeconds?: number;
    key?:
      | (keyof InputRow & string)
      | readonly (keyof InputRow & string)[]
      | ((
          row: InputRow,
          index: number,
        ) => string | number | readonly unknown[]);
  }): Promise<PlayDataset<OutputRow>>;

Step Parameters

NameTypeRequiredDescription
nameNameYesOutput column name.
resolverMapStepResolver<OutputRow, Value>YesComputes the value for one row.

Step Returns

MapStepBuilder<InputRow, OutputRow & Record<Name, Value>>

Run Parameters

NameTypeRequiredDescription
options{ description?: string; staleAfterSeconds?: number; key?: | (keyof InputRow & string) | readonly (keyof InputRow & string)[] | (( row: InputRow, index: number, ) => string | number | readonly unknown[]); }NoRun options.

Run Returns

Promise<PlayDataset<OutputRow>> Execute the row-column program and return a durable dataset handle. The returned PlayDataset preserves one output row per input row, with original fields merged with the columns produced by .step(...).

ctx.step(id, fn)

Create one scalar checkpoint for the whole play run. Use ctx.step when a value is nondeterministic, expensive, external, or useful to inspect as a named boundary. The first execution stores the JSON-serializable output under id; replay and retries return the stored value instead of running run again. Plain deterministic assignment does not need ctx.step. Use ctx.map(...).step(...), not ctx.step, when the value should become a field on each exported row.
step<T>(
    id: string,
    run: () => T | Promise<T>,
    options?: { staleAfterSeconds?: number },
  ): Promise<T>;

Parameters

NameTypeRequiredDescription
idstringYesCheckpoint id.
run() => T | Promise<T>YesComputes the value once.
options{ staleAfterSeconds?: number }NoCheckpoint options.

Returns

Promise<T>

ctx.runPlay(key, playRef, input, options)

No source JSDoc yet.
runPlay<TOutput = unknown>(
    key: string,
    playRef: string | PlayReferenceLike,
    input: Record<string, unknown>,
    options: { description?: string; staleAfterSeconds?: number },
  ): Promise<TOutput>;

Parameters

NameTypeRequiredDescription
keystringYes
playRefstring | PlayReferenceLikeYes
inputRecord<string, unknown>Yes
options{ description?: string; staleAfterSeconds?: number }Yes

Returns

Promise<TOutput>

ctx.tools.execute(request)

Execute a single tool with a keyword-style request object.
execute<TOutput = LoosePlayObject>(
      request: ToolExecutionRequest & { staleAfterSeconds?: number },
    ): Promise<ToolExecuteResult<TOutput>>;

Parameters

NameTypeRequiredDescription
requestToolExecutionRequest & { staleAfterSeconds?: number }YesTool call request.

Returns

Promise<ToolExecuteResult<TOutput>>

ToolExecutionRequest

Keyword-style request object for ctx.tools.execute(...). The tool value comes from live tool discovery. The id is the stable logical call name inside this play and participates in replay/idempotency.
export type ToolExecutionRequest = {
  id: string;
  tool: string;
  input: Record<string, unknown>;
  description?: string;
  staleAfterSeconds?: number;
};

Fields

NameTypeRequiredDescription
idstringYesStable logical id for this tool call within the play.
toolstringYesCurrent tool id from deepline tools search / deepline tools describe.
inputRecord<string, unknown>YesJSON-serializable provider/tool input object.
descriptionstringNoHuman-readable description for logs and run inspection.
staleAfterSecondsnumberNo

ctx.fetch(key, url, init)

Durable HTTP fetch. Use this for non-provider HTTP calls that must replay safely. The response is recorded under key so workflow replay sees the same value. Prefer ctx.tools.execute(...) for Deepline-managed provider APIs because tools handle auth, retries, rate limits, extraction metadata, and spend tracking.
fetch(
    key: string,
    url: string | URL,
    init?: RequestInit,
    options?: { staleAfterSeconds?: number },
  ): Promise<{
    ok: boolean;
    status: number;
    statusText: string;
    url: string;
    headers: Record<string, string>;
    bodyText: string;
    json: unknown | null;
  }>;

Parameters

NameTypeRequiredDescription
keystringYesCheckpoint id.
urlstring | URLYesURL to fetch.
initRequestInitNoFetch options.
options{ staleAfterSeconds?: number }No

Returns

Promise<{ ok: boolean; status: number; statusText: string; url: string; headers: Record<string, string>; bodyText: string; json: unknown | null; }>

ctx.runSteps(program, input, options)

Run a reusable step program against one scalar input object. steps().step(...) is a composable mini-pipeline. Use ctx.runSteps(...) when that mini-pipeline should execute outside a row dataset. Inside a ctx.map column resolver, pass the step program directly to .step(name, program) instead.
runSteps<TInput extends Record<string, unknown>, TOutput>(
    program: StepProgram<TInput, unknown, TOutput>,
    input: TInput,
    options?: { description?: string },
  ): Promise<TOutput>;

Parameters

NameTypeRequiredDescription
programStepProgram<TInput, unknown, TOutput>YesStep program.
inputTInputYesProgram input.
options{ description?: string }NoRun options.

Returns

Promise<TOutput>

PlayDataset

Durable handle for rows produced by ctx.csv(...) or ctx.map(...).run(). A PlayDataset is not a normal in-memory array. It points at runtime-managed rows, usually backed by persisted sheet storage, and carries metadata such as dataset kind, dataset id, table namespace, count, and preview rows. Pass dataset handles directly into later ctx.map(...) stages by default so Deepline keeps row progress, retries, memory use, and table output under runtime control. Use count() and peek() for bounded inspection. Use materialize(limit) or async iteration only when the dataset is intentionally small and bounded.
export interface PlayDataset<T> extends AsyncIterable<T> {
  readonly datasetKind: PlayDatasetKind;
  readonly datasetId: string;
  readonly backing?: PlayDatasetBacking;
  readonly sourceLabel?: string | null;
  readonly tableNamespace?: string | null;
  count(): Promise<number>;
  peek(limit?: number): Promise<T[]>;
  map<U>(
    mapper: (row: T, index: number) => U | Promise<U>,
    options?: PlayDatasetTransformOptions,
  ): PlayDataset<U>;
  filter(
    predicate: (row: T, index: number) => boolean | Promise<boolean>,
    options?: PlayDatasetTransformOptions,
  ): PlayDataset<T>;
  slice(
    start?: number,
    end?: number,
    options?: PlayDatasetTransformOptions,
  ): PlayDataset<T>;
  take(limit: number, options?: PlayDatasetTransformOptions): PlayDataset<T>;
  materialize(limit?: number): Promise<T[]>;
  toJSON(): {
    kind: 'dataset';
    datasetKind: PlayDatasetKind;
    datasetId: string;
    count: number;
    backing?: PlayDatasetBacking;
    sourceLabel?: string | null;
    tableNamespace?: string | null;
    columns?: string[];
    _metadata?: {
      workProgress?: PlayDatasetWorkProgressSummary;
    };
    preview: T[];
  };
}

Fields

NameTypeRequiredDescription
datasetKindPlayDatasetKindYesDataset kind.
datasetIdstringYesDataset id.
backingPlayDatasetBackingNoBacking store info.
sourceLabelstring | nullNoDisplay label.
tableNamespacestring | nullNoRuntime table name.

ToolExecuteResult

Canonical result returned by Deepline tool execution. The top-level object is Deepline-owned execution metadata and semantic extraction state. Raw tool/provider data lives under toolResponse.raw; response metadata lives under toolResponse.meta. Semantic single-value getters live under extractedValues.<name>.get(), and list getters live under extractedLists.<name>.get(). Use extractors first when a tool contract exposes them. Drop to toolResponse.raw when you need provider-specific fields or when debugging from persisted run rows.
export type ToolExecuteResult<
  TResult = unknown,
  TMeta = Record<string, unknown>,
  TExtracted extends Record<string, unknown> = Record<string, unknown>,
  TLists extends Record<string, Record<string, unknown>> = Record<
    string,
    Record<string, unknown>
  >,
> = ToolExecuteResultBase<TResult, TMeta> &
  ToolExecuteResultAccessors<TExtracted, TLists>;