Skip to content

Quick start

This guide takes you from nothing to a working pair of services, with a first pipeline triggered by a real webhook. VectorStep orchestrates: it receives webhooks, resolves the matching pipeline, and gates each step’s result before continuing. The Gateway executes: it owns the full agentic loop for a step (LLM calls, MCP tool execution, multi-turn conversation) and hands VectorStep back one clean result — never the intermediate tool calls. Start the Gateway first, since VectorStep calls out to it.

  • macOS or Linux (or Windows via WSL2 — the commands below are bash scripts, so there’s no native Windows path yet)
  • Python 3.11+, git
  • An LLM provider API key (Anthropic, OpenRouter, Google, Azure OpenAI, or a local Ollama — the Gateway supports all of them)
  • Nothing else. Local development runs on SQLite with zero infrastructure; PostgreSQL is recommended for production.
Terminal window
curl -sSL https://raw.githubusercontent.com/bantex01/VectorStep-Gateway/main/install-gateway.sh | bash

This clones the Gateway into ~/.vectorstep-gateway/, creates a virtualenv, installs dependencies, and copies the config template. Safe to run again later — it never overwrites an existing config.yaml or agents/.

Terminal window
cd ~/.vectorstep-gateway
# Edit config.yaml — set your LLM provider keys and any MCP servers

For a first agent, copy the bundled sample rather than writing one from scratch — it needs no MCP tools, just a model, so it runs with nothing more than an API key. Once you’re past this guide, Tutorials walks through writing a real one.

Terminal window
cp -r samples/agents/generic-pipeline-step agents/

Copy it as-is, without renaming the directory — the Gateway requires agent.yaml’s name: field to match its containing directory exactly, and skips (with a logged error) any agent where they don’t.

The sample agent defaults to an Anthropic model, which is why that’s the key exported below. The Gateway also supports OpenRouter, Google, Azure OpenAI, and Ollama — see Providers for every model string format.

Terminal window
export ANTHROPIC_API_KEY=sk-ant-...
source .venv/bin/activate && python -m gateway.main

On first run the Gateway generates an identity and an operator token:

Terminal window
cat ~/.vectorstep-gateway/identity/device-auth.json
# Copy the 'operator' token — VectorStep's config needs it in the next step

Both config.yaml and agents/ are gitignored — they hold credentials and environment-specific agent definitions.

Terminal window
curl -sSL https://raw.githubusercontent.com/bantex01/VectorStep/main/install-service.sh | bash

This clones VectorStep into ~/.vectorstep/, with the venv and config set up inside ~/.vectorstep/service/ (SQLite by default — no Postgres prompt). Safe to run again later — it never overwrites an existing config.yaml.

Terminal window
cd ~/.vectorstep/service

Open config.yaml and paste the operator token from step 1 into executors.gateway.token:

executors:
gateway:
token: <paste the operator token here>

Then start it:

Terminal window
source .venv/bin/activate && uvicorn src.main:app --reload --port 8000

Still inside ~/.vectorstep/service/ from step 2. Pipelines are YAML files in pipelines/; reusable steps live in steps/ — both empty on a fresh install. Create both of the files below — a complete pipeline built for the agent you just made, with no MCP tools required, since generic-pipeline-step reasons from the alert payload alone. (The samples bundled in samples/pipelines/ and samples/steps/, one level up, are real production examples wired to OpenClaw and external tools like Jira and Confluence — worth exploring later, but not a fit for this walkthrough.)

Create steps/first-line-triage.yaml:

name: first-line-triage
description: First-line triage for a critical alert — no MCP tools required.
executor: gateway
executor_config:
agent: generic-pipeline-step
session_key: "agent:generic-pipeline-step:{{pipeline_run_id}}:{{current_step}}"
confidence_threshold: 0.60
on_low_confidence: escalate
prompt_template: |
A {{severity}} alert fired for {{labels.service}} in {{labels.environment}}.
Summary: {{summary}}
Summarise what's happening. Set confidence based on how clearly the alert
data explains the problem — not on how serious it is.
Return JSON only, no other text:
{
"confidence": 0.0,
"summary": "One sentence: what's happening and how serious",
"next_step_context": "Focused brief for whatever handles this next",
"reasoning": {
"supports": "Evidence that makes this alert credible",
"contradicts": "Evidence that suggests noise or a false positive",
"assumptions": "What you're assuming in the absence of data"
}
}

Create pipelines/alert-triage.yaml:

name: alert-triage
description: First-line triage for critical alerts
trigger:
match: { source: alertmanager, severity: critical }
dedup:
enabled: false
context_template:
include:
- severity
- summary
steps:
- name: triage
use: first-line-triage # reusable step from your step library
executor: gateway
executor_config:
agent: generic-pipeline-step
confidence_threshold: 0.75
on_low_confidence: escalate # below the bar, a human sees it instead

context_template.include is what makes {{severity}} and {{summary}} resolve to real values in the prompt above — only fields listed here are pulled from the incoming alert; everything else you might reference (like {{labels.service}}) is available without it. Leave a field out and it silently renders as an empty string rather than erroring, so it’s easy to miss if you add a new {{...}} reference later and forget to list it here.

dedup.enabled: false here is a quick-start convenience, not a general recommendation — the bundled test fixture has no unique fingerprint, so every replay hashes identical and would otherwise hit the (correct, and normally desirable) service-wide dedup window. See Idempotency & deduplication for how it works against real alert traffic.

Reload without restarting:

Terminal window
curl -X POST http://localhost:8000/reload
# → {"status": "reloaded", "pipelines_loaded": 1}

Send a test webhook using one of the bundled fixtures:

Terminal window
curl -X POST "http://localhost:8000/webhook?source=alertmanager&allow_testing=true" \
-H "Content-Type: application/json" \
-d @tests/fixtures/alertmanager_critical.json
# → {"status": "accepted", "run_id": "<uuid>"}

New pipelines default to stage: testing — fully executable, but inert to real ingestion traffic until you deliberately opt in with allow_testing=true (or promote the pipeline itself to stage: production later). See Pipeline stages for what each stage actually gates.

Open http://localhost:8000/ui/ — the dashboard shows the run live. Click into it for the full run log: every step’s prompt, output, confidence score, and the Trust panel explaining exactly how each gating decision was made.

Don’t expect a solved incident — expect an honest escalation, and that’s the point. The triage step should show a badge reading escalated, with confidence below the pipeline’s confidence_threshold: 0.75, and a summary that references the real alert content now flowing through {{severity}} and {{summary}} — something like “A critical alert fired for payments-api: error rate exceeded 5% for 5 minutes. No deeper diagnostic data (logs, traces, upstream dependencies) is available to confirm a root cause or rule out a false positive.”

That’s the agent being honest, not broken: generic-pipeline-step has tools: [] — no MCP tools — so even with a concrete metric breach in hand, it has no way to independently verify anything beyond what the alert itself states. It correctly recognises it can’t diagnose the actual cause from that alone, scores its own confidence accordingly, and the pipeline’s on_low_confidence: escalate gate does exactly what it’s supposed to: refuse to let an under-verified assessment pass as if it were a real finding. Expand REASONING on the step to see the model’s own supports/contradicts/assumptions breakdown behind that score.

One thing that can look contradictory at first: the step may show proceed: true right next to an escalated badge. Those are two different signals — proceed is the agent’s own opinion (from its soul.md) about whether its instructions call for stopping outright; the escalation itself is a separate, pipeline-level decision driven purely by confidence falling below the threshold. An agent can think there’s no reason to abort and still get escalated for a human to check, because it didn’t feel confident about what it found.

Giving this same agent real tools — so its low confidence turns into a grounded, higher one — is exactly what Tutorial: build your first agent does next.

You can also live-tail from the run detail page, or query the API directly:

Terminal window
curl http://localhost:8000/runs # newest first
curl http://localhost:8000/runs/<run_id> # full detail with per-step confidence

If any of this — the Gateway, agents, MCP tools, confidence gating — is new to you, don’t jump straight to the reference docs below. Go to Tutorials next: it builds a real agent from scratch, wires it to two MCP servers, and then turns on gating one signal at a time, hands-on. It builds directly on the pipeline you just triggered.

Once you’re comfortable with the mechanics:

  • How confidence and calibration work — the trust vector (S/V/G/D) and every knob that affects it. Read this before turning on any enforcement.
  • Pipeline schema — the full YAML reference: verifiers, grounding, parallel groups, fan-out, flow control.
  • Verifiers — adding a second opinion to a step, and when to use critic vs independent mode.