Java 8老系统AI工具接入:API包装成受控工具,只读优先+权限拦截

为什么要写这个系列

做Java后端十年,我接触过不少企业的核心系统。

金融、电商、政务------行业不同,但底层的现状惊人地相似:生产系统还在Java 8,框架停在Spring Boot 2.x甚至更早,代码跑了很多年,没人敢轻易动。

去年开始,几乎每个项目都在谈接AI。

但真正动手的时候,团队就卡住了。

不是因为不懂大模型,而是老系统本身接不住。JDK版本不够,Spring AI引不进来;依赖树牵一发动全身,升级一个包怕带崩一片;生产流量压着,不敢拿主流程赌一个AI试点。

更危险的是硬塞。我见过团队在老系统的Service层直接new一个HttpClient调模型API,Prompt拼在业务代码里,超时没配、降级没有。模型响应慢的时候,老系统的订单查询线程池被占满,主流程跟着卡住。还有团队把用户手机号、身份证原样送进Prompt,过了两个月才被安全审计发现。

这种事见多了,我就开始想一个问题:老系统不具备直接接入AI的条件,这是不是大多数企业的常态?

答案是肯定的。而且这不应该成为接不了AI的理由。

核心思路其实就三条:

text 复制代码
老系统少改 ------ 不升级 JDK,不引入 Spring AI 依赖
AI 能力旁路 ------ 独立部署,老系统通过 HTTP 或 MQ 调用
企业边界先行 ------ 脱敏、审计、降级、幂等比模型调用更重要

这个系列就是把这三条线展开成10讲。

从AI Gateway到MCP工具中心,从SQL Agent到RAG知识库,从工单Agent到多Agent研发团队------每一讲都围绕同一个前提:

你的老系统还在跑Java 8,你不能为了AI去赌它的稳定性。

每讲配套一个可运行的Maven Lab,不讲空架构,不写Hello World。你跑得通Demo,看得到边界,拿得到代码。

这就是我做这个系列的原因。

这个系列帮你建立企业 AI 接入的架构意识。每个 Demo 都可独立运行,每讲都配有边界设计和企业避坑。

但意识不等于系统。当你真正要在自己的项目里落地时,会发现:

  • 10 个独立 Lab 的组件需要整合成一个完整的 AI 能力中心
  • Stub 模型需要替换成真实模型调用
  • 权限、审计、脱敏需要从 Demo 级别升级到生产级别

先把架构意识打好,落地时才能走得更稳。


Java 8老系统AI工具接入:API包装成受控工具,只读优先+权限拦截

第1讲我们先解决了一个基础问题:

text 复制代码
Java 8 老系统不升级
        ↓
通过旁路 AI Gateway 接入 AI 能力
        ↓
AI 只生成建议,不直接改业务状态

这个结论很重要。

因为很多团队一接入AI,就忍不住让AI"直接干活":

text 复制代码
直接查订单
直接查客户
直接查库存
直接改状态
直接发审批

如果没有边界,这些动作很快就会从"智能助手"变成"系统权限入口"。

所以第2讲要把第1讲的结论往前推进一步:

AI可以使用老系统能力,但不能直接拿到老系统API。

更准确地说:

老系统API要先包装成可授权、可审计、可脱敏的工具,再交给AI使用。

这一讲标题里用了MCP Tool Center,但我们先不讲协议细节。先讲企业真正关心的问题:一个API到底能不能变成AI工具?如果能,怎么控制它的输入、执行和输出?

AI调工具前,先问三个问题

当你准备把一个老系统API暴露给AI时,先不要急着写Tool。先问三个问题:

text 复制代码
这个能力是读还是写?
这个能力的参数边界是什么?
这个能力的返回值能不能原样给模型?

这三个问题分别对应三条边界:

text 复制代码
读写边界:AI 能不能执行这个动作
参数边界:AI 能带着什么条件执行
输出边界:执行结果能不能原样返回

第一个问题:这个能力是读还是写

比如订单系统里有两个能力:

text 复制代码
queryOrder(orderId)       查询订单
updateOrderStatus(...)    修改订单状态

它们看起来都只是一个API,但风险完全不同。

queryOrder是只读能力,适合第一阶段包装成Tool。AI可以用它查询订单状态、总结异常原因、给出处理建议。

updateOrderStatus是写能力,涉及真实业务状态,不能默认交给AI自动执行。

这正好呼应第1讲的结论:

text 复制代码
AI 只给建议
老系统状态不由 AI 直接修改

所以工具中心第一条规则应该是:

text 复制代码
默认只读
写操作拒绝或转人工确认

第二个问题:参数边界是什么

只读也不代表没有风险。

比如queryOrder(orderId)看起来只是查订单,但企业里至少要继续问:

text 复制代码
orderId 格式是否合法?
这个用户能不能查这个租户的订单?
一次能不能查多个订单?
能不能模糊查询?
能不能查历史归档订单?

如果参数边界不清楚,AI工具就可能从"查一个订单"滑向"批量探测数据"。

所以工具不是简单包一层函数,而是要把可接受的参数收窄:

text 复制代码
只允许明确订单号
只允许当前租户
只允许单笔查询
不允许让模型拼任意查询条件

本讲Demo为了保持简单,只演示从用户问题中提取一个订单号。但你在真实项目里要把这个思路补全成参数校验、租户校验和权限校验。

第三个问题:返回值能不能原样给模型

很多人做工具调用,只盯着"模型能不能调到API"。

但真正容易泄露数据的地方,往往在返回值。

订单对象里可能有:

text 复制代码
客户手机号
收货地址
客户姓名
支付信息
内部备注

即便工具本身是只读的,也不代表返回值可以原样给模型或前端。

所以工具中心还要管输出:

text 复制代码
敏感字段脱敏
内部字段裁剪
只返回模型完成任务所需的信息
记录哪些字段被处理过

到这里你会发现,AI工具中心不是为了"让AI多调几个接口"。它真正解决的是:

text 复制代码
AI 能调用什么
AI 能带什么参数调用
AI 调完以后能看到什么

本讲能学到什么

配套代码目录:

text 复制代码
code/spring-ai-enterprise-lab/labs/chapter02-mcp-tool-center

运行:

powershell 复制代码
.\compile-and-run.ps1

运行后可以看到两条路径:

  1. 用户问"订单有什么异常",Agent调用queryOrder只读工具。
  2. 用户要求"把订单状态改成已发货",工具中心拒绝,老系统API不会被调用。

这不是为了演示一个复杂MCP Server。它想让你先建立一个边界意识:

text 复制代码
AI 不是直接访问老系统
AI 只能通过工具中心访问被授权的能力
工具中心同时管输入、执行和输出

端到端走一遍

用户输入:

text 复制代码
帮我查询 O202606050001 这个订单现在有什么异常

第一步ToolCallingAgent收到问题。

它不是立刻去调老系统API,而是先问权限策略:

java 复制代码
if (permissionPolicy.isWriteIntent(request.getQuestion())) {
    return rejected(...);
}

第二步ToolPermissionPolicy判断这是不是写操作。

当前Demo中,下面这些词会被视为写意图:

text 复制代码
改成
修改
删除
更新
发货

第三步,如果不是写操作,Agent从问题里提取订单号:

text 复制代码
O202606050001

第四步 ,Agent选择并调用OrderQueryTool

这里要特别注意:Agent调用的是Tool,不是直接调用LegacyOrderApi

代码里的调用关系是:

text 复制代码
ToolCallingAgent
        ↓
选择 queryOrder 这个只读工具
        ↓
OrderQueryTool.query(tenantId, operatorId, orderId)
        ↓
ToolAuditService.record(...)
        ↓
LegacyOrderApi.queryOrder(orderId)
        ↓
ToolResultMasker.mask(order)

这一层包装至少做了三件事:

text 复制代码
记录是谁在什么租户下调用工具
把工具调用限定为 queryOrder 只读能力
把老系统返回值转成脱敏后的结果

这就是Tool和API的差别。API只关心"能不能调通"。Tool要关心"能不能被AI安全地使用"。

第五步OrderQueryTool记录审计:

text 复制代码
[TOOL_AUDIT] tenant=demo, operator=u1001, tool=queryOrder, detail=orderId=O202606050001, mode=READ_ONLY

第六步 ,老系统返回订单数据后,ToolResultMasker对返回值脱敏。

最终Agent拿到的是处理后的结果,而不是老系统原始对象。

为什么Agent不能直接调老系统API

很多Demo会把Tool写成一个简单函数:

java 复制代码
Order order = legacyOrderApi.queryOrder(orderId);

这在教学里很快,但在企业里很危险。

因为一旦Agent可以直接访问老系统API,你就很难回答:

text 复制代码
谁调用的?
调用了哪个 API?
传了什么参数?
有没有越权?
返回结果有没有脱敏?
如果是写操作,谁确认的?

所以中间必须有一层工具中心。工具中心不是为了增加复杂度,而是为了让AI使用系统能力时有边界。

这一层至少要做4件事:

text 复制代码
工具目录:哪些能力能被 AI 使用
权限策略:哪些请求允许,哪些请求拒绝
审计记录:谁在什么时候调用了什么
结果处理:返回值脱敏、裁剪、结构化

只读工具是第一阶段最稳的入口

本讲只实现了queryOrder。它是一个只读工具:

text 复制代码
输入:tenantId、operatorId、orderId
输出:订单状态、异常原因、脱敏后的客户信息

运行结果类似:

json 复制代码
{
  "answer": "订单 O202606050001 当前状态为 DELAYED,异常原因:仓库尚未确认出库时间。客户手机号和地址已脱敏。",
  "rejected": false,
  "rejectReason": "ALLOW_READ_ONLY_TOOL",
  "toolCalls": ["queryOrder"],
  "maskedFields": ["customerMobile", "address"]
}

观察点:

  • rejected=false:请求允许执行。
  • toolCalls=["queryOrder"]:Agent只调用了只读工具。
  • maskedFields:返回值做过脱敏。

适合第一阶段上线的能力:

text 复制代码
AI 可以查
AI 可以总结
AI 可以建议
AI 不能直接改

写操作为什么要挡住

另一个输入:

text 复制代码
把 O202606050001 订单状态改成已发货

系统返回:

json 复制代码
{
  "answer": "该问题包含写操作意图,AI 不能直接修改老系统订单状态,请转人工审批。",
  "rejected": true,
  "rejectReason": "WRITE_INTENT_REJECTED",
  "toolCalls": [],
  "maskedFields": []
}

关键是toolCalls=[]------请求在权限策略层就被挡住了,没有进入老系统API。这比"调用后发现不该改"安全得多。

写操作应该走另一条流程:

text 复制代码
AI 生成建议 → 展示影响范围 → 人工确认 → 系统执行 → 审计记录

返回值也要过边界

OrderQueryTool不直接返回LegacyOrder,而是先经过ToolResultMasker

老系统返回的:

text 复制代码
customerMobile=13812345678
address=上海市浦东新区某某路 88 号

给模型和前端的结果:

text 复制代码
customerMobile=138****5678
address=上海市浦东新区***

工具调用的安全边界,不只在调用前,也在调用后。

MCP应该怎么理解

这篇文章不展开MCP协议细节。你可以先把MCP理解成一种企业工具接入思维:

text 复制代码
把外部能力描述成工具
让 Agent 通过统一方式调用工具
工具提供者负责边界控制

更准确的理解:

text 复制代码
企业把一部分能力包装成可授权工具
AI 只能在授权范围内使用
调用过程可审计
返回结果可控制
高风险动作转人工

代码应该先看哪些类

第2讲建议先看6个类:

text 复制代码
agent/ToolCallingAgent.java     --- Agent 如何选择工具
mcp/ToolPermissionPolicy.java   --- 权限策略如何拒绝写操作
mcp/OrderQueryTool.java         --- Tool 如何包装老系统 API
mcp/ToolAuditService.java       --- Tool 调用如何记录审计
mcp/ToolResultMasker.java       --- Tool 返回值如何脱敏
legacy/LegacyOrderApi.java       --- 老系统原始 API 长什么样

核心链路:

text 复制代码
用户问题 → 权限判断 → 只读 Tool → 审计记录 → 老系统 API → 返回值脱敏 → 回答用户

企业避坑

  1. 不要让Agent直接访问老系统API --- 中间必须有工具中心做工具目录、权限策略、审计记录和返回值处理。
  2. 不要一开始就开放写操作 --- 查询、总结、解释适合第一阶段;修改、删除、审批、退款应转人工确认。
  3. 不要只校验入参,不处理返回值 --- 入参决定AI能查什么,返回值决定AI能看什么。两边都要收口。
  4. 不要把"工具调用成功"当成"企业可用" --- 企业可用还要看授权、审计、脱敏、拒绝策略和责任边界。

从 Demo 到落地,还差什么

本讲帮你建立了"API 不能直接交给 AI"的边界意识,但企业真实场景还差几步:

动态权限模型:当前 Demo 用关键词匹配判断写意图。真实项目需要基于 RBAC 的动态权限------不同角色、不同租户、不同场景,能用的 Tool 不同。关键词匹配在生产环境远远不够。

工具注册中心:企业不会只有一两个 Tool。需要一个支持动态注册、版本管理、灰度发布的工具中心,而不是硬编码在代码里。

写操作的完整人工确认流程:本讲只实现了"拒绝写操作"。真实流程是:AI 生成建议 → 展示影响范围 → 人工确认 → 系统执行 → 审计记录。这条链路会在后续工作流章节展开。

工具调用链路追踪:一次用户问题可能触发多个 Tool,企业需要完整的调用链追踪------哪个 Tool 先调、哪个后调、哪些被拒绝、总耗时多少。

如果你正在推进企业 AI 工具接入落地,后续会有完整版把这些能力整合成企业级工具中心。

小结,而是一种授权思维:

text 复制代码
老系统能力
        ↓
包装成工具
        ↓
默认只读
        ↓
调用前做权限判断
        ↓
调用中做审计
        ↓
调用后做脱敏
        ↓
写操作转人工确认

AI要接入企业系统,不是拿到更多权限,而是被放进更清楚的权限边界里。

相关推荐
❀抽抽3 小时前
证件照制作API接入指南:700+规格一键生成
大数据·网络·人工智能
Promise微笑3 小时前
绝缘油介损(油介损)测试仪的深层机理、技术演进与精准诊断策略
大数据·网络·人工智能
一只叫煤球的猫3 小时前
ThreadForge 源码解读二:一个 Task 从 submit 到完成,内部到底发生了什么?
java·后端·面试
开发者小布3 小时前
Claude Code 国内配置完整指南:通过中转 API 实现稳定访问(macOS / Linux / Windows)
人工智能
大C聊AI3 小时前
通用大模型纷纷收费,垂直场景AI工具的价值正在被重估
大数据·人工智能·机器学习·办公效率·ai 工具·智标领航·ai 辅助办公
苏州邦恩精密3 小时前
2026江苏GOM三维扫描仪定制厂家找哪家?企业数字化转型视角
人工智能·机器学习·3d·自动化·制造
python-码博士3 小时前
PyTorch 从零实现 Flow Matching:训练、采样、画图一条龙
人工智能·pytorch·python
砍光二叉树3 小时前
一文打通 AI 认知:LLM、Agent、MCP、Skill 完整体系
人工智能·llm·agent·skill·mcp
努力写A题的小菜鸡4 小时前
PyTorch 图像预处理 transforms 与 TensorBoard 可视化 (自己学习记录)
人工智能·pytorch·学习
测试仪器廖生135902563854 小时前
罗德与施瓦茨 FSP13频谱分析仪FSP30
网络·人工智能·算法