manavgup/ai-agent-controlplane-demo
GitHub: manavgup/ai-agent-controlplane-demo
该项目演示了如何通过 IBM ContextForge 网关作为 AI Agent 的控制平面,在金融科技场景中实现对工具调用的策略管控、数据保护和权限治理。
Stars: 1 | Forks: 2
# ai-agent-controlplane-demo
**没有 Docker?** 该技术栈也可以在 **Podman** 上运行 — 参见 [在 Podman 上运行](docs/RUNBOOK.md#run-on-podman-no-docker),或者使用 `bash scripts/test-fresh-host.sh` 在全新的 Ubuntu/WSL2/x86 主机上一键执行。 | | **uv** | **离线**生成网关 JWT(无网络往返) | `https://docs.astral.sh/uv/` | | **IBM Bob Shell** (`bob`) | _可选_ — 仅用于**驱动** Bob;技术栈 + `16/16` 的证明运行不需要它 | macOS/Linux: `curl -fsSL https://bob.ibm.com/download/bobshell.sh \| bash` ([bob.ibm.com/download](https://bob.ibm.com/download)) — 会首先检查 Node ≥ 22.15 | | **Node.js ≥ 22.15** | _可选_ — IBM Bob Shell(它是一个 Node 应用)和 MCP Inspector (`npx`) 需要;启动技术栈或证明控制不需要它 | [nodejs.org](https://nodejs.org),或 `nvm install 22` | ## 两种运行方式 相同的技术栈,两种故事 — **选择你的路径**:
自底向上,与 `make quickstart` 相反:从任何你都能认出的原生 MCP 服务器开始,一次一层地引入 ContextForge —— **全程携带你构建的工具**。打开提示卡并驱动 Bob 经历四个阶段: ``` make dev-start # opens docs/build.html — the follow-along build guide (copy-paste Bob prompts) ``` | 阶段 | 命令 | 你(和 Bob)做什么 | Bob 角色 | |---|---|---|---| | **① 构建** | `make stage1-build` | **提示 Bob** 从零开始编写 `mcp-servers/sales-tax/server.py`(一个 FastMCP `add_tax` 工具)。它在 `:8000` 上原生运行;调用会打印 `add_tax(100) → 108.50`。*它能工作 —— 而且完全没有被管治:没有 token,没有策略,任何连上端口的人都能运行任何东西。* | — | | **② 管治** | `make stage2-govern` | **相同**的服务器被容器化并加入网格,被**注册**(在目录中,受 token 控制 —— *尚不可调用*),然后被**授予**到一个 `Builder` 虚拟服务器中,并**通过网关回调** → `108.50`。**2b 额外环节** Bob *扩展*了一个它没有编写的服务(`fx-rates` 增加了 `convert`)。 | operator → **builder** | | **③ 控制** | `make stage3-controls` | 一个提示词驱动一个批处理;**四项控制对真实调用生效** — PII 脱敏、注入被中和、OPA 阻止了 5 万美元的跨语言电汇、RBAC(Bob 没有 `wire` 工具)。 | analyst | | **④ 网格** | `make stage4-mesh` | 完整的受管治视图 —— 与 `quickstart` 的最终状态完全相同,只是你看着它被构建出来。 | — | **核心主线是 `register → grant → call`。** 你的工具经历了从 *能用但不受管治* → *在目录中但不可调用* → *被授予并可通过唯一受管治的接口调用*,同时应用了脱敏、策略和审计。注册一个后端并不会让它变得可调用 —— **将其授予给 agent 是一个单独的、特权步骤**(`make salestax-grant` 将其添加到 `Builder` vserver 中)。这个界限*就是*最小权限。 **`builder` 角色**(`make bob-install-builder`)是开发者的席位 —— 它调用*你自己被授予的工具*(`add_tax`, `convert`),以及现有的 **analyst**(最小权限消费者)和 **operator**(注册 / 审计 / 评估策略)角色。 **你的笔记本电脑上没有 Docker?** `make connect` 会打印一行指向在其他地方运行的网关的 `bob mcp add … -t http` 命令 —— 可以是队友的机器、一台虚拟机,或者一个 **GitHub Codespace** —— 这样你只需要**安装 Bob** 就能驱动整个受管治的网格,并且管治在网络上保持不变。 → 解说环节:**[`docs/SHOWCASE-BOB.md`](docs/SHOWCASE-BOB.md)** · 可跟随操作的 **[`docs/build.html`](docs/build.html)**(演示者控制台:**[`docs/cockpit.html`](docs/cockpit.html)**) · 零设置级别见 **[`docs/ONBOARDING.md`](docs/ONBOARDING.md)**。
自顶向下:**一条命令**就能让一台笔记本电脑从无到有变成一个运行中的、受管治的网格,并证明全部四项控制(`16/16`) —— 不需要 Bob。然后以 FinOps **分析师**(第一幕)和平台**操作员**(第二幕)的身份驱动 Bob,并观察控制平面在管理界面中的反应。 → 完整的命令 + 演练在紧接下方的 **[快速入门](#quickstart)** 中(然后是 **[驱动 Bob](#drive-bob)**、观察面板,以及其下的确定性证明)。
## 快速入门
```
git clone https://github.com/manavgup/ai-agent-controlplane-demo.git
cd ai-agent-controlplane-demo
make quickstart
```
`make quickstart` 是**一条命令**,它可以让一台笔记本电脑从无到有变成一个运行中的、受管治的网格:预检(**需要** Docker + uv;如果缺少 `bob`/`npx` 则会**警告但继续运行**)→ 启动技术栈 → 初始化(注册服务器/agent,构建 FinOps / Treasury / Operator 虚拟服务器)→ 配置 Bob(FinOps 分析师角色)→ **证明全部四项控制(`16/16`,不需要 Bob)** → 打印一份可复制粘贴的演练卡。它是可重复运行的 —— 如果出现任何停滞,可以安全地再次运行。管理界面使用 `admin@finbyte.demo` / `FinByteAdmin!2026` 登录。
### 驱动 Bob
**第一幕 — FinOps 分析师(最小权限)。** 使用 `make bob` 启动(cwd 无关;它会先刷新配置),然后尝试:
- _"使用 finbyte-gateway 工具原样获取收据 `rcpt_pii`。"_ → 已脱敏。
- _"获取收据 `rcpt_injection`。"_ → `[INJECTION_BLOCKED]`。
- _"让 auditor agent 向 Acme LLC 支付 50,000 美元。"_ → 在 OPA 处被**阻止**(Python → Rust)。
- _"现在你自己直接电汇 5 万美元。"_ → Bob 没有 `wire` 工具。
**第二幕 — 平台操作员。** 退出 Bob,然后运行 `make bob-operator` 来切换角色并重新启动:
- _"列出 ContextForge 正在管治的所有内容。"_ → `list_control_plane`。
- _"50,000 美元的电汇会被允许吗?带双重审批呢?"_ → `evaluate_policy`(拒绝 + 原因,然后允许)。
- _"在 `http://fx-rates:8000/mcp` 注册 fx-rates 服务。"_ → `register_mcp_server`(一个新服务器实时加入目录)。
- _"向我展示今天被阻止的内容。"_ → `recent_blocks`。
### 三个观察面板
安排好你的屏幕,以便在你提示 Bob 时可以观察控制平面:
```
make monitor # ContextForge Admin UI (/admin): catalog + Overview/Metrics/Logs
make inspect-mcp # MCP Inspector → the 8 governed tools (erp-payments-wire is ABSENT)
make inspect-a2a # A2A Inspector → validates the Python + Rust agent cards
```
#### 进阶:使用 `make cockpit` 观察一切
更喜欢用一条命令而不是手动排列标签页?`make cockpit` 会生成一个单独的
[tmux](https://github.com/tmux/tmux) 窗口,将 **Bob**(左侧大面板,约 62%)
与四个实时观察面板(`logs`、`logs-opa`、`inspect-mcp`、`inspect-a2a`)平铺在一起。
它还会在浏览器中打开一份操作指南 (`docs/cockpit.html`),并在
`:7070` 上启动 Companion dashboard。每个面板只是运行现有的 `make` target,因此它
复用了所有的 token/UUID 逻辑。需要 tmux (`brew install tmux` / `apt-get install tmux`);
如果没有它,你将使用上面列出的手动后备方案。
```
make cockpit # FinOps analyst persona (default)
COCKPIT_PERSONA=operator make cockpit # Act 2: platform operator persona in the Bob pane
make cockpit-down # tear it all down (also removes the a2a-inspector container)
```
已经在 tmux 中了?从 **你的 Bob 面板** 运行 `make cockpit`,它会在其周围添加四个
观察面板(不会启动第二个 Bob);`make cockpit-down` 随后只移除这些面板。
**通过 SSH:** cockpit (tmux) 可以在远程主机上正常运行,但浏览器 UI
(操作指南页面、Companion、管理界面、MCP/A2A Inspectors)也驻留在那里 —— `make cockpit` 会打印 URL 以及端口转发提示,而不是直接打开标签页。从你的笔记本电脑转发它们:
```
ssh -L 4444:localhost:4444 -L 7070:localhost:7070 -L 6274:localhost:6274 -L 6277:localhost:6277 -L 8090:localhost:8090
```
### 在全新的 Linux 主机 / 虚拟机上运行
在干净的 Linux 主机上(或者 Apple 芯片上的轻量级 Multipass/Lima 虚拟机 —— 这是一条实用路径,因为 macOS 客户机虚拟机需要约 60 GB+ 的磁盘空间)从无到有达到 `16/16`:
```
# 1. 安装 runtime + build deps(Docker Engine 原生运行,无需嵌套虚拟化):
# - Docker Engine https://docs.docker.com/engine/install/
# - Node.js ≥ 22.15 nvm install 22 (仅用于 DRIVE Bob)
# - uv https://docs.astral.sh/uv/
# - git + make 您的发行版的包管理器
# 2. 克隆 + 全部启动 → 16 个通过,0 个失败(不需要 Bob):
git clone https://github.com/manavgup/ai-agent-controlplane-demo.git
cd ai-agent-controlplane-demo
make quickstart
# 3. 要 DRIVE 该 demo,请安装 IBM Bob Shell(跨平台;检查 Node ≥ 22.15):
curl -fsSL https://bob.ibm.com/download/bobshell.sh | bash
make bob # first run prompts an IBMid device-code login on a headless box
```
## 证明 / 观察控制
无头证明只需一条命令:
```
make verify-controls # → RESULT: 16 passed, 0 failed
```
它运行 `scripts/money-shots/run-all.sh`,该脚本会断言全部四项控制以及跨语言 agent 网格的拦截情况,还有 Rust agent 成功执行一次符合策略的支付 —— 总共 16 个断言。这就是安全网:随时运行它以确认技术栈是真实可靠的。
要在你提示 Bob 时实时观察控制的触发情况,请参见 **[`docs/LOG-CHEATSHEET.md`](docs/LOG-CHEATSHEET.md)** —— 精确的提示 → 日志行映射(包括哪个环节_本应_不记录任何日志) —— 并 tail 以下日志:
```
make logs # raw gateway logs (blocked calls surface as ERROR 'invocation failed')
make logs-opa # live, readable OPA decisions: ALLOW/DENY + args + reason
```
## 项目布局
```
ai-agent-controlplane-demo/
├── a2a-agents/ # the 2 A2A agents: auditor/ (Python, a2a-sdk) + payments/ (Rust, a2a-lf)
├── bob-personas/ # mcp.json templates for the analyst + operator + builder personas (live-UUID rewrite)
├── companion/ # optional browser dashboard (Flask, :7070) to watch the control plane
├── gateway/ # ContextForge image + OPA image: custom/ plugin, plugins/ config, policies/ Rego, seed/
├── mcp-servers/ # the 6 MCP servers: expense-db, erp-payments, policy-docs, notify, controlplane, fx-rates
│ # + sales-tax/ — the Dev Day "Bob builds it from scratch" server (generated; Stage 1→2)
├── scripts/ # quickstart.sh, demo.sh, watch-decisions.sh, money-shots/ proof suite
├── slides/ # the conference talk deck (.pptx) + outline
└── docs/ # QUICKSTART/RUNBOOK/LOG-CHEATSHEET/SCENARIOS/SHOWCASE-BOB + diagrams/
```
## 工作原理
- **虚拟服务器。** 网关暴露了完整工具目录中经过筛选的最小权限切片:**FinOps**(8 个工具,没有 wire —— 分析师),**Treasury**(电汇路径:`wire`, `reimburse`, `a2a_payments`),以及 **Operator**(4 个控制平面工具)。RBAC 是根据角色指向的_虚拟服务器_来执行的,而不是根据 token identity。
- **stdio bridge。** Bob 通过 `uvx --from mcp-contextforge-gateway python -m mcpgateway.wrapper` 连接,参数为 `MCP_SERVER_URL=http://localhost:4444/servers//sse` 和 `MCP_AUTH=Bearer `。Bob 从仓库根目录读取 `.bob/mcp.json` —— 这就是为什么你总是要通过 `make bob` / `make bob-operator` 启动。
- **路径独立性。** 网关配置、FinByteGuard plugin 和 Rego 策略被预构建在镜像中(`gateway/Dockerfile`, `gateway/Dockerfile.opa`)。零宿主机 bind-mounts 意味着技术栈可以从**任何**克隆路径运行 —— 即使是 Docker 无法共享的路径,比如 macOS 上的 `/tmp`。
## 故障排除与重置
- **参与者演练:** [`QUICKSTART.md`](QUICKSTART.md) — 3 面板、可跟随操作的指南。
- **演示者运行顺序 + 恢复:** [`docs/RUNBOOK.md`](docs/RUNBOOK.md)。
- **任何偏差 / `16/16` 失败:** `make demo-reset`(重建 + 重新初始化网关),然后 `make verify-controls`。
- **易错点 — "No MCP servers configured":** 你从错误的目录(通常是 `bob-personas/` 子文件夹)启动了 `bob`。Bob 会相对于它的 cwd 查找 `.bob/mcp.json`。退出它并运行 **`make bob`**,它会从仓库根目录启动 _并且_ 在重新初始化后刷新实时的 UUID。
- **全新的 Linux 虚拟机 — 在 `make quickstart` 镜像构建期间出现 `Could not resolve host …`**(例如 `index.crates.io`,而镜像 _拉取_ 成功):Docker 构建容器正在使用宿主机已失效的 `systemd-resolved` `127.0.0.53` 存根。修复 → 写入包含 `{"dns":["8.8.8.8","1.1.1.1"]}` 的 `/etc/docker/daemon.json`,运行 `sudo systemctl restart docker`,然后重新运行 `make quickstart`(幂等)。参见 **[在全新的 Linux 主机 / 虚拟机上运行](#running-on-a-fresh-linux-box--vm)**。
## 安全 / 免责声明
**这是一个演示,不是生产环境。** JWT 使用**公开的**演示密钥(`demo-only-change-me-…`)签名,针对本地 HTTP 演示禁用了 CSRF,并且针对 Compose 私有网络放宽了 SSRF 防护。请勿在演示之外重用任何此配置。对于生产环境,请生成你自己的密钥,启用 HTTPS + CSRF,并收紧 SSRF —— 参见上游的 [IBM ContextForge](https://github.com/IBM/mcp-context-forge) 项目。
## 许可证
在 **MIT License** 下发布 —— 见 [`LICENSE`](LICENSE)。上述仅用于演示的警告仍然适用:捆绑的密钥和密码是故意公开的,绝不能在生产环境中重用。
无法在本地运行 Docker/ContextForge?点击徽章 —— 整个受管治的网格将在云端构建;你的笔记本电脑上只需要 IBM Bob(ONBOARDING.md 中的第 2 级)。
**没有 Docker?** 该技术栈也可以在 **Podman** 上运行 — 参见 [在 Podman 上运行](docs/RUNBOOK.md#run-on-podman-no-docker),或者使用 `bash scripts/test-fresh-host.sh` 在全新的 Ubuntu/WSL2/x86 主机上一键执行。 | | **uv** | **离线**生成网关 JWT(无网络往返) | `https://docs.astral.sh/uv/` | | **IBM Bob Shell** (`bob`) | _可选_ — 仅用于**驱动** Bob;技术栈 + `16/16` 的证明运行不需要它 | macOS/Linux: `curl -fsSL https://bob.ibm.com/download/bobshell.sh \| bash` ([bob.ibm.com/download](https://bob.ibm.com/download)) — 会首先检查 Node ≥ 22.15 | | **Node.js ≥ 22.15** | _可选_ — IBM Bob Shell(它是一个 Node 应用)和 MCP Inspector (`npx`) 需要;启动技术栈或证明控制不需要它 | [nodejs.org](https://nodejs.org),或 `nvm install 22` | ## 两种运行方式 相同的技术栈,两种故事 — **选择你的路径**:
🎓 渐进式构建 — 从零开始构建一个 agent 工具,然后观察它如何被管治 (开发者路径)
自底向上,与 `make quickstart` 相反:从任何你都能认出的原生 MCP 服务器开始,一次一层地引入 ContextForge —— **全程携带你构建的工具**。打开提示卡并驱动 Bob 经历四个阶段: ``` make dev-start # opens docs/build.html — the follow-along build guide (copy-paste Bob prompts) ``` | 阶段 | 命令 | 你(和 Bob)做什么 | Bob 角色 | |---|---|---|---| | **① 构建** | `make stage1-build` | **提示 Bob** 从零开始编写 `mcp-servers/sales-tax/server.py`(一个 FastMCP `add_tax` 工具)。它在 `:8000` 上原生运行;调用会打印 `add_tax(100) → 108.50`。*它能工作 —— 而且完全没有被管治:没有 token,没有策略,任何连上端口的人都能运行任何东西。* | — | | **② 管治** | `make stage2-govern` | **相同**的服务器被容器化并加入网格,被**注册**(在目录中,受 token 控制 —— *尚不可调用*),然后被**授予**到一个 `Builder` 虚拟服务器中,并**通过网关回调** → `108.50`。**2b 额外环节** Bob *扩展*了一个它没有编写的服务(`fx-rates` 增加了 `convert`)。 | operator → **builder** | | **③ 控制** | `make stage3-controls` | 一个提示词驱动一个批处理;**四项控制对真实调用生效** — PII 脱敏、注入被中和、OPA 阻止了 5 万美元的跨语言电汇、RBAC(Bob 没有 `wire` 工具)。 | analyst | | **④ 网格** | `make stage4-mesh` | 完整的受管治视图 —— 与 `quickstart` 的最终状态完全相同,只是你看着它被构建出来。 | — | **核心主线是 `register → grant → call`。** 你的工具经历了从 *能用但不受管治* → *在目录中但不可调用* → *被授予并可通过唯一受管治的接口调用*,同时应用了脱敏、策略和审计。注册一个后端并不会让它变得可调用 —— **将其授予给 agent 是一个单独的、特权步骤**(`make salestax-grant` 将其添加到 `Builder` vserver 中)。这个界限*就是*最小权限。 **`builder` 角色**(`make bob-install-builder`)是开发者的席位 —— 它调用*你自己被授予的工具*(`add_tax`, `convert`),以及现有的 **analyst**(最小权限消费者)和 **operator**(注册 / 审计 / 评估策略)角色。 **你的笔记本电脑上没有 Docker?** `make connect` 会打印一行指向在其他地方运行的网关的 `bob mcp add … -t http` 命令 —— 可以是队友的机器、一台虚拟机,或者一个 **GitHub Codespace** —— 这样你只需要**安装 Bob** 就能驱动整个受管治的网格,并且管治在网络上保持不变。 → 解说环节:**[`docs/SHOWCASE-BOB.md`](docs/SHOWCASE-BOB.md)** · 可跟随操作的 **[`docs/build.html`](docs/build.html)**(演示者控制台:**[`docs/cockpit.html`](docs/cockpit.html)**) · 零设置级别见 **[`docs/ONBOARDING.md`](docs/ONBOARDING.md)**。
🛰 受管治网格 — 直接进入完成的、受管治的技术栈 (快速入门路径)
自顶向下:**一条命令**就能让一台笔记本电脑从无到有变成一个运行中的、受管治的网格,并证明全部四项控制(`16/16`) —— 不需要 Bob。然后以 FinOps **分析师**(第一幕)和平台**操作员**(第二幕)的身份驱动 Bob,并观察控制平面在管理界面中的反应。 → 完整的命令 + 演练在紧接下方的 **[快速入门](#quickstart)** 中(然后是 **[驱动 Bob](#drive-bob)**、观察面板,以及其下的确定性证明)。
标签:AI智能体, Streamlit, 可视化界面, 数据脱敏, 示例项目, 策略引擎, 结构化提示词, 网关控制面, 网络安全挑战, 访问控制, 请求拦截, 逆向工具, 金融科技