vectorstep-service-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vectorstep_service_mcp-0.1.0/LICENSE +21 -0
- vectorstep_service_mcp-0.1.0/PKG-INFO +84 -0
- vectorstep_service_mcp-0.1.0/README.md +53 -0
- vectorstep_service_mcp-0.1.0/pyproject.toml +55 -0
- vectorstep_service_mcp-0.1.0/setup.cfg +4 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/__init__.py +1 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/__main__.py +13 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/client.py +59 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/__init__.py +0 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/confidence_and_trust_vector.md +120 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/promotion_readiness.md +97 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/prompt_versions.md +110 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/stages_and_scoping.md +58 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/docs/statuses_and_accuracy.md +75 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/errors.py +75 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/server.py +9 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/tools/__init__.py +1 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/tools/analytics.py +283 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/tools/docs.py +78 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/tools/read.py +91 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp/tools/write.py +149 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/PKG-INFO +84 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/SOURCES.txt +31 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/dependency_links.txt +1 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/entry_points.txt +2 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/requires.txt +7 -0
- vectorstep_service_mcp-0.1.0/src/vectorstep_service_mcp.egg-info/top_level.txt +1 -0
- vectorstep_service_mcp-0.1.0/tests/test_client.py +118 -0
- vectorstep_service_mcp-0.1.0/tests/test_e2e.py +155 -0
- vectorstep_service_mcp-0.1.0/tests/test_stub.py +5 -0
- vectorstep_service_mcp-0.1.0/tests/test_tools_docs.py +112 -0
- vectorstep_service_mcp-0.1.0/tests/test_tools_read.py +435 -0
- vectorstep_service_mcp-0.1.0/tests/test_tools_write.py +288 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Dalton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vectorstep-service-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server exposing VectorStep's authoring, inspection, and analytics surface to MCP clients (Claude Code/Desktop).
|
|
5
|
+
Author-email: Alex Dalton <alex@vectorstep.io>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://vectorstep.io
|
|
8
|
+
Project-URL: Documentation, https://vectorstep.io/docs/integrations/mcp/
|
|
9
|
+
Project-URL: Changelog, https://vectorstep.io/docs/about/status-and-support/
|
|
10
|
+
Keywords: mcp,vectorstep,ai,agents,orchestration,pipelines
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Topic :: System :: Monitoring
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: mcp==1.28.1
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Requires-Dist: pyyaml>=6.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# VectorStep Service MCP
|
|
33
|
+
|
|
34
|
+
An [MCP](https://modelcontextprotocol.io) server that exposes [VectorStep](https://github.com/bantex01/VectorStep) — pipeline authoring, run inspection, and analytics — to MCP clients such as Claude Code and Claude Desktop.
|
|
35
|
+
|
|
36
|
+
## What it is
|
|
37
|
+
|
|
38
|
+
A separate, standalone repository and process with no import-level dependency on VectorStep — the two are coupled only over HTTP, so each can be developed, versioned, and deployed independently.
|
|
39
|
+
|
|
40
|
+
It lets an MCP client create and edit pipelines and step-library definitions (with the same validation VectorStep itself uses), inspect runs and steps, answer operational and quality questions, and trigger runs or submit human feedback. Agents are not authored here — that's the job of the companion `VectorStep-Gateway-MCP`; this server may only read agents, to help author pipelines that reference them.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3 -m venv .venv
|
|
46
|
+
.venv/bin/pip install -e .
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
CI runs this repo's test suite on every push and pull request
|
|
50
|
+
(`.github/workflows/tests.yml`).
|
|
51
|
+
|
|
52
|
+
Then register it with your MCP client, pointing at a running VectorStep instance:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
claude mcp add vectorstep-service \
|
|
56
|
+
--env VECTORSTEP_BASE_URL=http://127.0.0.1:8000 \
|
|
57
|
+
-- /absolute/path/to/VectorStep-Service-MCP/.venv/bin/python -m vectorstep_service_mcp
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Full install, client config (Claude Code, Claude Desktop, MCP Inspector), and tool inventory: [MCP servers](https://vectorstep.io/docs/integrations/mcp/).
|
|
61
|
+
|
|
62
|
+
## Documentation
|
|
63
|
+
|
|
64
|
+
Full docs at [vectorstep.io](https://vectorstep.io/docs/):
|
|
65
|
+
|
|
66
|
+
| Section | Covers |
|
|
67
|
+
|---|---|
|
|
68
|
+
| [MCP servers](https://vectorstep.io/docs/integrations/mcp/) | Install, client config, tool inventory, `explain` tool, write-path design notes for both MCP servers |
|
|
69
|
+
| [Pipelines](https://vectorstep.io/docs/pipelines/schema/) | The pipeline/step schema this server authors against |
|
|
70
|
+
|
|
71
|
+
## The ecosystem
|
|
72
|
+
|
|
73
|
+
| Repo | Role |
|
|
74
|
+
|---|---|
|
|
75
|
+
| **VectorStep** | The orchestration service: webhook intake, pipeline runner, trust gating, UI, analytics |
|
|
76
|
+
| **VectorStep-Gateway** | WebSocket gateway that runs agents: LLM providers, MCP tools, the full agentic loop |
|
|
77
|
+
| **VectorStep-Service-MCP** | MCP server exposing pipeline authoring, run inspection and analytics to Claude Code/Desktop |
|
|
78
|
+
| **VectorStep-Gateway-MCP** | MCP server for authoring and inspecting Gateway agents |
|
|
79
|
+
|
|
80
|
+
## Licence
|
|
81
|
+
|
|
82
|
+
VectorStep Service MCP is proprietary software, free to download and use under the terms in [`LICENSE`](LICENSE). The source is not publicly distributed and this repository is private.
|
|
83
|
+
|
|
84
|
+
Bug reports, questions, and feature requests are welcome at **alex@vectorstep.io**. Code contributions are not accepted — see clause 6 of the licence. For a suspected vulnerability, follow [`SECURITY.md`](SECURITY.md) rather than emailing the address above.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# VectorStep Service MCP
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server that exposes [VectorStep](https://github.com/bantex01/VectorStep) — pipeline authoring, run inspection, and analytics — to MCP clients such as Claude Code and Claude Desktop.
|
|
4
|
+
|
|
5
|
+
## What it is
|
|
6
|
+
|
|
7
|
+
A separate, standalone repository and process with no import-level dependency on VectorStep — the two are coupled only over HTTP, so each can be developed, versioned, and deployed independently.
|
|
8
|
+
|
|
9
|
+
It lets an MCP client create and edit pipelines and step-library definitions (with the same validation VectorStep itself uses), inspect runs and steps, answer operational and quality questions, and trigger runs or submit human feedback. Agents are not authored here — that's the job of the companion `VectorStep-Gateway-MCP`; this server may only read agents, to help author pipelines that reference them.
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python3 -m venv .venv
|
|
15
|
+
.venv/bin/pip install -e .
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
CI runs this repo's test suite on every push and pull request
|
|
19
|
+
(`.github/workflows/tests.yml`).
|
|
20
|
+
|
|
21
|
+
Then register it with your MCP client, pointing at a running VectorStep instance:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
claude mcp add vectorstep-service \
|
|
25
|
+
--env VECTORSTEP_BASE_URL=http://127.0.0.1:8000 \
|
|
26
|
+
-- /absolute/path/to/VectorStep-Service-MCP/.venv/bin/python -m vectorstep_service_mcp
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Full install, client config (Claude Code, Claude Desktop, MCP Inspector), and tool inventory: [MCP servers](https://vectorstep.io/docs/integrations/mcp/).
|
|
30
|
+
|
|
31
|
+
## Documentation
|
|
32
|
+
|
|
33
|
+
Full docs at [vectorstep.io](https://vectorstep.io/docs/):
|
|
34
|
+
|
|
35
|
+
| Section | Covers |
|
|
36
|
+
|---|---|
|
|
37
|
+
| [MCP servers](https://vectorstep.io/docs/integrations/mcp/) | Install, client config, tool inventory, `explain` tool, write-path design notes for both MCP servers |
|
|
38
|
+
| [Pipelines](https://vectorstep.io/docs/pipelines/schema/) | The pipeline/step schema this server authors against |
|
|
39
|
+
|
|
40
|
+
## The ecosystem
|
|
41
|
+
|
|
42
|
+
| Repo | Role |
|
|
43
|
+
|---|---|
|
|
44
|
+
| **VectorStep** | The orchestration service: webhook intake, pipeline runner, trust gating, UI, analytics |
|
|
45
|
+
| **VectorStep-Gateway** | WebSocket gateway that runs agents: LLM providers, MCP tools, the full agentic loop |
|
|
46
|
+
| **VectorStep-Service-MCP** | MCP server exposing pipeline authoring, run inspection and analytics to Claude Code/Desktop |
|
|
47
|
+
| **VectorStep-Gateway-MCP** | MCP server for authoring and inspecting Gateway agents |
|
|
48
|
+
|
|
49
|
+
## Licence
|
|
50
|
+
|
|
51
|
+
VectorStep Service MCP is proprietary software, free to download and use under the terms in [`LICENSE`](LICENSE). The source is not publicly distributed and this repository is private.
|
|
52
|
+
|
|
53
|
+
Bug reports, questions, and feature requests are welcome at **alex@vectorstep.io**. Code contributions are not accepted — see clause 6 of the licence. For a suspected vulnerability, follow [`SECURITY.md`](SECURITY.md) rather than emailing the address above.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "vectorstep-service-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "MCP server exposing VectorStep's authoring, inspection, and analytics surface to MCP clients (Claude Code/Desktop)."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Alex Dalton", email = "alex@vectorstep.io" }]
|
|
10
|
+
keywords = ["mcp", "vectorstep", "ai", "agents", "orchestration", "pipelines"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Intended Audience :: System Administrators",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: Software Development :: Libraries",
|
|
21
|
+
"Topic :: System :: Monitoring",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"mcp==1.28.1",
|
|
25
|
+
"httpx>=0.27",
|
|
26
|
+
"pyyaml>=6.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest>=8.0",
|
|
32
|
+
"pytest-asyncio>=0.24",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://vectorstep.io"
|
|
37
|
+
Documentation = "https://vectorstep.io/docs/integrations/mcp/"
|
|
38
|
+
Changelog = "https://vectorstep.io/docs/about/status-and-support/"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
vectorstep-service-mcp = "vectorstep_service_mcp.__main__:main"
|
|
42
|
+
|
|
43
|
+
[build-system]
|
|
44
|
+
requires = ["setuptools>=77"]
|
|
45
|
+
build-backend = "setuptools.build_meta"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.package-data]
|
|
51
|
+
vectorstep_service_mcp = ["docs/*.md"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
asyncio_mode = "auto"
|
|
55
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Entry point for the VectorStep Service MCP server. Runs over stdio (Claude Code /
|
|
2
|
+
Desktop) — see the README for VECTORSTEP_BASE_URL / VECTORSTEP_WEBHOOK_TOKEN configuration."""
|
|
3
|
+
|
|
4
|
+
from . import tools # noqa: F401 — importing registers every @mcp.tool()
|
|
5
|
+
from .server import mcp
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
mcp.run(transport="stdio")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
main()
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Thin HTTP client for talking to a VectorStep service instance.
|
|
2
|
+
|
|
3
|
+
This is the ONLY coupling to VectorStep (SPEC-vectorstep-service-mcp.md §2.3): no VectorStep
|
|
4
|
+
code is imported anywhere in this package. Configured from VECTORSTEP_BASE_URL /
|
|
5
|
+
VECTORSTEP_WEBHOOK_TOKEN — see the README.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
|
|
12
|
+
from .errors import VectorStepAPIError, error_from_response
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class VectorStepClient:
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
base_url: str | None = None,
|
|
19
|
+
token: str | None = None,
|
|
20
|
+
timeout: float = 30.0,
|
|
21
|
+
transport: httpx.AsyncBaseTransport | None = None,
|
|
22
|
+
):
|
|
23
|
+
self.base_url = (base_url or os.environ.get("VECTORSTEP_BASE_URL") or "http://127.0.0.1:8000").rstrip("/")
|
|
24
|
+
self.token = token if token is not None else os.environ.get("VECTORSTEP_WEBHOOK_TOKEN")
|
|
25
|
+
self.timeout = timeout
|
|
26
|
+
# Injectable for tests (httpx.MockTransport) — None uses the real network.
|
|
27
|
+
self.transport = transport
|
|
28
|
+
|
|
29
|
+
def _headers(self) -> dict:
|
|
30
|
+
return {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
31
|
+
|
|
32
|
+
async def request(self, method: str, path: str, **kwargs) -> dict:
|
|
33
|
+
url = f"{self.base_url}{path}"
|
|
34
|
+
try:
|
|
35
|
+
async with httpx.AsyncClient(timeout=self.timeout, transport=self.transport) as http_client:
|
|
36
|
+
resp = await http_client.request(method, url, headers=self._headers(), **kwargs)
|
|
37
|
+
except httpx.RequestError as exc:
|
|
38
|
+
raise VectorStepAPIError(
|
|
39
|
+
"network", f"Could not reach VectorStep at {self.base_url}: {exc}",
|
|
40
|
+
) from exc
|
|
41
|
+
|
|
42
|
+
if resp.status_code >= 400:
|
|
43
|
+
raise error_from_response(resp)
|
|
44
|
+
|
|
45
|
+
if not resp.content:
|
|
46
|
+
return {}
|
|
47
|
+
return resp.json()
|
|
48
|
+
|
|
49
|
+
async def get(self, path: str, params: dict | None = None) -> dict:
|
|
50
|
+
return await self.request("GET", path, params=params)
|
|
51
|
+
|
|
52
|
+
async def post(self, path: str, json: dict | None = None) -> dict:
|
|
53
|
+
return await self.request("POST", path, json=json)
|
|
54
|
+
|
|
55
|
+
async def put(self, path: str, json: dict | None = None) -> dict:
|
|
56
|
+
return await self.request("PUT", path, json=json)
|
|
57
|
+
|
|
58
|
+
async def delete(self, path: str) -> dict:
|
|
59
|
+
return await self.request("DELETE", path)
|
|
File without changes
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Confidence and the trust vector
|
|
2
|
+
|
|
3
|
+
`get_run` returns several confidence-shaped fields per step. They are **not**
|
|
4
|
+
duplicates of the same number — each is a distinct, independent signal, and
|
|
5
|
+
VectorStep combines them by taking the *weakest* one, not an average. This doc
|
|
6
|
+
maps those fields to what they actually mean, so you don't report
|
|
7
|
+
`primary_confidence` as "VectorStep's confidence in this step" when it's really
|
|
8
|
+
just the agent's own unverified self-report.
|
|
9
|
+
|
|
10
|
+
## The four signals (+ calibration)
|
|
11
|
+
|
|
12
|
+
| Signal | Field on a step | What it actually measures |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| **S** — self-report | `primary_confidence` | What the agent said about its own answer. The **least** trustworthy number here — it's the agent grading its own work, no outside check. |
|
|
15
|
+
| **V** — verifier | `verifier_confidence` (see also `verifier_mode`, `verifier_agent`, `verifier_model`) | A second agent's opinion, if a `verifier:` block was configured. `verifier_mode: "critic"` saw the primary's answer and reviewed it (its errors correlate with the primary's own — weaker signal); `"independent"` redid the task blind (uncorrelated — stronger signal). A verifier can only ever *lower* the combined score, never raise it. |
|
|
16
|
+
| **G** — grounding | `grounding_score` (0–1, or `null` if not computed) | Of the primary's specific factual claims, what fraction are actually backed by a real tool-call result in its own trace? This is about evidence, not correctness of reasoning. `null` means grounding wasn't configured for this step at all — that's different from a low score. |
|
|
17
|
+
| **D** — deterministic check | `deterministic_passed` (bool, or `null` if none declared) | A hard, computer-verified fact (a shell command, webhook call, or human approval) — no model involved. If declared and failed, it forces trust to **zero**, no matter how confident everything else was. `null` means no checks were declared, not that one passed. |
|
|
18
|
+
| **Calibration** | inside `trust_report.calibration` | Whether this exact agent/model's *real historical accuracy* at this confidence level (from past human-graded runs) should replace the raw self-report. The one signal that can move the score **up** as well as down. |
|
|
19
|
+
|
|
20
|
+
To see the full calibration picture for a step — every confidence bin, per
|
|
21
|
+
(agent, model, provider), not just the one bin a single run happened to land
|
|
22
|
+
in — call `get_step_calibration(step_name)` directly rather than piecing it
|
|
23
|
+
together by sampling `get_run` across many runs.
|
|
24
|
+
|
|
25
|
+
### Calibration buckets are versioned
|
|
26
|
+
|
|
27
|
+
A calibration bucket is keyed by `(step_name, agent, model, provider,
|
|
28
|
+
prompt_hash, agent_version)`, not just the first four. Editing a step's
|
|
29
|
+
prompt template, or editing a Gateway agent's `agent.yaml`/`soul.md`, starts
|
|
30
|
+
a **new** bucket — outcomes from the old prompt/agent config never count as
|
|
31
|
+
evidence for the new one, and vice versa. This is deliberate: a bucket
|
|
32
|
+
mixing two different prompts isn't a bigger sample, it's a wrong one.
|
|
33
|
+
|
|
34
|
+
Consequences worth knowing before reporting on calibration data:
|
|
35
|
+
|
|
36
|
+
- **A small bucket isn't necessarily a new or unused step.** It may just be
|
|
37
|
+
mid-history under a recently-edited prompt or agent — call
|
|
38
|
+
`get_step_versions(step_name)` / `get_agent_versions(agent_name)` to see
|
|
39
|
+
the rest of that history before concluding a step "has no track record."
|
|
40
|
+
- **Reverting a prompt restores its history for free.** Because buckets are
|
|
41
|
+
keyed by content hash, going back to an exact previous template rejoins
|
|
42
|
+
that version's original bucket and all its labelled results — nothing is
|
|
43
|
+
lost.
|
|
44
|
+
- **`trust_report.calibration.bucket_reset`**, when present, tells you
|
|
45
|
+
explicitly that THIS run's bucket just reset and why:
|
|
46
|
+
`reason` is `"prompt_changed"`, `"agent_changed"`, or `"both_changed"`;
|
|
47
|
+
`previous_validated_n` is how many marked results the prior version had.
|
|
48
|
+
Treat this as the explanation for a step that suddenly stopped being
|
|
49
|
+
calibrated, not as a sign anything is broken.
|
|
50
|
+
- **`agent_version` changes originate in the Gateway repo, not VectorStep's own
|
|
51
|
+
YAML.** A pipeline/step YAML file can look completely unchanged while an
|
|
52
|
+
agent's `soul.md` was edited on the Gateway — if calibration resets for a
|
|
53
|
+
step you didn't touch, check `get_agent_versions` for the agent it uses
|
|
54
|
+
before assuming something is wrong on the VectorStep side.
|
|
55
|
+
|
|
56
|
+
## `effective_confidence` vs. `trust_report.combined_trust`
|
|
57
|
+
|
|
58
|
+
`effective_confidence` on a step is the self-report *after* the verifier is
|
|
59
|
+
applied (S adjusted by V) — it predates grounding/deterministic/calibration
|
|
60
|
+
in the pipeline's history and is kept for backward compatibility.
|
|
61
|
+
|
|
62
|
+
`trust_report.combined_trust` (inside the JSON blob in `trust_report`) is the
|
|
63
|
+
**actual final number the step's gate compared against its
|
|
64
|
+
`confidence_threshold`** — after verifier, calibration, grounding, and
|
|
65
|
+
deterministic checks have all been applied in that order. **When you want
|
|
66
|
+
"how much did VectorStep actually trust this step's result," use
|
|
67
|
+
`trust_report.combined_trust`, not `effective_confidence`.**
|
|
68
|
+
|
|
69
|
+
## Reading `trust_report`
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"signals": {
|
|
74
|
+
"S": 0.95, "S_after_V": 0.95,
|
|
75
|
+
"V": 0.85, "V_mode": "critic", "V_combination_strategy": "veto", "V_veto_floor": 0.6,
|
|
76
|
+
"G": 0.50, "C": null, "D": true
|
|
77
|
+
},
|
|
78
|
+
"combined_trust": 0.50,
|
|
79
|
+
"grounding": { "...": "per-claim detail" },
|
|
80
|
+
"deterministic_checks": [{"name": "...", "passed": true, "...": "..."}],
|
|
81
|
+
"calibration": { "...": "bin/bucket detail, or null if not enforced" },
|
|
82
|
+
"gate": {
|
|
83
|
+
"policy": "trust_vector",
|
|
84
|
+
"confidence_threshold": 0.75,
|
|
85
|
+
"on_low_confidence": "escalate"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Order the signals are applied, each stage only able to lower the number
|
|
91
|
+
(calibration is the sole exception):
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
S → (verifier) → S_after_V → (calibration, if enforced+validated) →
|
|
95
|
+
→ (grounding, if enforced — a ceiling) → (deterministic checks — force to
|
|
96
|
+
zero on any failure) → combined_trust → compared to confidence_threshold
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`trust_report.gate.policy` tells you whether any of this mattered at all:
|
|
100
|
+
`"legacy_confidence"` means the step has none of verifier/grounding/
|
|
101
|
+
deterministic/calibration configured — it's a plain self-report-vs-threshold
|
|
102
|
+
gate, and every signal above `S` will be `null`. `"trust_vector"` means at
|
|
103
|
+
least one of these mechanisms is active.
|
|
104
|
+
|
|
105
|
+
## A field being `null` is information, not a gap
|
|
106
|
+
|
|
107
|
+
`verifier_confidence: null` → no verifier was configured for this step, not
|
|
108
|
+
"the verifier failed." `grounding_score: null` → grounding wasn't computed,
|
|
109
|
+
not "zero evidence." `deterministic_passed: null` → no hard checks were
|
|
110
|
+
declared, not "unknown pass/fail." Don't treat `null` as a bad result — it
|
|
111
|
+
means the mechanism was never turned on for this step.
|
|
112
|
+
|
|
113
|
+
## What "escalated because of low confidence" actually means
|
|
114
|
+
|
|
115
|
+
If `trust_report.combined_trust` fell below `confidence_threshold`, the step
|
|
116
|
+
took whatever action `gate.on_low_confidence` says (`escalate` / `abort` /
|
|
117
|
+
`proceed`). A step escalating doesn't mean anything went wrong with the
|
|
118
|
+
agent's answer — it means the *evidence for trusting that answer* didn't
|
|
119
|
+
clear the bar the pipeline author set. See `statuses-and-accuracy` for why
|
|
120
|
+
that's often the *correct*, intended outcome rather than a failure.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Promotion readiness — owner-defined criteria, not a hardcoded bar
|
|
2
|
+
|
|
3
|
+
`get_promotion_readiness(name)` reports whether a `stage: testing` pipeline's
|
|
4
|
+
steps already have the evidence their OWNER requires before flipping
|
|
5
|
+
`stage:` to `production`. `preview_promotion_readiness(name, readiness,
|
|
6
|
+
apply_to)` tests a candidate `readiness:` config against the same evidence
|
|
7
|
+
without writing anything. Both are **strictly advisory** — neither call
|
|
8
|
+
blocks, gates, or changes VectorStep's behaviour in any way. The `stage:` edit
|
|
9
|
+
itself stays a one-line YAML change a human makes and commits, exactly as
|
|
10
|
+
before this feature existed.
|
|
11
|
+
|
|
12
|
+
## Four independent tiers
|
|
13
|
+
|
|
14
|
+
A pipeline (or a step within it) can configure any subset of four tiers in
|
|
15
|
+
its `readiness:` YAML block:
|
|
16
|
+
|
|
17
|
+
- **operational** — pure run-completion counting: N runs that ended in an
|
|
18
|
+
acceptable status. The cheapest bar, and the only one a non-LLM step
|
|
19
|
+
(`webhook`/`notify`/`human`/`pipeline` executor) can ever satisfy, since
|
|
20
|
+
those never write `effective_confidence`. Can only ever report `pass` or
|
|
21
|
+
`insufficient_data` — twenty completed runs plus five failed ones still
|
|
22
|
+
satisfies "twenty completed runs," so this tier never reports `fail`.
|
|
23
|
+
- **confidence** — mean self-reported `effective_confidence` over qualifying
|
|
24
|
+
runs. A weak signal alone (a model can be confidently wrong), useful as an
|
|
25
|
+
early checkpoint before anyone has marked anything.
|
|
26
|
+
- **accuracy** — judged accuracy (correct=1.0, partial=0.5, incorrect=0.0)
|
|
27
|
+
over human/deterministic/run-level labels, using the same label-precedence
|
|
28
|
+
chain as calibration: a human mark beats a failed deterministic check beats
|
|
29
|
+
an inherited run-level rating.
|
|
30
|
+
- **calibration** — the strongest bar: not just "the output is good" but "the
|
|
31
|
+
step's confidence NUMBER can be trusted," using the same bucket machinery
|
|
32
|
+
as `get_step_calibration`.
|
|
33
|
+
|
|
34
|
+
Every CONFIGURED tier must show `pass` for a step to read `ready`. An
|
|
35
|
+
unconfigured tier is not a failure — it's simply not asked. A pipeline can
|
|
36
|
+
require `operational` + `accuracy` without touching `calibration`, because
|
|
37
|
+
those answer genuinely different questions.
|
|
38
|
+
|
|
39
|
+
## Verdict vocabulary
|
|
40
|
+
|
|
41
|
+
Per tier: `not_configured | insufficient_data | pass | fail`.
|
|
42
|
+
|
|
43
|
+
**`insufficient_data` means "the bar can still be met by accumulating more
|
|
44
|
+
evidence." `fail` means "observed evidence actively contradicts the bar."**
|
|
45
|
+
These are not interchangeable when summarising a step's readiness for a
|
|
46
|
+
user — a step reading `insufficient_data` just needs more runs/marks; a step
|
|
47
|
+
reading `fail` has a real problem right now.
|
|
48
|
+
|
|
49
|
+
Step-level and pipeline-level roll-ups use the same precedence:
|
|
50
|
+
`fail > insufficient_data > pass > not_configured`, surfacing as
|
|
51
|
+
`not_ready | building | no_data | ready | not_configured`.
|
|
52
|
+
|
|
53
|
+
## THE trap: n_min is per confidence band, not a total
|
|
54
|
+
|
|
55
|
+
`calibration.n_min` (default 20) is the number of marked results needed **at
|
|
56
|
+
the same predicted-confidence band**, not a total across all bands. A step
|
|
57
|
+
with 100 marked results spread evenly across 10 confidence bands has only 10
|
|
58
|
+
in each band, and will **not** validate at `n_min: 20` even though 100
|
|
59
|
+
sounds like plenty. Always check the fullest band's own count
|
|
60
|
+
(`bins[i].n` on the relevant combo), never `total_n`, before concluding a
|
|
61
|
+
step is close to validating calibration.
|
|
62
|
+
|
|
63
|
+
## `require_current_config` and `require_own_evidence`
|
|
64
|
+
|
|
65
|
+
Most tiers default `require_current_config: true` (except `operational`,
|
|
66
|
+
which defaults `false`) — evidence is filtered to runs matching the
|
|
67
|
+
pipeline's CURRENT prompt template and the step's most recently observed
|
|
68
|
+
`agent_version`. A step whose prompt was just edited can drop straight to
|
|
69
|
+
`insufficient_data` even with a long track record; `current_config` on each
|
|
70
|
+
step's result reports `prompt_hash_matches_history` and an explicit `notes`
|
|
71
|
+
entry naming how many earlier marked results were excluded, so this is never
|
|
72
|
+
a silent zero.
|
|
73
|
+
|
|
74
|
+
`calibration.require_own_evidence` (default `false`) lets a shared library
|
|
75
|
+
step's PRODUCTION track record from a *different* pipeline count, when the
|
|
76
|
+
agent/model/prompt/agent-version all match exactly — `production_pipelines`
|
|
77
|
+
on the calibration combo names which pipeline(s) contributed that evidence.
|
|
78
|
+
Set it `true` to restrict a step to only this pipeline's own runs.
|
|
79
|
+
|
|
80
|
+
## Reading a result without asserted criteria
|
|
81
|
+
|
|
82
|
+
A pipeline with no `readiness:` block anywhere returns
|
|
83
|
+
`criteria_source: "none"` and asserts no verdict — but each step's
|
|
84
|
+
`observed_combos` still carries calibration bins evaluated at
|
|
85
|
+
`bin_width`/`n_min` (the tool's own parameters, default 0.1/20), so real
|
|
86
|
+
signal never disappears behind "no criteria configured." A step's own
|
|
87
|
+
configured calibration tier always uses its own values instead of these
|
|
88
|
+
defaults.
|
|
89
|
+
|
|
90
|
+
## Preferring the ready-made narrative
|
|
91
|
+
|
|
92
|
+
Each step's result includes a `narrative`: a numbers-first, plain-English
|
|
93
|
+
walkthrough of every configured tier's verdict. Prefer quoting it directly
|
|
94
|
+
over re-deriving your own summary from the raw tier numbers — it already
|
|
95
|
+
accounts for the per-band n_min trap, provenance breakdowns, and the
|
|
96
|
+
`acceptable_statuses` "adding a status makes the bar LAXER, not stricter"
|
|
97
|
+
gotcha.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Prompt and agent versioning
|
|
2
|
+
|
|
3
|
+
Every calibration bucket VectorStep computes is scoped to the exact configuration
|
|
4
|
+
that produced it — not just `(step_name, agent, model, provider)`, but also
|
|
5
|
+
the step's `prompt_hash` and the Gateway agent's `agent_version`. This doc
|
|
6
|
+
explains why, and how to read the tools that expose it
|
|
7
|
+
(`get_step_versions`, `get_agent_versions`) without misreading a healthy
|
|
8
|
+
reset as a problem.
|
|
9
|
+
|
|
10
|
+
## The bug this exists to fix
|
|
11
|
+
|
|
12
|
+
Before this existed, editing a step's prompt template — or editing a
|
|
13
|
+
Gateway agent's `soul.md`/`agent.yaml` — silently kept counting outcomes
|
|
14
|
+
from the OLD configuration as evidence for the NEW one. For a step with
|
|
15
|
+
`calibration: {enforce: true}`, that meant the enforcement gate was making
|
|
16
|
+
real control decisions using a measured accuracy figure that described a
|
|
17
|
+
configuration that no longer existed. Nothing in the data indicated this
|
|
18
|
+
was happening — it was invisible.
|
|
19
|
+
|
|
20
|
+
Now, `prompt_hash` (a content hash of the step's prompt template) and
|
|
21
|
+
`agent_version` (a content hash of the agent's full config, computed by the
|
|
22
|
+
Gateway) are part of every calibration bucket's key. An edit to either one
|
|
23
|
+
starts a fresh bucket. Old labelled results stop counting toward the new
|
|
24
|
+
configuration.
|
|
25
|
+
|
|
26
|
+
## A small bucket is not the same as a bad one
|
|
27
|
+
|
|
28
|
+
The bucket key growing from 4 components to 6 means buckets are smaller and
|
|
29
|
+
take longer to reach the labelled-sample minimum (`n_min`) than before this
|
|
30
|
+
existed. That is the honest cost of measuring the right thing — a bucket
|
|
31
|
+
that blends two different prompts is not a bigger sample, it's a wrong one.
|
|
32
|
+
|
|
33
|
+
Practically: if `get_step_calibration` shows a step with very few labelled
|
|
34
|
+
samples even though you know it's been running for months, don't conclude
|
|
35
|
+
it's under-used or unlabelled. Call `get_step_versions(step_name)` — it's
|
|
36
|
+
very likely mid-history under a prompt version that was edited recently,
|
|
37
|
+
and the rest of its track record is sitting under a different `prompt_hash`
|
|
38
|
+
in that same response (or under the synthetic legacy entry described next,
|
|
39
|
+
if the step predates this feature entirely).
|
|
40
|
+
|
|
41
|
+
## The `prompt_hash: null` / `agent_version: null` legacy entry
|
|
42
|
+
|
|
43
|
+
`get_step_versions`/`get_agent_versions` can each return one entry whose
|
|
44
|
+
`prompt_hash`/`agent_version` is `null`. This is NOT an error and NOT a step
|
|
45
|
+
with no history — it represents every run recorded **before** prompt/agent
|
|
46
|
+
versioning existed, or before an operator ran the backfill script
|
|
47
|
+
(`backfill_prompt_versions.py`) for that step. `NULL` is a real, distinct
|
|
48
|
+
bucket in `get_step_calibration` too (never a wildcard — a `NULL` row never
|
|
49
|
+
pools with a real-hash row), so this entry's `runs_total`/`labelled_n` are
|
|
50
|
+
just as real as any other version's.
|
|
51
|
+
|
|
52
|
+
What's different about it: `template` (or `soul_md`/`agent_yaml`) is always
|
|
53
|
+
`null` for this entry — no text was ever captured for pre-versioning runs,
|
|
54
|
+
so there's nothing to show. `diff_from_previous` is `null` for it, and also
|
|
55
|
+
`null` for whichever real version comes right after it chronologically
|
|
56
|
+
(nothing to diff against a version with no text). Treat it exactly like a
|
|
57
|
+
`note`d agent snapshot: an honest gap, not evidence anything is broken.
|
|
58
|
+
Running the backfill script resolves it into a real, named version (on the
|
|
59
|
+
operator's assertion that the current on-disk prompt/agent config matches
|
|
60
|
+
what those historical runs actually used) — but until that happens, expect
|
|
61
|
+
to see it on nearly every step/agent that predates this feature.
|
|
62
|
+
|
|
63
|
+
## Reverting a prompt restores its history — for free
|
|
64
|
+
|
|
65
|
+
The prompt-version registry is content-addressed: the hash IS the primary
|
|
66
|
+
key. If an operator edits a prompt, doesn't like the result, and reverts it
|
|
67
|
+
back to the exact original text, that revert reproduces the exact same
|
|
68
|
+
hash as before — and automatically rejoins that version's original
|
|
69
|
+
calibration history. No special-casing, no data loss. This is intentional,
|
|
70
|
+
not a quirk to route around.
|
|
71
|
+
|
|
72
|
+
The corollary: a *reformatting* of a prompt (different whitespace,
|
|
73
|
+
reindentation, an added blank line) genuinely produces a different hash and
|
|
74
|
+
a fresh bucket — normalisation only strips trailing whitespace per line and
|
|
75
|
+
leading/trailing blank lines, nothing else. Blank-line structure and
|
|
76
|
+
indentation can genuinely affect model behaviour, so treating a
|
|
77
|
+
reformatted prompt as unchanged would be the wrong call more often than
|
|
78
|
+
the current conservative default.
|
|
79
|
+
|
|
80
|
+
## `agent_version` changes happen in a different repo
|
|
81
|
+
|
|
82
|
+
`prompt_hash` is something VectorStep computes itself, from a step's
|
|
83
|
+
`prompt_template` — the text is always right there in `get_step_versions`'
|
|
84
|
+
response. `agent_version` is different: it's a hash the **Gateway**
|
|
85
|
+
computes over an agent's entire config, including `soul.md`, and VectorStep
|
|
86
|
+
cannot recompute it or predict when it will change. A pipeline/step YAML
|
|
87
|
+
file can be completely untouched while an agent's `soul.md` is edited on
|
|
88
|
+
the Gateway side — and that alone is enough to reset calibration for every
|
|
89
|
+
step using that agent.
|
|
90
|
+
|
|
91
|
+
If a step's calibration resets and you didn't edit anything in VectorStep:
|
|
92
|
+
1. Check `trust_report.calibration.bucket_reset.reason` on a recent run of
|
|
93
|
+
that step — `"agent_changed"` or `"both_changed"` points at the Gateway,
|
|
94
|
+
not the step's own prompt.
|
|
95
|
+
2. Call `get_agent_versions(agent_name)` (bare name, no `gateway:` prefix)
|
|
96
|
+
to see the agent's version history and what changed.
|
|
97
|
+
3. A version's `note` field (instead of recovered `soul_md`/`agent_yaml`
|
|
98
|
+
text) means VectorStep couldn't confirm that snapshot at the time — the
|
|
99
|
+
Gateway was unreachable, or the agent changed again before VectorStep could
|
|
100
|
+
ask. That's an honest gap in VectorStep's records, not evidence the agent
|
|
101
|
+
itself has no configuration.
|
|
102
|
+
|
|
103
|
+
## Quick reference
|
|
104
|
+
|
|
105
|
+
| Question | Tool |
|
|
106
|
+
|---|---|
|
|
107
|
+
| Is this step's confidence trustworthy right now? | `get_step_calibration(step_name)` |
|
|
108
|
+
| Did a specific prompt edit actually help? | `get_step_versions(step_name)` |
|
|
109
|
+
| What changed in this agent, and which steps did it affect? | `get_agent_versions(agent_name)` |
|
|
110
|
+
| Why did this run's bucket reset? | `get_run(run_id)` → `trust_report.calibration.bucket_reset` |
|