Skip to content

Key Concepts

Runsight has five core primitives: workflows, blocks, souls, tools, and dispatch. Everything is defined in YAML files on your filesystem. Git is the version control layer.

A workflow is a YAML file in custom/workflows/ that defines a directed graph of blocks. The engine discovers workflow files automatically.

version: "1.0"
blocks:
research:
type: linear
soul_ref: researcher
summarize:
type: linear
soul_ref: writer
depends: research
workflow:
name: Research Pipeline
entry: research

A workflow file has these top-level sections:

SectionDefaultPurpose
version"1.0"Schema version
blocks{}Block definitions keyed by block ID
workflowrequiredGraph metadata — name, entry block, and transitions
souls{}Inline soul definitions (optional shorthand)
tools[]Tool IDs available to this workflow
limitsnoneBudget constraints (cost caps, timeouts)
evalnoneTest cases for offline evaluation
enabledfalseWhether the workflow is active
interfacenonePublic input/output contract for callable sub-workflows
config{}Arbitrary workflow configuration

Only workflow is required — all other sections have defaults.

Workflows are nestable — a workflow block can execute another workflow file as a child, with parent-child run linkage and independent error handling.

Blocks are the execution units inside a workflow. Each block has a type that determines its behavior. Runsight ships with six block types:

TypeWhat it does
linearSingle LLM call through a soul. The most common block type.
gateLLM quality gate — evaluates another block’s output and routes on pass/fail.
codeRuns Python code. Define a def main(data) function in the code field.
loopIterates inner blocks for up to max_rounds rounds with optional break conditions.
workflowExecutes a child workflow via workflow_ref. Parent-child run linkage, on_error modes.
dispatchParallel branching — each exit port gets its own soul and task instruction. All branches execute concurrently.

All blocks share a unified execution lifecycle via execute_block():

  1. Observer notified (on_block_start)
  2. Block-scoped budget session created (if limits defined)
  3. Retry wrapper applied (if retry_config defined)
  4. Timeout enforced via asyncio.wait_for
  5. Block executes
  6. Exit conditions evaluated — sets the exit_handle for downstream routing
  7. Observer notified (on_block_complete)

Blocks can define assertions for quality evaluation, exits for multi-path routing, depends for dependency ordering, and error_route for error-specific branching.

A soul is an agent identity — it defines who an LLM is and how it behaves. Souls are YAML files in custom/souls/:

custom/souls/researcher.yaml
id: researcher_v1
role: Senior Researcher
system_prompt: >
You are an expert researcher. Given a topic, provide a concise,
well-structured summary of key findings, trends, and insights.
provider: openai
model_name: gpt-4.1-mini
temperature: 0.7
max_tokens: 2048

Soul fields:

FieldRequiredPurpose
idYesUnique identifier
roleYesAgent role label
system_promptYesLLM system instructions
providerNoLLM provider (e.g., openai, anthropic)
model_nameNoModel name (e.g., gpt-4.1-mini). Falls back to runner default if omitted.
temperatureNoSampling temperature
max_tokensNoOutput token limit
toolsNoTool names this soul can use
avatar_colorNoUI display color
max_tool_iterationsNoMax tool-use loops per execution (default: 5)

Blocks reference souls via soul_ref:

blocks:
research:
type: linear
soul_ref: researcher # resolves to custom/souls/researcher.yaml

Souls can also be defined inline in the workflow YAML as optional shorthand — see Inline Souls.

One soul per step. Each block references at most one soul. The exception is dispatch, where each exit port has its own soul.

Tools are capabilities that souls can use during execution. They come in three types:

  • Built-in tools: Ship with Runsight — delegate (exit port routing), http (outbound requests), file_io (file operations)
  • Custom tools: YAML files in custom/tools/ with a Python or HTTP executor
  • HTTP tools: Declarative HTTP request definitions

Custom tool example:

custom/tools/slack_payload_builder.yaml
version: "1.0"
type: custom
executor: python
name: Slack Payload Builder
description: Builds a Slack message payload from plain text.
parameters:
type: object
properties:
text:
type: string
required: [text]
code: |
import json
def main(args):
return {"payload_json": json.dumps({"text": args["text"]})}

Tools are identified by their filename stem — a file at custom/tools/slack_payload_builder.yaml has tool ID slack_payload_builder. Built-in tools use reserved IDs: delegate, http, file_io.

Tools are discovered automatically from custom/tools/.

Tool governance is enforced at the workflow level: a soul only gets access to tools that the workflow explicitly lists in its tools section. Both the workflow and the soul must declare the tool for it to be available during execution.

Dispatch is the branching mechanism. There are two ways to branch in Runsight:

Any block can define exits. When a soul lists delegate in its tools and the workflow enables it, the soul can call delegate(port="...", task="...") to pick which exit port to route to — making the LLM the decision-maker.

blocks:
triage:
type: linear
soul_ref: triager
exits:
- id: urgent
label: Urgent — needs immediate attention
- id: normal
label: Normal — standard processing
handle_urgent:
type: linear
soul_ref: responder
depends: triage
handle_normal:
type: linear
soul_ref: processor
depends: triage

The delegate tool requires two parameters: port (constrained to the declared exit IDs) and task (instruction for the downstream block). The soul must list delegate in its tools array, and the workflow must include delegate in its top-level tools list.

The dispatch block type runs all branches concurrently — each exit port gets its own soul and task instruction. Unlike exit ports on a linear block (where the LLM picks one), dispatch executes every branch.

See Dispatch & Delegate for details.

Everything in Runsight is a file:

PrimitiveLocationFormat
Workflowscustom/workflows/*.yamlYAML
Soulscustom/souls/*.yamlYAML
Toolscustom/tools/*.yamlYAML

Git is the version control layer:

  • Save writes the workflow YAML to disk and commits to the main branch
  • Dirty runs (unsaved changes) automatically create simulation branches (sim/{workflow-slug}/{YYYYMMDD}/{short-id})
  • Every run records the commit SHA of the workflow that executed
  • Fork recovery lets you branch from a failed run to iterate without losing history
  • The run detail view shows the historical YAML snapshot — the exact file content that ran, not the current version

There is no database for workflow definitions. Your repo is the database. Diff your workflows, review them in PRs, roll back with git.