内容
<p align="center"><img src="docs/assets/cover.png" alt="kassi: divines disaster, crafts the cure" width="820" /></p>
# kassi
> 预见灾难,打造解决方案。
<p align="center">
<img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="License: Apache-2.0" />
<img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+" />
<img src="https://img.shields.io/badge/MCP-k6%20%2B%20Splunk-8A2BE2" alt="MCP: k6 + Splunk" />
</p>
**kassi 是一款 AI 代理,能够对代码变更进行负载测试,在 Splunk 中查找回归问题,并编写修复方案,然后再将其部署到生产环境。** 将其指向 git diff 或纯语言意图。它驱动实际的 [k6](https://github.com/grafana/mcp-k6) 负载测试针对受影响的端点,与 Splunk 服务器端遥测数据相关联,确定根本原因,并提供一个经过验证的修复方案。对于需要尽早发现负载诱导回归的工程和 SRE 团队。
kassi 作为一个经过审计的 [Burr](https://github.com/apache/burr) 状态机运行在 MCP 上,由 [Theodosia](https://msradam.github.io/theodosia/) 提供服务:驱动代理看到一个工具,非法步骤被拒绝,每个步骤和拒绝都被记录在哈希链账本上。命名为 Kassandra,她预见了他人不会相信的事情;工作流被设计为塔罗牌抽签,每个阶段对应一张大阿尔卡纳牌(`kassi arcana` 布局)。
为 Splunk Agentic Ops 黑客马拉松(可观测性赛道)而构建。参见 [`DEVPOST.md`](DEVPOST.md) 了解相关介绍,[`architecture_diagram.md`](architecture_diagram.md) 了解设计。
<p align="center"><img src="docs/assets/kassi-run.gif" alt="kassi walking its state machine from The Fool to Judgement, correlating k6 load with Splunk telemetry, and proposing a fix" width="860" /></p>
上述演示是一个记录的端到端运行:它打印状态机,然后驱动整个工作流(脚本 + 配置模型的分析,k6 文档 + 运行,Splunk 预飞行检查和关联)针对一个 live Splunk。
### 截图
| | |
| --- | --- |
|  |  |
| **`kassi render`**: 完整状态机,仅限合法边 | **`kassi arcana`**: 每阶段一张牌 |
|  |  |
| **`kassi doctor --runtime`**: 图 + 治理检查 | **一次完整运行**:k6 + Splunk 相关联,每个工具调用都记录 |
## 功能
- **差异或意图驱动。** 从 git diff 读取更改的端点,或根据纯语言意图评估 OpenAPI 规范。
- **真实负载。** 生成并运行实际的 k6 测试,通过 Grafana k6 MCP 服务器,在确定性脚手架之上,以便运行不会因模型不足而失败。
- **Splunk 服务器端真相。** 通过官方 Splunk MCP 服务器,与窗口 SPL 相关联,然后运行 Splunk AI 工具包(`StateSpaceForecast` + `anomalydetection`)以统计方式定位饱和度起始点。捕获延迟降级,产生零错误,将静默过去任何阈值警报。
- **根本原因和修复。** 编写引用分析并验证修复方案,适用于干净应用,通过独立审计模型筛选后,判决被密封。
- **通过构造审计。** 受监管的状态机拒绝非法步骤;每个步骤和拒绝都被记录在哈希链账本中,`kassi verify` 检查。
- **无人工干预守护。** `kassi watch` 在提交更改端点时运行整个工作流,在提交时捕获回归。
- **与模型无关。** 相同的循环(驱动、编写、审计)在本地开放 8B、安全隔离或前沿模型上运行,不变。
- **自我可观测。** 将其自己的状态机行走记录发布到 Splunk,因此代理在其观察的系统中可见。
- **衡量。** 在实时基准测试中 0% 错误警报;在 RCAEval RE3 上 100% 排名前 3 的根因([详情](#benchmark))。
## 安装
```bash
uv sync
```
kassi 通过 [Grafana k6 MCP 服务器](https://github.com/grafana/mcp-k6) 驱动 k6,并通过 [官方 Splunk MCP 服务器](https://splunkbase.splunk.com/app/7931) 读取 Splunk。完整设置:[`docs/SPLUNK_SETUP.md`](docs/SPLUNK_SETUP.md)。
```bash
brew install k6 && kassi warm-k6 # 安装 k6 2.0+;首次使用时预热扩展缓存
# 替代方案:独立二进制(KASSI_K6_CMD=mcp-k6)或 Docker(KASSI_K6_DOCKER=1)
```
Splunk 步骤是可选的:无需 `KASSI_SPLUNK_MCP_ENDPOINT` + `KASSI_SPLUNK_TOKEN`,kassi 跳过关联,仅运行 k6。模型后端:参见 [配置](#configuration)。
## 快速开始
首次成功的最快方法是不需要 Splunk、k6 或模型的。它针对伪造对象运行整个状态机:
```bash
uv run pytest # 完整工作流针对 Theodosia 的 FakeUpstream 和伪造模型
kassi render # 打印状态机
kassi arcana # 塔罗牌展开,一张牌对应一个阶段
```
对于一个完整的实时运行,针对一个捆绑的演示应用程序(启动应用程序,驱动实际 k6,查询实时 Splunk,编写接地分析):
```bash
uv run python scripts/verify_scenario.py petclinic # 或 storefront | feed | gateway | orders
```
## 用法
检查和提供工作流:
```bash
kassi doctor --runtime # 验证图和运行时工具形状
kassi render # 打印状态机
kassi serve # 作为 stdio 上的 MCP 服务器安装(两个上游均已连接)
```
在本地驱动,无云代理。`kassi pilot` 允许本地开放模型驱动有限状态机一步一步:它读取可达动作并为每个阶段调用 `step`,在阶段内完成工作(`screen` 阶段移交给独立审计员)。驱动程序、编写器和审计员都是本地模型:
```bash
kassi pilot --intent "load test the pet listing endpoint" \
--repo-path examples/petstore --target-base-url http://localhost:8000 --splunk-index web
# 或 diff 模式:kassi pilot --repo-path /path/to/repo --ref HEAD~1 --splunk-index web
```
在后台运行,触发于差异检测。`kassi watch` 轮询仓库的 git HEAD,当新提交更改 HTTP 端点时,以差异模式驱动整个工作流,然后打印判决和提议的修复方案,并将运行发布到 Splunk:
```bash
kassi watch --repo-path /path/to/repo --target-base-url http://localhost:8000 --splunk-index web
# 一次性用于 post-commit 钩子或 CI:kassi watch --once --repo-path . --target-base-url ...
```
或从 Claude Code(或任何 MCP 客户端)驱动它,通过注册服务器:
```bash
claude mcp add --scope=user --transport=stdio kassi -- kassi serve
```
然后要求代理运行工作流,使用 `step` 工具,例如:
“使用 kassi step 工具。对 http://localhost:8000 加载测试宠物列表端点;规范位于 examples/petstore 下;与 Splunk 索引 web 相关联。”
`select_mode` 的输入参数:
- 差异模式:`{"repo_path": "/path/to/repo", "ref": "HEAD~1", "target_base_url": "http://localhost:8000", "splunk_index": "web"}`
- 意图模式:`{"repo_path": "/path/with/openapi.json", "intent": "load test the checkout endpoint", "target_base_url": "...", "splunk_index": "web"}`
审查记录的运行:
```bash
kassi sessions ls
kassi sessions show <app-id>
kassi logs <app-id> --refusals
kassi verify <app-id> # 确认账本未被篡改
```
## 配置
| 变量 | 默认值 | 用途 |
| --- | --- | --- |
| `KASSI_LLM` | `ollama` | 模型后端:`ollama`(本地),`claude_agent`(通过 Claude Code 会话,无 API 密钥),或 `anthropic`(Claude Messages API) |
| `KASSI_MODEL` | `granite4.1:8b` / `sonnet` | 模型标签:Ollama 标签,或 Claude 后端的 Claude 模型别名/ID |
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama 端点(指向运行本地模型的 host,例如 LAN 盒) |
| `ANTHROPIC_API_KEY` | 未设置 | Claude API 密钥(仅限 `KASSI_LLM=anthropic`;`claude_agent` 使用登录的 Claude Code 会话) |
| `KASSI_K6_CMD` | `k6 x mcp` | k6 MCP 服务器命令行(设置为 `mcp-k6` 以使用独立二进制) |
| `KASSI_K6_DOCKER` | 未设置 | 如果设置,通过 Docker 运行 k6 MCP 服务器 |
| `KASSI_K6_IMAGE` | `grafana/mcp-k6:latest` | Docker 镜像(当设置 `KASSI_K6_DOCKER` 时) |
| `KASSI_SPLUNK_MCP_ENDPOINT` | 未设置 | Splunk MCP 服务器的 streamable-HTTP 端点(例如 `https://localhost:8089/services/mcp`) |
| `KASSI_SPLUNK_TOKEN` | 未设置 | 加密的 MCP 令牌(作为 `Authorization: Bearer` 发送) |
| `KASSI_SPLUNK_MCP_CMD` | `npx` | stdio 桥接命令(运行 `mcp-remote`) |
| `KASSI_SPLUNK_INSECURE` | 未设置 | 跳过桥接中的 TLS 验证(仅限本地自签名 Splunk) |
| `THEODOSIA_HOME` | `~/.kassi` | 账本/会话存储 |
`kassi serve` 如果存在,从项目根目录加载这些 `.env`;实际环境变量优先。 将 `.env` 存放在 git 之外,因为令牌是凭证。
在 Docker 中运行 k6 服务器时,主机上的目标可以通过 `http://host.docker.internal:<port>` 从容器内部访问。
## 工作原理
```mermaid
stateDiagram-v2
[*] --> select_mode
select_mode --> read_diff: 差异模式
select_mode --> parse_intent: 意图模式
read_diff --> extract_endpoints
read_diff --> analyze: 失败
extract_endpoints --> doc_lookup
parse_intent --> doc_lookup
parse_intent --> analyze: 失败
doc_lookup --> scaffold
scaffold --> generate_script
scaffold --> analyze: 没有端点
generate_script --> validate_script
validate_script --> fix_script: 需要修复
fix_script --> validate_script
validate_script --> run_test: 有效/脚手架
validate_script --> analyze: 放弃
run_test --> splunk_preflight: 启用 Splunk
run_test --> analyze: 仅限 k6 / 失败
splunk_preflight --> correlate
correlate --> detect_anomalies
detect_anomalies --> analyze
analyze --> screen
screen --> report
report --> [*]
```
由 `kassi render --mermaid` 生成
- `doc_lookup` — 咨询 k6 MCP 文档工具并记录基于版本的引用。非阻塞;如果文档不可用,则继续生成。
- `scaffold` — 从 OpenAPI 规范(每个端点的请求带有示例正文,内置基本 URL,负载选项)组成确定性、自包含的 k6 基线。该脚手架是已知的良好基准。
- `generate_script` — 模型在脚手架之上编写最终脚本,引导 k6 自己的 `generate_script` MCP 提示和 `best_practices` 资源。
- `validate_script` — 在 `k6.validate_script` 处验证脚本。失败路由到 `fix_script`,修复脚本并循环返回。受 `MAX_FIX_ATTEMPTS` 限制;干净地放弃以便未验证的脚本永远不会到达 `run_test`。
- `run_test` — 通过 `k6.run_script` 执行验证的脚本并记录时钟测试窗口。
- `splunk_preflight` — 检查目标索引是否存在,捕获事件计数、源类型和 Splunk 版本关联前。尽早捕获错误索引失败。非阻塞。
- `correlate` — 四个窗口 SPL 查询(汇总、时间线、按端点、主要错误)合成客户端和服务器的发现:哪些路由降级以及为什么。回答 k6 总结无法显示的内容。
- `detect_anomalies` — AI 工具包的 `StateSpaceForecast` 预测延迟带(回退到 `predict` 如果缺少附加组件)和 `anomalydetection` 标记异常桶。饱和度起始点由 Splunk 的 ML 而不是固定阈值查找。非阻塞。
- `analyze` — 编写模型生成有根有据的分析(根本原因、证据和建议)和差异模式下的修复方案。两者都回退到确定性文本,如果没有模型可用。
- `screen` — 独立审计员模型检查分析中的每个声明与引用的遥测。通行/失败被密封到报告。非阻塞。
- `report` — 汇总客户端和服务器的判决,将其密封到账本,并通过 HEC 将运行和代理的状态机行走发布到 Splunk。
## 大阿尔卡纳
每个阶段是一张牌。运行 `kassi arcana` 获取完整的展开。
| 卡片 | 阶段 | 征兆 |
| --- | --- | --- |
| The Fool (0) | `select_mode` | 查询者开始:差异或意图 |
| 高 priestess (II) | `read_diff` | 从差异中读取隐藏的知识 |
| The Emperor (IV) | `extract_endpoints` | 秩序来自变化:命名路由 |
| Empress (III) | `parse_intent` | 直觉将意图转换为端点 |
| Hierophant (V) | `doc_lookup` | 咨询教义:k6 文档接地仪式 |
| The Chariot (VII) | `scaffold` | 车辆从规范组装:可运行的脚手架形成 |
| The Magician (I) | `generate_script` | 上面下面一样:代理在脚手架上编写脚本 |
| Justice (XI) | `validate_script` | 脚本被称重;不合格的被拒绝 |
| Temperance (XIV) | `fix_script` | 有缺陷的草稿被调和直到保持不变 |
| The Tower (XVI) | `run_test` | 负载打击结构;揭示了什么被破坏 |
| The Hermit (IX) | `splunk_preflight` | 指数前的一盏灯 |
| The Lovers (VI) | `correlate` | 客户端和服务器在一个窗口内连接 |
| The Star (XVII) | `detect_anomalies` | Splunk 自己的预测被铸造;负载突破带的位置被揭示 |
| The Sun (XIX) | `analyze` | 解释被清楚地说明:原因、证据和治疗方案被揭露 |
| The Hanged Man (XII) | `screen` | 从另一个角度看待:解释被验证或不验证 |
| Judgement (XX) | `report` | 判决被宣布并密封到账本 |
| The World (XXI) | 账本 | 循环结束:一个不可篡改的、基于哈希链的记录 |
| The Devil (XV) | 拒绝 | 你被束缚:只允许合法的行动 |
## 案例研究
实时 Splunk Enterprise 10.4.0 经过认证,使用官方 Splunk MCP 服务器(Splunkbase 7931,v1.2.0),在运行时调用。`scripts/verify_petclinic.py` 驱动整个 FSM,差异模式下没有任何罐装内容。临时 git 仓库包含一个健康的 petclinic 基线和第二个提交,该提交添加了 `POST /api/visits`,因此 kassi 从差异中选取更改的端点,运行 k6 通过 k6 MCP 服务器进行实际负载测试,并从 Splunk 读取服务器端回归信息,通过四个 `correlate` 查询。 它还运行 AI 工具包的 `StateSpaceForecast`(以 `predict` 作为备用)和 `anomalydetection` 在相同的窗口内,在 `detect_anomalies` 处运行,所有这些都在官方 `splunk_run_query` 工具上。
```console
$ KASSI_LLM=claude_agent uv run python scripts/verify_petclinic.py
目标应用: petclinic(有缺陷的 POST /api/visits)在 http://127.0.0.1:8400
差异模式: HEAD~1..HEAD 添加 POST /api/visits # kassi 恰好测试了更改的端点
... extract_endpoints_ok count=1 # 从差异中读取一个新路由
... validation failed(尝试 0): Unexpected token ILLEGAL ... Missing k6 module imports
... fix_script_done attempt=1 # 从实际的 k6 错误修复
... run_test_ok exit_code=0 reqs=2937
判决: 服务器端回归:/api/visits p95 318.44ms,59.4% 5xx,原因 'database is locked'
端点: POST /api/visits
k6 客户端: 2937 reqs,p95 318.44 ms,59.4% 失败
最差端点: /api/visits 59.4% 错误 p95 318.44 ms
根本原因: database is locked(1797x)
异常扫描: splunk StateSpaceForecast + anomalydetection 在 13 个桶上,1 个异常桶
mcp 工具调用: k6.{list_sections, get_documentation x4, generate_script(提示),
validate_script x2, run_script}
splunk.{get_info, get_index_info, get_metadata, run_query x6}
解读:
🂠 The Fool:差异模式显示 1 个端点受到审查。
🂠 The Magician:脚本编写,修复一次,验证成功。
🂠 The Tower: 2937 请求执行;p95 318.44 毫秒,59.4% 失败率。
🂠 The Lovers: /api/visits 最差,59.4% 错误,数据库锁定 1797 次。
🂠 The Star: StateSpaceForecast 预测 p95 ~312ms;anomalydetection 标记异常桶。
🂠 Judgement: 服务器回归确认:/api/visits,数据库锁定根本原因。
```
这证明了在运行时针对 live Splunk,所有这些都在运行时:kassi 从 git diff 中读取新的 `POST /api/visits`(未受影响的 GET 路由未被触及,因此它恰好测试了新的端点),模型编写了一个失败的 k6 验证脚本,`fix_script` 循环从实际的 k6 错误修复并验证,实际 k6 驱动了 2937 个请求,四个 `correlate` 查询在官方 Splunk MCP 服务器上隔离了新的端点(`/api/visits` 在 59.4% 5xx),并将根本原因命名为 k6 无法看到的内容(“数据库已锁定”),并且 AI 工具包的 `StateSpaceForecast` 预测延迟带,而 `anomalydetection` 统计异常标记桶。每个上游调用都在哈希链账本和 `mcp_provenance` 中。参见 [`docs/SPLUNK_SETUP.md`](docs/SPLUNK_SETUP.md) 了解完整的设置。
对于一个更轻量的复制品,无目标应用,`scripts/verify_correlate_live.py` 将 k6 指标罐装并摄入样本遥测数据,但仍然查询真正的官方 Splunk MCP 服务器。
## 演示场景
`examples/` 目录中包含五个目标应用程序,每个应用程序都包含一个健康的基准线和一个新的端点,该端点具有不同的负载诱导故障,因此该套件涵盖了常见的回归类(不仅仅是一个技巧)。每个应用程序都将相同的 `access_json` 遥测数据发送到 Splunk,因此 kassi 不会更改它们;故障仅在并发性下出现。
| 应用 | 新端点 | 故障特征 | 它锻炼了什么 |
| --- | --- | --- | --- |
| `petclinic` | `POST /api/visits` | 5xx, 常量, `database is locked` | 相关性隔离根本原因错误 |
| `storefront` | `POST /api/checkout` | 延迟, **0 错误** (N+1 over a shared connection) | 服务器端 `db_time`, 对客户端错误率不可见 |
| `feed` | `POST /api/events` | 延迟 **随着运行而增加** (无界重新计算) | `detect_anomalies`: 预测带和异常检测捕获趋势 |
| `gateway` | `GET /api/quote` | **4xx** 429 限流 (过紧的速率限制) | 客户端与服务器错误分割: "受限, 不是损坏" |
| `orders` | `POST /api/order` | 延迟 **+ 504 混合** (下游级联) | 依赖根本原因, 弹性推荐 |
运行任意一个端到端(启动应用程序,真正的 k6,实时 Splunk,基础分析):
```bash
uv run python scripts/verify_scenario.py feed # 或 petclinic | storefront | gateway | orders
```
`petclinic` 也是上述强调的差异模式运行。
## 基准测试
`kassi-bench` 将 kassi 与基本事实进行比较:80 次实时运行,涵盖五类因更改引起的故障(5xx 回归,两种延迟降级,4xx 限流,一个 504 级联)以及三个健康控制,每个运行 10 次,模型编写负载测试和分析,判决从 Splunk 确定性计算。在这些故障中,kassi 检测到 90%,定位 92%,分类 90%,并命名根本原因 95%;控制保持 0% 的误报率。第二个套件,`kassi-bench-ext`,将 kassi 与 go-httpbin(一个第三方应用程序,它从未进行过检测,通过通用访问日志代理观察)对抗,并获得 15/15 的评分。针对规范的学术基准 **RCAEval RE3** (在线精品和火车票的代码级故障),kassi 的诊断引擎在 57 个案例中以 **81%** 的比例定位根本原因服务(在线精品为 90%),在 **100%** 的案例中进入前三名,与最强的已发布方法竞争,并远超经典基线。在它们之间,套件发现并修复了三个真正的错误:一个缺失的限流分支,一个太低的延迟底线,以及一个验证步骤,该步骤读取了一个跨越 k6 阈值的交叉阈值,认为它是一个损坏的脚本。完整的 方法论 和 表格:
[`docs/benchmark/BENCHMARK.md`](docs/benchmark/BENCHMARK.md).
```bash
uv run python scripts/benchmark.py --reps 10 # 演示套件 -> docs/benchmark/results.json
docker run -d -p 8600:8080 ghcr.io/mccutchen/go-httpbin
uv run python scripts/benchmark_external.py --reps 5 # 外部套件(go-httpbin 通过代理)
uv run python scripts/benchmark_rcaeval.py --systems OB,TT # 规范 RCAEval RE3(下载后)
uv run python scripts/benchmark_report.py # 重新生成报告
```
## 仪表盘
<p align="center"><img src="docs/assets/shot-dashboard.png" alt="kassi 仪表盘:从 Splunk 读取更改影响" width="820" /></p>
`report` 阶段将每次运行发布到 `index=kassi_runs` HEC: 一个 `kassi:run` 摘要(判决,k6 客户端指标,服务器端相关性,预测,根本原因)和一个 `kassi:step` 事件,每个状态机阶段,代理从 The Fool 到 Judgement 的过程,由 Burr 的 `app_id` 键控。所以仪表盘显示了更改的影响以及代理如何得出判决。代理保持 CLI/MCP;Splunk 是报告表面。一次性配置:
```bash
uv run python scripts/setup_dashboard.py # 创建索引,HEC令牌和仪表盘
# 将打印的 KASSI_HEC_TOKEN 粘贴到 .env 中,然后每次运行自行发布
```
仪表盘 (`docs/dashboard/kassi_overview.xml`) 显示最新的判决,代理的状态机流程图(每个阶段,其结果和工具调用),跨运行的步骤结果,k6 与服务器端 p95,跨运行的 p95,服务器端每个端点的错误,以及运行历史表。由 `KASSI_HEC_TOKEN` 控制:未设置时,运行不会发布。
## 开发
```bash
uv run ruff format . && uv run ruff check .
uv run pytest
```
测试使用 Theodosia 的 `FakeUpstream` 进行 MCP 服务器和假 LLM,因此它们在没有 k6,Splunk,Ollama 或网络的情况下离线运行。
### 本地 Splunk
[`docs/SPLUNK_SETUP.md`](docs/SPLUNK_SETUP.md) 介绍了在本地运行 Splunk Enterprise,播种样本遥测数据,并验证集成。两个辅助脚本:
```bash
uv run python scripts/seed_splunk.py # 索引 + HEC + 样板数据 + 验证 SPL kassi 发出
uv run python scripts/verify_correlate_live.py # 驱动整个 FSM;关联实时 Splunk
KASSI_LLM=claude_agent uv run python scripts/verify_petclinic.py # 真实应用程序根本原因演示
```
`verify_petclinic.py` 是主要的演示,不是 canned:它启动 [`examples/petclinic`](examples/petclinic) 应用程序(一个健康的基准线加上一个新的 `POST /api/visits`,具有 SQLite 写锁故障,只有在负载下才会出现, shipping 访问日志到 Splunk 的 HEC),通过 k6 MCP 服务器运行真正的 k6,并从 Splunk 读取服务器端回归:哪个端点,如何严重,以及 k6 单独看不到的“数据库锁定”根本原因。
`scripts/dev_splunk_mcp.py` 是一个本地_stdio MCP 桥到 Splunk REST,仅用于在没有官方应用程序的情况下练习关联路径。生产环境使用官方 Splunk MCP 服务器通过 `KASSI_SPLUNK_MCP_ENDPOINT` + `KASSI_SPLUNK_TOKEN`。参见 [案例研究](#案例研究) 以获取已验证的运行。
## 许可证
Apache-2.0. kassi 建立在 Theodosia(Apache-2.0),Burr(Apache-2.0)和官方 Grafana k6 和 Splunk MCP 服务器之上。
Tarot icon 由 [Eucalyp](https://thenounproject.com/Eucalyp/) 从 Noun Project 提供, [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/).
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器