Pipeline schema
Pipelines are YAML files in ~/.vectorstep/pipelines/. Each declares a trigger
(source + match rules), a list of steps (each with an executor, prompt
template, confidence threshold and flow-control policy), and optional
pipeline-level settings (stage, tags, notifications, readiness criteria).
Steps can be defined inline or pulled from the reusable
step library with use:.
A pipeline’s top-level name: (and a library step’s name:) becomes a
filename on disk, so both are restricted to [a-zA-Z0-9][a-zA-Z0-9_-]{0,63} —
letters, digits, underscore and hyphen, starting with a letter or digit, up
to 64 characters. A name outside that pattern is rejected with a validation
error on write. This does not apply to labels that merely look like names,
such as a step’s own name: within steps: or a deterministic check’s
name: — those are never used as filenames.
Model selection and verifiers
Section titled “Model selection and verifiers”Model selection is handled by the named agent’s own config in the executor
backend. To override the model for a specific step, set
executor_config.model — this is passed directly to the executor and takes
precedence over the agent’s configured model.
Steps support an optional verifier block for independent confidence
verification by a second agent. The verifier trigger can be set to
always: true (fires unconditionally), or scoped to a confidence band. See
Verifiers for full trigger configuration
examples.
Step types
Section titled “Step types”The steps list is heterogeneous — each entry is a sequential step (has a
name: key), a parallel group (has a parallel: key), or a fan-out (has a
fan_out: key). See Parallel groups & fan-out
for parallel groups and fan-out, and Executors
(executor: pipeline) for sub-pipeline calls.
Full example
Section titled “Full example”name: alert-triage-criticaldescription: Full triage pipeline for critical alertstags: [critical, sre, grafana] # optional — free-form labels, searchable on /ui/pipelinesversion: 1stage: production # testing (default) | production — see /docs/concepts/stages/
trigger: match: severity: critical # matched against NormalisedContext fields/labels environment: prod # all conditions must match (AND logic) dedup: # optional — overrides config.yaml dedup.* for this pipeline window_seconds: 600 # see /docs/integrations/webhooks/#idempotency--deduplication
context_template: include: # fields auto-injected into every step prompt - severity - labels.service - labels.environment - summary
vars: # pipeline-level variables, available in all prompts jira_project: MYPROJECT confluence_space: MYSPACE
steps: - name: initial-triage executor: openclaw # or: gateway | human | webhook executor_config: agent: sre-triage-sonnet # named agent in the executor backend session_key: "agent:sre-triage-sonnet:{{pipeline_run_id}}:triage" model: anthropic/claude-sonnet-4-6 # optional — overrides agent's configured model thinking_level: low # optional — off|minimal|low|medium|high|xhigh confidence_threshold: 0.75 on_low_confidence: escalate # escalate | abort | proceed on_abort: notify timeout_seconds: 120 prompt_template: | You are an SRE triaging a {{severity}} alert for {{labels.service}} in {{labels.environment}}.
Alert summary: {{summary}}
Return JSON only, no other text: { "confidence": 0.0, "summary": "...", "next_step_context": "...", "reasoning": { "supports": "...", "contradicts": "...", "assumptions": "..." } }
- name: remediation executor: openclaw executor_config: agent: sre-remediation-sonnet session_key: "agent:sre-remediation-sonnet:{{pipeline_run_id}}:remediation" confidence_threshold: 0.85 on_low_confidence: escalate on_abort: notify prompt_template: | Previous triage: {{steps.initial_triage.next_step_context}} ... verifier: executor: openclaw executor_config: agent: sre-verifier-opus combination_strategy: veto veto_floor: 0.60 trigger: confidence_below: 0.95 confidence_above: 0.50
notifications: escalate: - channel: log # always available — zero config required template: | ESCALATED: {{pipeline_name}} — {{step_summary}} config: level: error # debug | info | warning | error | critical - channel: telegram template: | Escalated: {{pipeline_name}} Service: {{labels.service}} - channel: webhook template: | {"text": "Escalated: {{pipeline_name}} — {{labels.service}}"} config: url: https://hooks.slack.com/services/... headers: Authorization: ${SLACK_TOKEN}
notify: - channel: log template: "ABORTED: {{pipeline_name}} — {{step_summary}}" config: level: warning - channel: telegram template: | Aborted: {{pipeline_name}} Service: {{labels.service}} Step: {{current_step}}
schedule: # optional — omit for webhook-only pipelines cron: "*/5 * * * *" summary: "Scheduled health check for my-service" severity: warning labels: service: my-service environment: prod
budget: # optional — omit to run with no token/cost limit max_tokens: 50000 # abort run if accumulated tokens across all steps exceeds this max_usd: 5.00 # abort run if COUNTED cost across all steps exceeds this count_pricing: live_cross_provider # which pricing tiers count toward max_usd — see belowAt least one of max_tokens/max_usd is required if budget: is present at
all; both may be set together (whichever trips first aborts the run and
names which limit it was). count_pricing is a trust threshold naming the
least-trusted pricing tier still allowed to contribute to max_usd —
manual (strictest), live_exact, or live_cross_provider (default,
counts everything). It can also be set per step
(steps[].count_pricing), overriding the pipeline’s default for that
step’s contribution only — None inherits the pipeline’s value. See
Cost accounting for the full
three-tier pricing model this threshold applies to.
Token budget guardrail
Section titled “Token budget guardrail”If budget.max_tokens is set, the runner accumulates input_tokens + output_tokens from each completed step (including all branches of
parallel/fan-out groups) and aborts the run with status=aborted if the total
exceeds the ceiling. The check runs after each successful step — a step
that’s already failed or escalated won’t trigger a second abort. A
budget_exceeded event is appended to the run log.
Token counts come from meta.agentMeta.usage in the VectorStep Gateway response.
Steps using other executors (openclaw, human, webhook) contribute 0
tokens to the accumulator — set max_tokens conservatively if your pipeline
mixes executor types.