manavgup/ai-agent-controlplane-demo

GitHub: manavgup/ai-agent-controlplane-demo

该项目演示了如何通过 IBM ContextForge 网关作为 AI Agent 的控制平面,在金融科技场景中实现对工具调用的策略管控、数据保护和权限治理。

Stars: 1 | Forks: 2

# ai-agent-controlplane-demo

Open in GitHub Codespaces

无法在本地运行 Docker/ContextForge?点击徽章 —— 整个受管治的网格将在云端构建;你的笔记本电脑上只需要 IBM Bob(ONBOARDING.md 中的第 2 级)。

Reference architecture: IBM Bob drives a FinByte agent mesh through the IBM ContextForge gateway, with an OPA sidecar, six MCP servers, and two cross-language A2A agents.

这是一个开箱即用、可跟随操作的 [IBM ContextForge](https://github.com/IBM/mcp-context-forge)(MCP / A2A 网关)演示,它作为 AI agent(**IBM Bob**)与金融科技("FinByte")报销与支付 agent 网格之间的**控制平面**。该网关位于每一次工具调用和每一次 agent 间调用的中间,执行**四项控制**,你可以用**一条命令**证明所有这些控制 → `16 passed, 0 failed`。 ## 这是什么? 当一个 AI agent 可以读取收据、审批报销并转移资金时,问题就不再是_"agent 能做到吗?"_,而是变成了_"谁在管理 agent?"_。这个演示用控制平面回答了这个问题。**IBM Bob** 就是这个 agent —— 一个驱动 FinByte agent 网格(报销查询、ERP 支付、策略文档、通知以及两个自治的 A2A agent)的 MCP 客户端。它从不直接与那些后端通信。每一次调用都流经 **IBM ContextForge**,这是一个在 Bob 看到结果_之前_、在任何资金转移_之前_进行身份验证、授权、管治、脱敏和审计的网关。 该网关执行: - **策略 (OPA)。** 超过 10,000 美元 FinByte T&E 上限的电汇会被**阻止**,除非带有双重审批 —— 由 Open Policy Agent sidecar 针对某项 Rego 策略进行实时评估。 - **数据保护。** 工具输出中的 SSN、信用卡号、API 密钥和其他敏感信息在到达 agent _之前_会在**网关上被掩码**(`***-**-6789`, `****-****-****-1111`, `[SECRET_REDACTED]`)。 - **提示词注入中和。** 隐藏在工具输出中的对抗性指令("SYSTEM: 忽略所有先前策略…")会被**中和**为 `[INJECTION_BLOCKED]`。 - **RBAC 最小权限。** FinOps 分析师角色根本没有 `wire` 工具;只有特权操作员角色才能注册服务器、读取审计日志或查询策略。(速率限制是 ContextForge 的内置功能,但在此技术栈中_未_进行配置或演示。) - **Agent 网格管治。** 阻止直接电汇的同一策略,也会在桥接的工具 hook 处阻止**跨语言**的 agent 间支付(一个 Python auditor 向一个 Rust payments agent 委托 5 万美元的支付)。 整个技术栈是路径无关的 —— config、plugins 和 Rego 策略都被预构建在镜像中,因此**零宿主机 bind-mounts**,并且可以从任何克隆路径运行。 ## 架构 _(见顶部的图表。)_ IBM Bob 通过 `mcpgateway.wrapper` stdio bridge 连接到网关上的一个**虚拟服务器**(目录中经过筛选的最小权限切片)。该网关代理了五个受管治的 MCP 服务器、一个故意未注册的 MCP 服务器以及两个 A2A agent,并带有一个用于策略决策的 OPA sidecar。只有网关和两个 A2A agent 将端口发布到宿主机;OPA sidecar 和所有 MCP 服务器只能在 Compose 私有网络上访问。 | 组件 | 类型 | 端口 | 角色 | |---|---|---|---| | **IBM Bob** | AI agent / MCP 客户端 | — | 驱动网格;通过 `mcpgateway.wrapper` stdio bridge 连接到虚拟服务器 | | **ContextForge 网关** | MCP/A2A 网关(控制平面) | `4444` (宿主机) | 认证/授权、管治、脱敏、审计、联邦;管理界面位于 `/admin` | | **OPA** | Open Policy Agent sidecar | `8181` (内部) | 评估 Rego 电汇金额策略 (`package mcpgateway`) | | **expense-db** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | `list_pending_expenses`, `get_expense`, `get_receipt` (包含 PII / injection 固定数据) | | **erp-payments** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | `approve`, `reimburse`, `wire` (受管治的支付路径) | | **policy-docs** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | `get_policy`, `wire_limit` | | **notify** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | `notify` | | **controlplane** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | 操作员界面:`register_mcp_server`, `list_control_plane`, `recent_blocks`, `evaluate_policy` | | **fx-rates** | MCP 服务器 (Python, FastMCP) | `8000` (内部) | `get_fx_rate`, `list_currencies` — **运行但被故意设置为未注册** (用于实时注册环节) | | **auditor** | A2A agent (Python, `a2a-sdk`) | `9001` (宿主机) | 审计报销;可以向 Rust agent 委托支付 | | **payments** | A2A agent (Rust, `a2a-lf` / `a2a-server-lf`) | `3000` (宿主机) | 执行支付;JSON-RPC 位于 `/jsonrpc`,agent card 位于 `/.well-known/agent-card.json` | ## 调用是如何被管治的

Call path: Bob's tool call enters the gateway, runs through tool_pre_invoke (FinByteGuard queries OPA) and tool_post_invoke (FinByteGuard + PIIFilterPlugin sanitize output) before returning a governed result.

每一次工具调用都会流经两个网关 plugin hook。在 **`tool_pre_invoke`** 时,自定义的 **FinByteGuard** plugin(`gateway/custom/finbyte_guard.py`,基于 cpex framework)会提取调用的参数,并询问 **OPA** 电汇金额策略是否允许该操作 —— 拒绝任何超过 10,000 美元上限且无双重审批的操作,如果 OPA 无法访问则直接 _失败关闭_。在 **`tool_post_invoke`** 时,FinByteGuard 会深度清理机密信息(`sk-live-…` → `[SECRET_REDACTED]`)并中和提示词注入(→ `[INJECTION_BLOCKED]`),同时 cpex **PIIFilterPlugin** 会对 SSN 和信用卡号进行掩码处理。每一个决策都会生成一条 `AUDIT [FinByteGuard] …` 日志,并显示在管理界面的 **Logs** 标签页中。 ## 四项控制

The four controls: OPA wire-amount policy, PII/secret redaction, prompt-injection neutralization, and RBAC least-privilege — each shown as a Bob prompt and the gateway's response.

| 控制 | 对 Bob 的提示 | ContextForge 的操作 | |---|---|---| | **1 — 策略 (OPA)** | _"使用 finbyte-gateway 工具为报销 `exp_big` 向 Acme LLC 电汇 50,000 美元。"_ | 在 OPA 处**阻止**:_"…超过了 10,000 美元的自动审批限额… FinByte T&E 策略第 2 条。"_ 加上 _"带双重审批"_ → **允许**。相同的策略会在桥接的 `a2a-payments` hook 处阻止跨语言的 auditor→payments 的 5 万美元操作。 | | **2 — 数据保护** | _"原样获取收据 `rcpt_pii`。"_ | 在 Bob 看到之前进行**掩码**:SSN → `***-**-6789`,卡号 → `****-****-****-1111`,API 密钥 → `[SECRET_REDACTED]`。 | | **3 — 提示词注入** | _"获取收据 `rcpt_injection`。"_ | **中和**嵌入的 `SYSTEM: 忽略所有先前策略…` → `[INJECTION_BLOCKED]`。 | | **4 — RBAC 最小权限** | _"现在你自己直接电汇 5 万美元。"_ | Bob **做不到** —— FinOps 虚拟服务器隐藏了 `erp-payments-wire`。MCP Inspector 确认该工具不存在。操作员角色拥有分析师所缺乏的控制平面工具。 | 正常运行的基线:_"处理报销 `exp_clean` 并对其进行报销。"_ —— 一笔 18.50 美元的正常报销会直接通过。 ## 两个角色 (RBAC) 相同的 Bob 二进制文件会根据其 `.bob/mcp.json` 指向的虚拟服务器成为两个不同的参与者。这两个目标都会重写 `.bob/mcp.json`(基于 `bob-personas/*.template` 文件,刷新实时的 UUID),并从仓库根目录启动 Bob,因此它们是 cwd 无关且重置无关的。 | | `make bob` — **FinOps 分析师** (第一幕) | `make bob-operator` — **平台操作员** (第二幕) | |---|---|---| | 虚拟服务器 | **FinOps** (8 个工具) | **Operator** (4 个工具) | | 能做 | 列出/读取报销、读取收据、`approve`、`reimburse`、读取策略 + 电汇限额、与 **auditor** agent 通信 | `register_mcp_server`, `list_control_plane`, `recent_blocks`, `evaluate_policy` | | **不能**做 | **没有 `wire` 工具**;无法注册服务器、读取审计日志或直接查询策略 | 不是分析师处理报销的界面 | | 角色文件 | `bob-personas/mcp.json.template` (服务器 `finbyte-gateway`) | `bob-personas/mcp.operator.json.template` (服务器 `finbyte-operator`) | 随时可以通过 `make bob` 切换回分析师角色。 ## 前置条件 | 工具 | 用途 | 获取方式 | |---|---|---| | **Docker** (运行中) | 运行网关、OPA、MCP 服务器和 A2A agent | macOS/Windows 上的 **Docker Desktop**,或者 Linux 上的 **Docker Engine**(原生运行,无需嵌套虚拟化)。开始前先启动它。 — [docker.com](https://www.docker.com/products/docker-desktop/)
**没有 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)**、观察面板,以及其下的确定性证明)。
## 快速入门 ``` 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)。上述仅用于演示的警告仍然适用:捆绑的密钥和密码是故意公开的,绝不能在生产环境中重用。
标签:AI智能体, Streamlit, 可视化界面, 数据脱敏, 示例项目, 策略引擎, 结构化提示词, 网关控制面, 网络安全挑战, 访问控制, 请求拦截, 逆向工具, 金融科技