公司动态
Agent跑通Demo后团队接手就崩:权限和日志才是Java转大模型的真门槛
聊《同样转大模型Java背景的优势和短板分别是什么》之前先说一句实在的别急着背概念先看它在真实项目里到底解决什么问题。摘要去年带团队做Agent项目Demo阶段一切顺利上线后权限校验漏了、日志查不到、调用链断了Java后端的工程习惯反而成了负资产——因为大家以为写代码和工程化是两回事。这篇文章复盘从需求评审到验收标准的一次完整过程重点讲权限、日志、可观测这三个看起来和模型无关的问题以及Java开发者怎么把优势迁移过来。目录需求评审那一刻我才意识到问题不在模型Java开发者的工程优势到底值多少权限校验从能调通API到能控制谁能调可观测性Agent的调用链怎么接进现有监控失败排查一次结果不对的完整定位链路失败原因业务错误、配置错误和环境错误的区分代码解释用Spring AI做权限守卫的取舍适用边界什么时候该用什么时候别照搬面试准备简历上怎么写项目经验总结需求评审那一刻我才意识到问题不在模型去年Q3产品提了一个需求给内部客服系统加一个Agent能查订单状态、退款进度还能调用户的历史工单。技术评审会上Java后端同学很自信——不就是调个LLM API吗结果上线第一周三个问题同时爆发1. 客服A查了客服B的客户数据权限没拦2. 用户投诉回答不一致日志里查不到是哪次调用出的问题3. Agent连续重试了47次把下游订单系统打挂了没有熔断Demo阶段没人提这些问题因为Demo的数据是写死的权限是绕过的监控是没接的。真正的问题不是模型会不会用而是工程化能力够不够。Java开发者转大模型最大的优势不是会写Prompt而是见过太多Demo能跑、上线就崩的项目。问题是这个优势能不能迁移取决于你愿不愿意承认大模型应用不是调个API就完事了。Java开发者的工程优势到底值多少先说结论Java后端的工程习惯在大模型应用里非常值钱但前提是你要把它用在正确的地方。迁移过来的优势接口设计Controller-Service-Repository的分层思维Agent里照样适用异常处理重试、熔断、降级LLM调用失败率远高于普通HTTP日志规范MDC、traceIdAgent的多步调用需要这个权限模型RBAC、OAuthAgent调用外部系统时必须接需要补齐的短板Prompt工程怎么把需求变成可复用的Prompt模板Token管理上下文窗口、压缩策略、缓存机制评估体系怎么判断回答好不好而不是代码有没有报错我第一次做Agent项目时Prompt写得像写需求文档结果模型输出不可控。后来才意识到Prompt不是写给人看的是写给模型看的要结构化、要明确约束、要有边界。权限校验从能调通API到能控制谁能调这是这次需求里最容易被忽略的一环。客服系统接Agent核心问题是Agent能调哪些数据谁可以调。Demo阶段直接用Admin账号调了所有接口上线后才发现权限漏了。我们的取舍不用自定义权限中间件直接用Spring Security的已有能力Agent调用外部系统时透传当前用户的token而不是用服务账号每个Agent工具调用前做一次权限校验而不是在数据层做验收标准1. 客服A登录查不到客服B的客户数据2. Agent返回的结果里不包含调用者的权限范围之外的数据3. 权限校验失败时返回明确的错误信息而不是模型不知道这个取舍的关键是权限校验必须放在Agent调用外部系统之前而不是之后。否则模型可能已经泄露了不该泄露的信息。可观测性Agent的调用链怎么接进现有监控Java项目里有现成的监控体系Prometheus、Grafana、ELK。Agent应用要接进去关键是traceId的传递。问题 LLM调用是异步的而且模型返回的token是流式的传统的HTTP监控看不出来。解决方案1. 每个Agent步骤打点记录输入、输出、耗时、token数2. traceId透传到下游服务用MDC绑定3. 关键决策点比如工具调用、重试单独记录日志一个具体场景 用户投诉Agent回答错误需要从日志里还原整个决策链——用户问了什么、模型想了什么、调了哪个工具、工具返回了什么、最终答案是怎么生成的。如果没有traceId贯穿全程这个排查就是不可能的。失败排查一次结果不对的完整定位链路上个月遇到一个caseAgent返回的订单状态和数据库不一致。排查过程如下现象 用户查订单ORD-2024-001Agent返回已发货但数据库显示待发货。验证动作1. 查日志traceId为abc-123找到对应请求2. 看模型输入用户问的是我的订单状态Prompt里没有指定订单号3. 看工具调用Agent调了getOrderStatus工具传入的参数是ORD-2024-0014. 看工具输出工具返回了已发货5. 查数据库该订单确实是待发货排除结果 模型没有撒谎工具也没有错。问题出在工具的实现——它查的是缓存缓存数据延迟了5分钟。根因 缓存刷新策略不对不是模型问题不是Prompt问题是基础设施问题。这个case教会我一件事Agent的问题不一定在Agent本身。排查时要分层模型层、Prompt层、工具层、数据层一层层排除。失败原因业务错误、配置错误和环境错误的区分排查完问题之后下一步是搞清楚失败原因。很多团队踩坑的地方不在于不会排查而在于不会分类——把配置错误当成模型问题或者把业务逻辑缺陷当成环境问题结果修了半天没修到点子上。我们团队总结了一套分类方法核心是把失败原因分成三类业务错误、配置错误、环境错误。业务错误是最常见的也是Java开发者最容易忽略的。这类错误的特征是代码逻辑本身没有bug但业务规则理解错了。比如权限校验的时机不对——我们在Demo阶段把权限校验放在了工具调用之后结果模型已经把敏感数据返回给用户了权限校验才执行。再比如Prompt里缺少约束条件模型自由发挥超出了预期范围。业务错误的排查方向是回到需求文档确认代码实现和业务意图是否一致。配置错误在跨团队交接时特别容易踩坑。我们的项目里出现过两次一次是生产环境的API密钥配成了测试环境的导致所有调用都返回403另一次是数据库连接池配置太小Agent高并发时直接连不上。配置错误的特征是代码没问题换个环境或者改个参数就好了。排查时要重点检查环境变量、配置文件、密钥管理尤其是CI/CD流水线里的配置注入是否正确。环境错误是最难定位的因为代码和配置看起来都没问题。典型的例子是下游服务超时、网络抖动、缓存不一致。前面提到的订单状态不一致就是环境错误——缓存延迟5分钟代码和配置都是对的但数据就是不对。环境错误的排查方向是检查依赖服务的健康状态、网络连通性、缓存策略必要时加熔断和降级。区分这三类错误的实用技巧先看错误日志里的异常类型和堆栈业务错误通常有明确的业务异常抛出配置错误会有启动失败或连接拒绝环境错误则表现为超时或间歇性失败。如果还是分不清把问题复现环境从生产切到测试能复现的是业务或配置问题不能复现的很可能是环境问题。代码解释用Spring AI做权限守卫的取舍下面是一个用Spring AI做权限校验的示例。Component public class PermissionGuardTool implements Tool { Override public String name() { return check_permission; } ToolParam(description 用户ID) private String userId; ToolParam(description 目标资源ID) private String resourceId; ToolParam(description 操作类型read/write/delete) private String action; Override public Object call(MapString, Object args) { String uid (String) args.get(userId); String rid (String) args.get(resourceId); String act (String) args.get(action); // 1. 先查用户角色 Role role roleRepository.findByUserId(uid); // 2. 再查资源权限 Permission perm permissionRepository.findByResource(rid); // 3. 校验操作权限 if (!hasPermission(role, perm, act)) { throw new PermissionDeniedException( User uid cannot act resource rid ); } return PERMISSION_GRANTED; } private boolean hasPermission(Role role, Permission perm, String action) { // 简化逻辑实际项目用Spring Security的AccessDecisionManager return perm.getRoles().contains(role.getCode()) perm.getActions().contains(action); } }代码解释1. 输入 三个参数——userId、resourceId、action。这些参数来自Agent的工具调用不是用户直接输入的。2. 核心逻辑 先查角色再查权限最后校验操作。这是一个典型的RBAC模型。3. 输出 成功返回PERMISSION_GRANTED失败抛异常。4. 异常处理 权限拒绝时抛的是业务异常不是系统异常。这样Agent可以区分模型调用失败和权限不足而不是把权限错误当成模型错误重试。取舍 我们没有用Spring Security的注解方式PreAuthorize因为Agent的工具调用是动态的注解方式不够灵活。自定义的PermissionGuardTool更可控但需要手动集成到Agent的工具链里。适用边界什么时候该用什么时候别照搬这个方案适合中大型应用有多个用户角色需要审计和合规的场景金融、医疗Agent需要调用多个外部系统这个方案不适合个人项目、内部工具权限需求简单快速验证Demo不需要生产级稳定性单用户场景没有多租户隔离需求一个判断标准 如果你的应用需要谁在什么时间做了什么操作的审计日志那就值得投入工程化。如果只是个人练习不用过度设计。面试准备简历上怎么写项目经验Java转大模型面试时最容易被问的是你做的项目和传统后端有什么区别建议的写法项目描述里不要只写用了Spring AI做了个Agent要写清楚1. 权限模型怎么设计的为什么这么设计2. 可观测性traceId怎么传递日志怎么结构化3. 失败处理重试策略、熔断机制、降级方案4. 评估方式怎么判断Agent的输出质量一个真实案例 我面试时问候选人你的Agent怎么保证权限安全他答用了Spring Security。我问具体怎么接的他答不上来。后来发现他根本没做权限校验只是加了个注解。简历建议 写你做过什么不要写你会什么。做过权限校验就写校验逻辑和取舍做过可观测性就写traceId传递方案。总结Java转大模型最大的优势是工程化能力最大的风险是把工程化能力用错地方。Demo能跑通不代表能上线。权限、日志、可观测性这三个看起来和模型无关的问题才是真正的门槛。我的建议是1. 先补Prompt工程和Token管理的基础知识2. 再用你熟悉的工程能力做权限和可观测性的设计3. 最后用评估体系验证Agent的输出质量这条路不是从Java到大模型而是从传统后端到AI原生后端。区别在于后者需要同时懂模型和工程而不是只懂其中一个。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。