Overview
Flows is the customer-facing workspace for reviewing Genesis flow definitions and recent run history. Use it to see step composition, scheduling, runtime placement, last-run status, and graph-based detail views for both definitions and individual runs.In auth-enabled deployments, opening Flows requires
view_flows.
Granting a role access to specific Flows also implies view_flows, so the
workspace stays visible when those object-level grants are present.Interrupted copy recovery
If the server restarts while abulk_copy or sql step is writing to an
external table, Genesis leaves the step interrupted and keeps
rows_written unknown. While a qualifying interrupted step is waiting, a
background check counts the rows currently held by its target within the first
six hours after the interruption and adds that evidence to the step summary.
For a bulk_copy that copied a whole named source table, the summary also
includes the source count. A query-driven copy is reported with the target
count only.
The check does not change the step status or turn the count into a
rows_written result. Append-mode targets can include rows from before the
step, so their target and source counts are not expected to match. Configure
the check with jobs.flow_interrupted_copy_target_check.enabled (default
true) and jobs.flow_interrupted_copy_target_check.interval_seconds (default
120; 0 or less disables the interval) in Advanced Settings.
What the page supports
Managed source scan types can be added later, but removing an enabled scan type
from an existing source is not supported. Delete and recreate the source with
the desired scan types.
include and exclude selectors on a managed flows source narrow which
artifacts Genesis discovers and enables. Selectors without glob metacharacters
are exact matches; selectors with *, ?, or [...] use shell-style glob
matching against artifact_id, artifact_type:artifact_id, path, and
artifact_type:path. exclude overrides include when both match. On the
next sync, flows that no longer match are retired: Genesis disables the flow,
removes its cron job from the scheduler, and clears managed dependency rows for
that source. Retirement applies only to flows this managed source created; a
local flow with the same name stays enabled and keeps its schedule.
Git-backed vs Genesis-versioned flows
Flows synced from a managed Git repository show a green git-backed badge on the detail header. Flows authored and versioned inside Genesis show genesis-versioned (gray badge). The modes are mutually exclusive: git-backed flows cannot use Genesis version-history promote, revert, restore-to-draft, or discard-working-copy actions until you copy them to a standalone flow. A synced definition held becauseauto_promote_on_sync is off has its own review-and-promote action; see
Multi-Instance Sync
for that lifecycle.
Click the badge for a short explainer. On git-backed flows, Fork to standalone →
in the badge explainer opens a modal to name the new flow (defaults to
<flow_name>-standalone). The flow inspector also exposes a Fork to standalone
button for git-backed flows. API: POST /api/flows/{flow_id}/fork with body
{"new_name":"<flow_name>"} (requires manage on the source). Agents can use
flow_action(action="FORK_TO_STANDALONE", params={"flow_id":"...", "new_name":"..."}).
Pause and Resume remain available on git-backed flows. Enabling or disabling a
flow is runtime instance state, not a versioned definition change, so you can
emergency-stop a scheduled git-backed flow without forking first.
Review a synced Flow change
When a managed source hasauto_promote_on_sync: false, a flow with a waiting
change shows a pending-promotion status in its row and detail header. Open the
flow and choose Review and promote to inspect the incoming definition before
making it live. If a promotion was applied but its finishing step did not
complete, the header offers Finish promotion. These controls require admin
or manage_flows permission.
To review a new Flow that has no row in the Flows list yet, use Manage Sources
in the page header and open the source’s waiting artifacts. A newly synced Flow
can be enabled as part of promotion; that option applies only to new Flows.
Inspect a flow or run
From the Flows tab, click a row or flow name to open the definition inspector. Use the Runs picker to choose any recent run, including the current in-progress run, or click a last-run status badge or a row in Run History to open run details. If no runs exist yet, the picker shows No runs yet. Definition and run graphs can also show dedicated data nodes for declared inputs and outputs, observed run outputs, and data references inferred from supported Python database and dataset calls. Hover a data node to see its direction, source, location, and, when available, rows written. On the Flows page and in Deployments → Flows, clicking a step or data node on the definition or run graph opens a focused inspect modal with Input, Logic (SQL, Python, or bulk-copy metadata from the flow definition), Summary, Output samples, and errors. Use the branch icon in the header or open a flow from the list when you need the full multi-pane inspector with version history and scheduling controls. In the full inspector, clicking a data node still jumps to the related step details. When you select a step node, Genesis can show:- connection and execution metadata,
- the step’s SQL query or Python code,
- run errors or output summaries,
- sample output data when the run returns previewable results, including single-object payloads or wider tables in the expanded preview.
Succeeded after N attempts. Failure payloads shown through the UI and API
also redact local absolute paths before they reach the client.
For a step that writes rows to an external target, a failed write keeps the
Genesis-composed refusal context—such as the step’s mode, connection, table, or
statement label—whole, while masking any target-provided text attached to it.
For failures composed by the target, Genesis keeps the target’s error codes and
any recognised column or query details, while masking quoted values, numbers,
and echoed statements on a best-effort basis. A quoted target column name from
the rows being written remains visible, compared case-insensitively against the
write’s schema, so a failed copy can identify the column without exposing the
values beside it. If the message cannot be parsed confidently, Genesis withholds
the message and shows the codes instead. The full target error remains available
in the server log at DEBUG level; the masked or withheld form is what appears
in the run record, activity log, and retry notifications.
For Python step code, the inspector applies Genesis-aware highlighting to these flow references when they appear: tools.call, flow.emit, from genesis_flow import ..., genesis_flow.llm, genesis_flow.tools, genesis_flow.flow, llm.chat, and llm.complete.
Genesis SDK v1 does not replace the flow-step helpers on this page. Inside
flow Python steps, keep using
genesis_flow.tools, genesis_flow.llm,
genesis_flow.flow, genesis_flow.secrets, and the flow-scoped tokens
Genesis injects. Genesis.from_environment() is intended for
execute_python_code and external Python programs for now.Python-step LLM calls
Flow runs stay deterministic by default, but a Python step can make a one-shot model call throughgenesis_flow.llm.ask(...) when the pipeline needs
classification, summarization, extraction, or another bounded LLM step. These
calls do not run the full chat agent loop; they route through the Genesis model
stack and bill like other base LLM usage. With cost accounting enabled, calls
without a real conversation thread are recorded as system work in the Cost &
Usage cube rather than as conversation-thread activity.
model_tier and provider to inherit the flow authoring thread’s
defaults when available; otherwise Genesis falls back to the flow bot’s default
tier and provider resolution. Legacy model="fast", model="main", and
model="frontier" are still accepted as tier aliases for older flow code.
result.usage includes the resolved provider, model_tier,
configured_model, model, total_duration_ms, and token counts when the
provider returns them.
Chain the model output vs enrichment-only
Treatgenesis_flow.llm.ask results as forward when the next SQL step,
Python step, condition, or UI state must parse structured output — use
response_format when you need JSON and validate before writing result or
flow.emit. Treat the call as side-channel when the text is narrative,
audit notes, or optional columns that no branch depends on; downstream steps
should succeed even if enrichment is empty.
Genesis ships the built-in app-flow-llm-usage AgentSkill (default
thread-start on new deployments) with the same guidance for Genesis Apps
(/llm/call, /llm/direct) and Flow Python steps.
Team Wiki writes from flow steps
Whenwiki.write_enabled is true in AppConfig, a Flow Python step (or the
sandbox execute_python_code runtime) may call wiki_write through the flow
tool bridge if wiki_write is on the step’s signed tool allowlist. Genesis
stamps each write with a source_channel provenance tag the agent cannot
override: flow:<flow_id> for normal flow steps, or runtime:<execution_id>
for sandbox Python execution (the bridge reuses the flow identity with
step_name="execute_python_code"). Interactive chat writes keep the default
chat tag. Background Librarian extraction from conversations is independent
and requires wiki.librarian_enabled in addition to wiki.write_enabled; see
Advanced Settings → Team Wiki / Librarian settings.
Persist step output
When a step declares anoutput target, Genesis expects the step result to resolve to tabular rows shaped as a list of objects. Python steps can return rows directly, or return a dictionary with a row field:
output.from so the runner knows which field to write:
result = rows, {"data": rows}, {"result": rows}, {"rows": rows}, or a nested dictionary selected with a dotted output.from path such as payload.rows. SQL steps already return list[dict] rows directly, so omit output.from for SQL outputs; from: "data" and from: "rows" are tolerated for compatibility. If a step declares an output target but Genesis cannot extract rows, the run fails with an explicit extraction error instead of silently completing without a dataset write.
SQL result column casing follows the underlying connector and database conventions. Some backends, especially Snowflake-compatible paths, may return unquoted aliases such as kind and n as KIND and N. Use quoted aliases in SQL when exact column casing matters.
In run results, SQL reads report Query returned N rows, with rows_written set to the number of returned rows. SQL writes report Statement wrote N rows and set rows_written when the engine returns a recognized non-negative write count. If the engine does not report one, the summary says Statement completed; rows written: not reported by the engine and rows_written is null. Counts come from the write statement’s result; rows returned by RETURNING are still available as output but are not treated as a write count.
For Databricks targets, a completed Flow step can also provide writer evidence to a Prover
comparison when its relation and run timing match the target’s last-write reading and the
target snapshot is bound to that step’s connection. See how the Prover attributes a clean
table.
For Genesis Dataset outputs, table_name controls the table inside the dataset snapshot. If you omit it, Genesis defaults to the explicit dataset_id when provided, otherwise a slug of dataset_name such as Root Directories -> root_directories. If dataset_id is provided and no dataset exists yet, Genesis creates that stable dataset id automatically. If only dataset_name is provided, Genesis derives the new dataset id from the same slug and falls back to a UUID only when that id already exists. This keeps flow-populated datasets queryable with predictable table names.
For synthetic data or other publish-style Iceberg flows, prefer one publish step per target table:
This sample targets the local catalog. In a Databricks App, the built-in
iceberg.genesis_iceberg connection is the persistent Genesis lakehouse on Unity
Catalog. Flow outputs that omit connection_id use that connection by default;
omit namespace as well to write to the App’s lakehouse schema. An explicit
namespace must be that schema, because the App identity cannot access other
schemas. See Databricks App deployment guidance.
context_output: "metadata" keeps the full row payload out of downstream step context after the publish succeeds, while preserving rows_written, output_target, and output_location. Use context_output: "sample" when later steps need a small preview, and context_output: "full" only for small row sets that downstream steps truly need.
Flow Python steps can emit structured metadata with either flow.emit({"key": value}) or flow.emit("key", value). Downstream steps can read selected values through context/steps, or use explicit input mappings such as inputs: {"previous_rows": "producer.rows"}.
Use depends_on to declare dependencies; needs is accepted as an alias. SQL steps use query, with sql accepted as an alias for agent ergonomics. on_failure supports continue, log, notify_thread, pause_schedule, retry, and stop.
Set run_concurrently: true on consecutive independent steps to run them as a
batch. Genesis runs at most 8 steps in one batch and waits for every step in the
batch before starting the next step or batch. Use this for independent
bulk_copy steps when several tables share the same flow; do not use it when
one step reads another step’s output. Within a batch, bulk_copy steps targeting
registered connections (output.target: "external") execute up to 4 at once;
bulk_copy steps targeting Iceberg tables still execute one at a time.
Move a table between registered connections
To copy a whole table between two registered connections, use abulk_copy step.
The step reads the complete source relation in the worker and chooses the target
writer from the target connection type. Use either source_table for a table-wide
copy or query when the source relation needs a projection or filter:
connection_id, plus either source_table or query. Set mode
to replace or append. The output.target can be iceberg or external; an
external target also requires output.connection_id and output.table. External
bulk writers are available for registered Snowflake, Databricks, and SQLite
connections. The default timeout_seconds is 1800.
When Genesis validates a flow’s dotted connection ids, it also checks the legacy
connection store, so seeded demo ids such as sqlite.baseball_sqlite are accepted.
If a connection store cannot be read, Genesis reports that id as unchecked rather
than claiming it is missing.
Genesis uses this value as the worker deadline, converting it to minutes
without imposing a one-minute minimum.
For SQL and bulk_copy steps, you can also use a bare registered connection
name such as workspace_sqlite; Genesis resolves its registered type before
executing the step. The same applies to output.connection_id for an external
target. If Genesis cannot resolve an external target’s dialect, it refuses the
write rather than guessing how to quote SQL identifiers and values.
External output configuration refusals are reported as configuration errors,
including missing required fields, unsupported mode or identifier_case
values, invalid output.table names, and unresolved target dialects. These
errors show the step’s configuration details instead of being withheld as
possibly row-bearing target text.
If a bulk_copy step is cancelled, Genesis tells the worker to stop and waits
up to 30 seconds for the worker’s answer. The worker cancels any statement
already in flight and refuses the one final statement that would change the
target. Therefore, a copy stopped during staging leaves an existing target
unchanged, and a missing target is still missing. The run is marked cancelled
and its step summary says that nothing was written. A copy that finishes before
the cancellation is answered completes with its rows.
If cancellation arrives while the final target statement is already running,
the database may commit it before the abort takes effect. Genesis reports that
the target may have committed and tells you to verify it before relying on the
result or rerunning. A cancelled run does not retry the copy. If the step runs
past its wait time or the worker shuts down during staging, Genesis also stops
the copy before the final target statement. A hard worker shutdown can leave
the temporary stage, Volume, or scratch table behind; remove it after checking
the target. These are abandoned copies, not target-side failures.
For a Databricks target, add output.staging_volume with an existing Unity Catalog
Volume when you want to control staging. Use exactly three name parts:
catalog.schema.volume. When it is omitted, Genesis creates a temporary Volume
in the target schema and attempts to remove it after the copy.
replace uses an atomic target write for Databricks and a transaction for SQLite,
so a failed load does not first clear the previous target rows. When the target
is missing, Databricks creates it together with the loaded rows in the final
statement instead of creating an empty table first. If the source contains text values
beside numbers and the existing target column is numeric, Genesis checks the target
before staging and refuses the copy with the column names, target types, and text
value counts; it does not include the values themselves.
The result includes rows_written and execution_mode; rows_written is null
when the target does not report a count. When a Databricks bulk copy creates a
missing table and its final statement returns no count, Genesis retrieves the
created table’s count with a COUNT(*) query. If that query fails,
rows_written remains null; the completed copy still succeeds. A failed
external write reports the count committed by the target, not the number read
from the source: it is 0 when the
target is unchanged, a partial count when earlier append batches committed, and
null when the target may be empty or incomplete. External target steps do not
store output row samples in the run record; use the target connection to inspect
the data. When SQLite source columns contain only empty values, bulk copy
preserves their declared SQLite types instead of inferring a type from those
values. For a source column that is numeric apart from empty-string ('')
values, SQLite writes each empty string as NULL. The step result includes
values_nulled with each affected column and its count, and the step summary
explains the conversion; check it before reconciling by row count alone.
For a SQLite source, a column with no non-NULL values (including a column in
an empty result) keeps its declared SQLite type when one is available, so a
valueless numeric column remains numeric. If a column has no value and no
declared type, it is written as text; valueless_as_text and the step summary
name that column. A source column containing text alongside numbers is also
written as text when the target accepts it; text_beside_numbers reports the
text count by column and the summary names the affected columns. A Databricks
target with an existing numeric column still refuses such a copy before
staging, as described above.
Bulk copy keeps Infinity, -Infinity, and NaN as numeric values for
Databricks, Snowflake, and Iceberg targets. SQLite stores infinities as REAL,
but bulk copy refuses a column containing NaN before opening the target
database because SQLite would store it as NULL; nothing is written. Replace
NaN with NULL or a number in the source query, or use a target that stores
NaN.
For a Snowflake target, use a two- or three-part output.table name. A two-part
name uses the connection’s CURRENT_DATABASE() value; if no current database is
available, name the database explicitly. Snowflake stages the Parquet file in an
internal stage that Genesis creates and removes for that copy. append loads the
stage directly into the target. replace loads a transient scratch table first,
then atomically overwrites the target, so a failed copy does not leave the existing
target empty. When the target is missing, Snowflake loads a scratch table first
and creates the target with its rows in one final statement, instead of creating
an empty table first. Snowflake matches staged columns by name without regard to case.
Set output.identifier_case to preserve (the default), upper, or lower when
you want Snowflake to apply that case to the target and its newly created columns.
Databricks and SQLite accept only preserve on the bulk path. A connection type
without a bulk loader, or a bulk loader that cannot honor the requested identifier
case, fails the bulk_copy step; Genesis does not silently substitute the
row-by-row writer. The result’s execution_mode identifies the native path, such
as snowflake_stage_copy_into for append or
snowflake_stage_insert_overwrite for replace.
The get_connection() handle in a Python step is not an alternative for this transfer:
it is read-only for this purpose, its response is hard-capped at 200,000 bytes, and a
larger read raises instead of truncating. It exposes query(sql) and
cursor().execute(sql), but no connection-level .execute() or commit(). Use
bulk_copy for large transfers instead of materializing the source through a Python
step.
For a Lakebase connection using Databricks App identity, use a Flow SQL step or
local Python step rather than a Python sandbox step; see Connections — Databricks
Lakebase connections.
See Snowflake attribution.
SQL step safety
Flow SQL steps can use the normal query surface, but Genesis now blocks namespace-levelCATASTROPHIC statements in both definition validation and
runtime safeguards. DROP DATABASE, DROP SCHEMA, DROP CATALOG, and
CREATE OR REPLACE DATABASE/SCHEMA/CATALOG require an interactive
user_override, so they are not allowed inside saved flow definitions or
unattended flow runs.
If you need one of those operations, run it directly through chat with
_query_database after explicit human approval instead of embedding it in a
Flow. Older saved Flows that already contain one of these statements now fail
closed at run time instead of executing it.
Definition fingerprints
Genesis exposes a canonicaldefinition_sha256 fingerprint when you create,
inspect, update, revert, or validate a flow through flow_action (CREATE,
GET, GET_VERSION, UPDATE, REVERT, or VALIDATE_DEFINITION). The hash
covers portable execution fields — description, parameters /
parameters_schema, steps, on_failure, tags, and schedule when present
— and excludes the instance-local Flow name. Use it to confirm that a reviewed
candidate matches the definition you are about to apply, revert, or promote.
Flow input parameters
Flow definitions can declare optionalparameters_schema entries, or the
equivalent parameters alias, so each run starts with typed inputs instead of
only raw strings. Each parameter can define type, optional default, and
optional required. At run start, Genesis fills defaults, rejects missing
required values, and coerces primitive int / integer, float / number,
bool / boolean, and str / string inputs before exposing them in the
initial step context.
parameters alias:
execution_target: "sandbox" runs inside an isolated container. Listing / from a sandbox shows the container filesystem, not the host computer. The local execute_python_code executor confines reads and writes to BOT_GIT_PATH, BOT_REPOS_PATH, and BOT_SCRATCH_PATH (import with from genesis import ...), including writes into the repo working tree; paths outside those roots are refused.
For local Python process cleanup, see Code Executor Tools.Automation surface
Programmatic schedule updates
When you schedule a flow throughflow_action, Genesis accepts either a
structured cron trigger object or flat cron fields. The flat form supports
schedule, cron, or cron_expression, with optional timezone that
defaults to UTC. Cron strings must contain exactly 5 fields in
minute hour day month day_of_week order. For structured Flow cron triggers,
use minute, hour, day_of_month, month, and day_of_week; Genesis
normalizes day_of_month to the scheduler’s day field when it syncs the
saved Flow schedule. Genesis validates cron field ranges and IANA timezones
before it saves the schedule. A SCHEDULE call with an unrecognized params
key is refused without changing the schedule.
trigger=null and omit other schedule keys.
The REST route PUT /api/flows/{flow_id}/schedule uses the same cron payload
shape and also accepts {"type":"interval","seconds":<positive_integer>} when
you need a fixed interval instead of cron.
New or changed Flow schedules that run more often than hourly need a future
end_date inside trigger. Runs less than 5 minutes apart require an end date
within 7 days of creation or renewal; runs at least 5 minutes but less than an
hour apart require one within 30 days. Hourly and slower schedules may omit it.
Cron uses the shortest time-of-day gap, including midnight, even when calendar
restrictions separate actual runs. These checks run before saving a schedule
or selecting a historical version through revert or promotion.
For example, a temporary poller can use
{"type":"interval","seconds":60,"end_date":"<future ISO timestamp within 7 days>"}.
Supply the complete Flow trigger when renewing it, with the new end date.
For intentional ongoing automation, set perpetual:true and a nonempty
perpetual_reason explaining the lifetime owner, and omit end_date.
Managed Jira and ServiceNow polling Flows use this explicit intent and stop when
their configuration disables polling. Existing schedules remain operational
after startup until their schedule is edited; edits to unrelated Flow details
do not impose a new expiration.
Choose a cadence that matches the source’s update rate. Frequent LLM-backed
work can consume tokens and encounter rate limits; a Flow can perform direct
polling without a new LLM decision for each run. For scheduler audit fields and
the MODIFY_JOB renewal operation, see
Process Scheduler Tools.
Scheduled flows that use Connections
A flow step that uses a saved Connection resolves the connection’s secret in the context of whoever runs the flow. A manual run uses your identity; a scheduled run executes as a system scheduler user instead. If that scheduler user has no RBAC role bound to the connection, the scheduled run fails immediately with an error likeConnection '<type>.<name>' is not available or has no secret access key configured — even though the manual run worked. This is a common
next-morning surprise when building a first scheduled pipeline.
To fix this before the first scheduled tick, grant the connection a role the
scheduler user holds (commonly user) under Roles with Access:
- In the UI: Config → Connections → [connection] → Edit → Roles with Access.
- From an agent:
connections_action(action="UPDATE", connection_type="aws", name="my_conn", roles_with_access=["user"]).GETreturns the current bindings, andrbac_action(action="LIST_ROLES")lists valid role names.
A run started from a chat reports back to it
When an agent starts a Flow from a conversation, that run records which thread and which bot launched it. The moment the run reaches a terminal status —completed, failed, cancelled, or interrupted by a server restart — a
notice naming the run id, its kind and its outcome is delivered into that
conversation, and the agent’s next turn sees it.
This is what lets an agent say “I’ll report when it finishes” and mean it. It
applies on success as much as on failure: before it existed, silence meant
either “still running” or “finished and nobody said anything”, which is not a
signal anyone could act on.
Two properties worth knowing:
- The notice reaches an active thread on its next tool result. If the agent is mid-turn when the run ends, the full run result is attached to the next tool result. If the thread is idle, the notice arrives as a new turn instead.
- The notice includes the full run result. It carries the same result that
GET_RUNreturns, so the agent does not need a second lookup before reporting on the run. Flows → Run History remains available for human inspection.
interrupted and leaves rows_written unknown (null). The target may have
received the complete write, part of it, or none of it, so verify the target
before relying on the result or rerunning the step. A step that was still
pending never started and wrote nothing.
A run with no launching conversation — a scheduled run, or one started over the
API — has nobody to report to and stays silent here. This also applies when an
outside caller invokes a Flow through MCP or POST /api/tool_call: even if the
request carries a thread id, the caller has no Genesis conversation session to
receive a wake. Read the outcome with GET_RUN. Operator notifications below
cover unattended scheduled failures.
Unattended failure notifications
Scheduled Flows that fail without anyone watching must still reach an operator. Genesis now posts a baseline in-app notification when an unattended run ends infailed status, independent of the Flow’s on_failure setting. This is
separate from the opt-in escalation path (on_failure: notify_thread →
flow_failure_notifications outbox → Slack drain job), which stays silent on
stock configuration until you wire each layer.
When a notification fires, the bell shows title Scheduled Flow Failed and
a short message naming the Flow and how many scheduled runs have failed in a
row. Genesis keeps error text out of the message body (it can carry query
fragments) and stores a truncated copy in notification metadata for diagnostics.
Open Flows → Run History or the notification entity link to inspect the
failed run.
Notification policy is driven by flows.failure_visibility in App Config
(config/config-example.yaml):
Genesis counts consecutive failures since the Flow last completed successfully.
cancelled and interrupted runs are skipped — cancelling one run does not
reset a genuine failure streak. Manual runs do not match the default unattended
trigger set.
A Flow that keeps failing on schedule does not ring the bell on every run.
The escalation ladder (first_notify_after_failures, repeat_every_failures)
and min_seconds_between_notifications floor cap how often Genesis creates a
new Scheduled Flow Failed notification. Between those ladder notifications,
failed runs stay deliberately quiet because the operator was already told about
the current failure streak. The scheduler subprocess also stands down its
generic job-failure bell for those quiet runs, so a Flow failing every minute
does not produce one generic alert per minute. If the Flow recovers and then
fails again, that new streak is treated as a fresh outage and can alert again.
Process restart or eviction of in-memory notification state fails open — an
operator who might not have been told may receive another alert.
After you see an alert, use the evidence-first RCA tools below — not the
notification prose alone — before stating a root cause.
Flow failure investigation and RCA
When a Flow step exhausts retries or a run fails withon_failure: notify_thread,
Genesis can deliver a trusted failure alert that includes the durable run ID.
When the failed run carries an isolated presenter demo_scope (for example from
an RCA demo fixture prepared through the presenter routes), the alert also
includes a Demo scope line so operators can tell which presenter session
produced the failure.
Agents investigating that failure must use the evidence-first RCA tools in
flow_tools — not the alert prose alone — before stating a root cause.
Recommended workflow:
inspect_flow_failure(run_id=...)— load persisted execution evidence (task definition, error log, retry exhaustion, connection identity, preceding-step context) and receiverequired_citations(exactlabel=valuestrings to copy into finalization). Genesis stamps a thread-scoped inspection receipt in the current thread.- Reconcile and correct — derive the cause from the returned evidence, update the Flow to a newer version, and stage the exact correction against the inspected artifact.
run_flow_rca_verification(...)— the combined finalizer. Passfailed_run_id,root_cause,evidence_citations(every value fromrequired_citations), andremediation_summary. Genesis runs or reuses a linkedrca_verificationrun on the newer Flow version, then durably persists the corrected outcome and protected gold record. A successful terminal receipt (task_durably_complete: true) means the RCA is complete; restate the cited result in the next message and do not callrecord_flow_rca_outcome.record_flow_rca_outcome(...)— use only when correction cannot run yet (remediation_status='staged') or when manual recovery is needed after a completed linked verification. Staged outcomes do not create protected gold.
run_flow_rca_verification or
record_flow_rca_outcome returns the canonical completed outcome without
overwriting the protected record. If a downstream tool reports a missing or
mismatched inspection receipt, call inspect_flow_failure again in the same
thread before retrying finalization.
For tool parameters and response fields, see
flow_tools RCA tools
in the Genbot Toolkit.
Sharing flows across instances
If your organization runs multiple Genesis instances, flows can be sourced from a shared Git repository so they propagate to every instance through normal pull-request review. The flow YAML uses logical refs like@snowflake.warehouse that resolve per-instance via local bindings, so the
repository file stays portable. See
Multi-Instance Skill, Flow & App Sync.
Flow definition files must be valid YAML. Quote scalar values that contain a
colon, such as description: "Global policy: all X", so discovery and sync can
read the managed source consistently.
Related pages
- Multi-Instance Skill, Flow & App Sync — share Git-backed flows across instances.
- Scheduler
- Digital Twin and Context Graph

