When you submit input_type: "plan", each step has a kind, a title, an optional instructions and description, and a params object. This page lists every public step kind and the public parameters each accepts. Internal-only workflow parameters are intentionally omitted from this client contract.
The full params object must JSON-stringify to no more than 64 KB per step. Plans are limited to 50 steps total.
Direct plan params are validated when the run is created. Unknown params are rejected, and omitted optional params use the defaults documented below.
Step fields
params says how a step is wired — which steps feed it, how many results to keep, what columns to emit. The three text fields say what it is, in three different registers:
| Field | Type | Required | Read by | Description |
|---|---|---|---|---|
title | string | Yes | People | Up to 200 characters. Names the step in a progress list. |
instructions | string | On filter steps | Models | Up to 20,000 characters. What this step should achieve. |
description | string | No | People | Up to 2,000 characters. One present-tense sentence shown while the step runs. |
instructions is the only one a step's model reads. title and description are for the person watching, and never reach a prompt.
filter requires instructions. A filter judges every candidate against stated criteria, and no filter param carries those criteria — title is a label for a reader, not a rubric for a model. A filter step submitted without instructions is rejected at run creation with schema_validation_failed on plan.steps.N.instructions.
Every other kind treats instructions as optional steering. It is worth setting on transform, analyze, and reconstitute, which read it to decide what to write, what to rank by, and how to phrase the answer.
A plan may also carry a top-level thought_process (up to 8,000 characters) explaining why it is shaped the way it is. The engine's supervisor reads it when judging whether a step's outcome matches what the plan was reaching for.
A plan may also carry a top-level summary (up to 1,000 characters): one or two sentences telling the person who will approve it what it does. The engine's planner writes one for the plans it makes; a plan you supply may omit it.
Defaults applied at run creation:
fetch.output_mode:"entities"vector_search.limit:200vector_search.mode:"semantic"filter.output_mode:"entities"filter.ai_reasoning_column_name:"Reasoning"analyze.mode:"synthesize"
transform.reduce is a runtime default: true for analysis/tabular_view, and false for text_editor/email_editor.
fetch
Retrieve entities from the database or a previous run's artifact.
| Param | Type | Required | Description |
|---|---|---|---|
source | "database" | "artifact" | Yes | Where to read from. |
artifact_id | string | If source = "artifact" | UUID of a prior table or list artifact. |
query | string | No | Search terms used when source = "database". |
limit | integer | No | Maximum rows or entities returned. Retrieval cap, not a top-N ranking — use filter.limit_to for relevance. |
output_mode | "entities" | "tabular_view" | No | Default "entities". Use "tabular_view" for a formatted table artifact. |
title | string | No | Title for the table artifact when output_mode = "tabular_view". |
context_step_ids | integer[] | No | Step indices to pivot from (use their output entities as input). |
{
"index": 0,
"kind": "fetch",
"title": "Fetch climate-tech startups",
"params": { "source": "database", "query": "climate-tech startups in Europe", "limit": 200 }
}vector_search
Run a semantic or keyword search over a candidate pool of entities.
| Param | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query — concepts, sectors, or expertise areas. |
source_step_ids | integer[] | Yes | Step indices whose output entities form the search pool. Every vector_search must reference a prior fetch or filter step. |
limit | integer | No | Maximum results. Default 200. |
mode | "semantic" | "keyword" | No | Default "semantic". Use "keyword" for exact matches like company names or "Series A". |
context_step_ids | integer[] | No | Step indices whose output augments the query (concatenated). |
source_entity_ids | string[] | No | Restrict the search to specific entity IDs. |
{
"index": 1,
"kind": "vector_search",
"title": "Find investors interested in climate-tech",
"params": {
"query": "investors with climate-tech thesis",
"source_step_ids": [0],
"mode": "semantic",
"limit": 100
}
}filter
Reduce a candidate list using LLM-scored relevance evaluation. Requires instructions — see above. The criteria go there, not in params.
| Param | Type | Required | Description |
|---|---|---|---|
steps_to_filter | integer[] | Yes | Step indices whose output entities are filtered. |
limit_to | integer | No | Keep at most this many entities (top-N by relevance). |
output_mode | "entities" | "tabular_view" | No | Default "entities". |
ai_reasoning_column_name | string | No | Column name for the AI-generated reasoning when output_mode = "tabular_view". Default "Reasoning". |
title | string | No | Title for the table artifact. |
context_step_ids | integer[] | No | Additional context steps (e.g., a reference entity for comparison). |
{
"index": 2,
"kind": "filter",
"title": "Top 5 by fund-stage match",
"instructions": "Keep investors whose stated stage focus includes seed or Series A.",
"params": { "steps_to_filter": [1], "limit_to": 5 }
}transform
Run a per-entity LLM transformation. Capped at ~100 entities by default. To remove the cap, set config.unlimited_transform: true on the run; this requires the config:unlimited_transform scope on the API key (otherwise the run is rejected with 403 forbidden_feature).
| Param | Type | Required | Description |
|---|---|---|---|
output_type | "analysis" | "text_editor" | "email_editor" | "tabular_view" | Yes | Output shape. "analysis" is plain text; "text_editor" and "email_editor" produce one artifact per entity; "tabular_view" produces one table for all entities. |
steps_to_transform | integer[] | Yes | Step indices whose output entities are transformed. |
columns | string[] | If output_type = "tabular_view" | Exact column names the LLM must output. |
drop_columns | string[] | No | For "tabular_view" over a saved table (a fetch with source: "artifact"): columns of that table to leave out. The table's other columns and every row are kept. |
reduce | boolean | No | Whether to filter out irrelevant entities. Default true for analysis/tabular_view, false for text_editor/email_editor. |
keep_all_reason | string | No | With reduce: false, one sentence saying why every input row belongs in the result (for example, the request named these records). |
title | string | No | Title for table or artifact. |
context_step_ids | integer[] | No | Additional context steps. |
verbatim_template_step_ids | integer[] | No | For text_editor/email_editor: note steps whose note is a template the draft reproduces word for word, filling only the spots it marks. Each must also be in context_step_ids. |
verbatim_instructions | boolean | No | Every call follows instructions exactly as written. Use it when instructions is a complete rubric that must grade the same way on every run. |
{
"index": 3,
"kind": "transform",
"title": "Generate investor briefs",
"params": { "output_type": "text_editor", "steps_to_transform": [2] }
}analyze
Reduce step outputs into a synthesis, ranking, or set operation. Some modes do not call the LLM (cheap).
| Param | Type | Required | Description |
|---|---|---|---|
mode | "synthesize" | "stack_rank" | "merge" | "intersect" | "overlap" | "exclude" | "pivot_to_row" | No | Default "synthesize". "merge" unions and dedupes; "intersect" keeps entities present in all input steps; "overlap" counts how many input steps each entity is in, sorts by it, and reports exact overlap counts, per record type when the inputs mix types; "exclude" subtracts from the first step. "merge" / "intersect" / "overlap" / "exclude" / "pivot_to_row" skip the LLM call. |
context_step_ids | integer[] | Yes | Step indices to analyze. Use [-1] for passthrough (no context). Min 1. |
top_n | integer | If mode = "stack_rank" | Top-N to keep. Pass -1 to keep all. |
at_least | integer | No | For "overlap" only. Keep only entities in at least this many input steps. At most the number of context_step_ids. |
ranking_criteria | string | If mode = "stack_rank" | Criterion to rank by (e.g., "investment thesis fit"). |
fetch_full_graph | boolean | No | For "synthesize" only. Set true if input is small and you need to read entity notes. |
{
"index": 4,
"kind": "analyze",
"title": "Rank by thesis fit",
"params": {
"mode": "stack_rank",
"context_step_ids": [3],
"top_n": 5,
"ranking_criteria": "thesis alignment"
}
}discover
Surface trends and patterns across a list of entities.
| Param | Type | Required | Description |
|---|---|---|---|
steps_to_discover | integer[] | Yes | Step indices whose output entities are analyzed. |
context_step_ids | integer[] | No | Additional context steps. |
{
"index": 4,
"kind": "discover",
"title": "Find sector trends",
"params": { "steps_to_discover": [3] }
}reconstitute
Synthesize the final user-facing response. Always the last step in a plan.
| Param | Type | Required | Description |
|---|---|---|---|
context_step_ids | integer[] | Yes | Step indices whose output is presented. Use [-1] for passthrough. Min 1. |
expected_artifacts | string[] | Yes | Artifact types reconstitute may create. Use ["NONE"] for text-only responses (the common case when prior steps already produced artifacts). Min 1. |
{
"index": 5,
"kind": "reconstitute",
"title": "Format the result",
"params": { "context_step_ids": [4], "expected_artifacts": ["NONE"] }
}inject_context
Inject known entity, note, or calendar-event UUIDs into the pipeline. Used when you already have concrete IDs and want them available to downstream steps.
| Param | Type | Required | Description |
|---|---|---|---|
entityIds | string[] | No | Entity UUIDs to inject. |
noteIds | string[] | No | Note UUIDs to inject. |
eventIds | string[] | No | Calendar event UUIDs to inject. |
At least one of the three arrays should be provided.
{
"index": 0,
"kind": "inject_context",
"title": "Seed pipeline with target entity",
"params": { "entityIds": ["550e8400-e29b-41d4-a716-446655440000"] }
}