
1. 为什么 Java 还能做 AI Agent——打破“Java 只适合后端”的思维定式很多人看到“AI Agent”四个字第一反应是 Python、PyTorch、LangChain、LlamaIndex——这几乎成了行业默认配置。我第一次在某高校实验室看到一个用 Java 写的 Agent 调度器时也下意识皱了眉Java 启动慢、生态弱、模型加载麻烦拿什么跑推理但三个月后他们用这套系统支撑了全校 12 个院系的智能教务助手日均处理 8.6 万次多轮对话请求平均响应延迟 327msP99 稳定在 680ms 以内。那一刻我才意识到不是 Java 不行是我们长期用错了它。Java 的核心优势从来不在“写 prompt”或“调大模型 API”而在于确定性、可观察性、强类型约束和企业级工程韧性。当一个 Agent 系统要嵌入银行风控流程、医院电子病历系统或工业设备远程诊断平台时你不可能接受 Python 进程随机 OOM、GIL 导致并发卡顿、或者类型错误拖到运行时才暴露。Java 的 JIT 编译、ZGC/Shenandoah 低延迟 GC、JFRJava Flight Recorder全链路追踪、以及 Spring Boot Micrometer Prometheus 的成熟可观测栈恰恰是生产级 Agent 框架最稀缺的底座能力。关键词里没填但标题已锚定三个不可妥协的刚性需求零依赖外部 Python 环境纯 JVM、支持插件化任务编排非固定 workflow、具备状态持久化与中断恢复能力Agent 不是单次函数调用。这意味着我们不能简单套用 LangChain-Java 的翻译版 API也不能把 Spring AI 当成万能胶水——它解决不了 Agent 的“自主性”问题如何让一个 Java 对象在没有人工预设流程图的前提下根据当前目标、历史记忆、工具可用性动态生成下一步动作序列这才是 JavaManus 的设计原点。我试过三种主流路径第一种是“Python 外挂模式”用 ProcessBuilder 启动 Python 子进程跑 LLM 推理Java 做调度实测下来光是进程启动stdin/stdout 管道建立就吃掉 180~420ms且子进程崩溃会导致整个 Agent 会话中断无法恢复第二种是“JNI 绑定模式”用 JNI 调用 llama.cpp 的 C API虽然延迟压到 80ms 内但 JVM 崩溃风险陡增JFR 完全失效运维团队直接否决第三种才是 JavaManus 选择的路径LLM 仅作为决策引擎Decision Engine所有执行层Execution Layer完全由 Java 实现通过标准化协议桥接外部模型服务。换句话说JavaManus 不训练模型、不加载权重、不解析 token它只做三件事理解用户意图、规划工具调用序列、协调执行结果反馈。模型服务可以是本地 Ollama、云厂商 API、甚至 Mock Server——对 JavaManus 来说它们只是符合 OpenAI 兼容协议的 HTTP 端点。这种分层解耦带来的好处是立竿见影的某公司将其集成进原有 ERP 系统时仅需替换AIAgentConfig.modelEndpoint配置项无需修改任何业务代码某实验室用它对接自研的轻量级 RAG 引擎只需实现ToolExecutor接口的两个方法3 小时完成接入。这不是“Java 能不能做 AI”的问题而是“你是否愿意为生产环境的稳定性放弃一部分开发便利性”的取舍。JavaManus 的答案很明确宁可多写 200 行类型安全的 Builder 代码也不接受一个 runtime ClassCastException 让客服 Agent 在关键时刻失语。2. JavaManus 的四层架构为什么不用 Spring AI 或 LangChain-Java先说结论Spring AI 是优秀的 LLM 抽象层LangChain-Java 是忠实的 Python 生态平移。它们都解决了“怎么调模型”的问题但没解决“Agent 怎么思考”的问题。JavaManus 的架构设计本质上是对 Agent 核心能力的一次垂直切分——从下往上每一层只解决一个明确问题且层间契约极度精简。2.1 执行层Execution LayerJava 的主场拒绝黑盒这是 JavaManus 最厚实的一层也是它区别于所有“Java 版 LangChain”的根本。执行层不碰任何 NLP 逻辑只做三类事工具执行Tool Execution、状态管理State Management、上下文流转Context Propagation。工具执行所有外部能力必须封装为Tool接口的实现类。比如一个查天气的工具不是写个ToolMethod注解就完事而是必须显式声明public class WeatherTool implements Tool { Override public String name() { return get_weather; } Override public String description() { return Get current weather for a city. Input: {\city\: \Beijing\}; } Override public ToolSchema schema() { return ToolSchema.builder() .addStringField(city, The city name, e.g., Shanghai, true) .build(); } Override public CompletableFutureToolResult execute(ToolInput input) { // 纯 Java HTTP 调用可加熔断、重试、缓存 return weatherApiClient.getCurrentWeather(input.getString(city)) .thenApply(result - ToolResult.success(result.toJson())); } }关键点在于schema()方法——它强制要求工具提供 JSON Schema 描述输入结构。这使得上层决策引擎能静态分析工具能力边界避免传入非法参数导致 HTTP 500。而execute()返回CompletableFuture天然支持异步非阻塞一个 Agent 实例可并发调度 50 工具而不阻塞线程。状态管理Agent 的“记忆”不是靠 Redis 存字符串而是用AgentState类型安全对象。它包含conversationId: 全局唯一会话 IDUUIDturnHistory: 严格按时间序排列的Turn列表每个Turn包含userMessage,agentThought,toolCalls,toolResultsworkingMemory: 键值对形式的短期记忆如{current_order_id: ORD-789}生命周期绑定单次会话persistentMemoryRef: 指向外部存储如 PostgreSQL的引用用于跨会话长期记忆这种设计让状态变更可审计、可回滚。某次线上事故中我们通过AgentState的完整快照5 分钟内定位到是workingMemory中一个过期的支付令牌被错误复用而如果用 MapString, Object 存这个 bug 可能潜伏数周。上下文流转JavaManus 用ExecutionContext传递执行上下文它包含ThreadLocal绑定的CorrelationId、TenantId、SecurityContext。这意味着同一个 Agent 实例可安全服务于多租户场景——A 公司的财务 Agent 和 B 公司的 HR Agent 共享同一套 JVM但数据完全隔离。这是 Spring AI 默认不提供的企业级能力。2.2 规划层Planning Layer用 Java 写“思考过程”而非调用 Python 函数这是 JavaManus 最具争议也最体现设计哲学的一层。它不依赖任何 LLM 直接生成 Action而是将“规划”拆解为两个阶段阶段一意图解析Intent Parsing输入用户消息输出结构化意图对象Intentpublic record Intent( String primaryGoal, // cancel my order ListString constraints, // [order must be unshipped, refund to original payment method] OptionalString entityId // ORD-12345 ) {}这个解析由一个轻量级规则引擎驱动基于 Drools 的定制版配合少量关键词匹配和正则。为什么不用 LLM因为意图识别准确率必须 99.5%而 LLM 在固定领域如电商、客服的 zero-shot 准确率通常只有 88~93%。我们用 200 行 Java 规则覆盖了 95% 的高频意图剩余 5% 才交给 LLM 做兜底。实测下来整体准确率提升至 99.7%且规则可热更新无需重启 JVM。阶段二动作规划Action Planning拿到Intent后规划器遍历所有已注册Tool根据Tool.schema()和Intent.constraints做逻辑匹配生成ActionPlanpublic record ActionPlan( ListToolCall toolCalls, // 按执行顺序排列 boolean requiresUserConfirmation, // 是否需要用户确认如涉及扣款 Duration estimatedTime // 预估耗时用于超时控制 ) {}关键创新在于ToolCall的构造逻辑它不是简单拼接字符串而是用ToolArgumentResolver动态注入参数。例如Intent.entityId ORD-12345而CancelOrderTool的 schema 要求orderId: stringResolver 会自动将entityId映射为orderId并验证格式合法性。这避免了大量模板字符串拼接也杜绝了因字段名不一致导致的静默失败。提示规划层绝不调用任何外部网络服务。所有计算必须在毫秒级完成。我们用 JMH 基准测试确保plan(Intent)方法 P99 15ms。一旦超时立即降级为预设 fallback plan如转人工。2.3 决策层Decision LayerLLM 是“顾问”不是“老板”这是唯一与 LLM 交互的层但它被严格限制为“咨询角色”。JavaManus 的DecisionEngine接口定义极其克制public interface DecisionEngine { CompletableFutureDecision consult( String systemPrompt, ListMessage history, ListTool availableTools, String userQuery ); }注意它不接收AgentState不接收ExecutionContext不接收任何业务实体。输入只有四样东西系统指令、对话历史、可用工具列表、当前用户问题。输出Decision是一个极简对象public record Decision( String reasoning, // LLM 的思考过程用于 debug ListToolCall toolCalls, // LLM 建议调用的工具 String finalAnswer // 如果无需工具直接回答 ) {}这种设计带来三大收益可测试性你可以用 MockDecisionEngine 完全覆盖所有分支无需启动 LLM可解释性reasoning字段直接暴露 LLM 的决策逻辑方便 QA 团队审核可控性当 LLM 建议调用高危工具如delete_user_account时决策层前置拦截器可强制插入人工确认步骤而不会让 LLM 的“自信”绕过安全策略。某金融客户要求所有涉及资金的操作必须双人复核我们只在DecisionEngine的装饰器中添加了 30 行代码检查toolCalls是否含transfer_funds若是则清空toolCalls并设置finalAnswer请等待风控专员复核。这种灵活性是把 LLM 当作“主脑”的架构永远做不到的。2.4 集成层Integration Layer让 JavaManus 长进你的系统里这一层解决“怎么用”的问题。JavaManus 提供三种标准接入方式Standalone Mode内嵌 Jetty暴露/v1/agents/{id}/chatREST API适合快速验证Spring Boot Starter自动装配AIAgentServiceBean一行代码注入现有 Spring 应用Quarkus Extension编译期优化启动时间压到 120ms 内内存占用 64MB适合 Serverless 场景。最关键的集成点是AgentLifecycleListener——一个 SPI 接口允许你在 Agent 生命周期的关键节点插入钩子public interface AgentLifecycleListener { void onSessionStarted(String sessionId, AgentConfig config); void onToolCalled(String sessionId, ToolCall call, long startTimeMs); void onToolCompleted(String sessionId, ToolCall call, ToolResult result, long durationMs); void onSessionEnded(String sessionId, SessionEndReason reason); }某物流公司的监控系统正是通过实现这个接口实时捕获每个onToolCalled事件构建出全链路的“Agent 服务地图”清晰看到track_package工具调用失败率突增进而发现是第三方快递 API 的证书过期——而这一切发生在业务方收到用户投诉之前。3. 核心机制深度拆解状态机、工具路由与中断恢复JavaManus 不是简单的“Java 版本 LangChain”它的灵魂藏在三个底层机制里有限状态机驱动的会话流、基于 Schema 的工具动态路由、原子化的中断恢复协议。这三个机制共同保证了 Agent 在复杂业务场景下的鲁棒性。3.1 会话状态机为什么不用 while(true) 循环初版 JavaManus 确实用了一个while (session.isActive())循环来驱动 Agent 会话。但上线后第 3 天监控告警疯狂闪烁大量会话卡在WAITING_FOR_TOOL_RESULT状态线程堆栈显示全部阻塞在CompletableFuture.get()。根因很快定位某个天气工具因 DNS 解析失败get()调用设置了 30 秒超时而 Agent 实例配置了 100 个并发会话——瞬间 100 个线程被锁死。解决方案是引入FSMFinite State Machine。JavaManus 定义了 7 个核心状态状态触发条件下一状态超时策略IDLE新会话创建PROCESSING_USER_INPUT无PROCESSING_USER_INPUT收到用户消息GENERATING_THOUGHT或WAITING_FOR_CONFIRMATION5sGENERATING_THOUGHTLLM 返回决策EXECUTING_TOOLS或PROVIDING_ANSWER10sEXECUTING_TOOLS工具调用发起WAITING_FOR_TOOL_RESULT无由工具自身控制WAITING_FOR_TOOL_RESULT工具返回结果GENERATING_THOUGHT或PROVIDING_ANSWER30s可配PROVIDING_ANSWER生成最终回复IDLE或WAITING_FOR_USER_INPUT2sERROR_HANDLING任意环节异常PROVIDING_ANSWER错误提示3s状态迁移由StateTransitionEngine统一管理所有状态变更都走异步事件总线使用 LMAX Disruptor 实现彻底消除线程阻塞。当WAITING_FOR_TOOL_RESULT超时时引擎不杀线程而是发送ToolTimeoutEvent由监听器触发降级逻辑如返回“天气服务暂时不可用请稍后再试”并自动将状态切回WAITING_FOR_USER_INPUT。这种设计让单个 Agent 实例轻松支撑 500 并发会话CPU 占用率稳定在 35% 以下。注意状态机的所有状态、事件、迁移规则都定义在agent-fsm.yaml配置文件中支持热重载。某次大促前运营团队要求将WAITING_FOR_CONFIRMATION超时从 60 秒缩短到 15 秒我们只改了配置未动一行 Java 代码。3.2 工具路由如何让一个 Agent “学会”调用新工具传统方案是重启应用加载新Tool类。JavaManus 的答案是工具即配置路由即匹配。所有Tool实现类必须标注ToolComponent注解并在resources/META-INF/tools/下放置对应 YAML 文件# resources/META-INF/tools/weather-tool.yaml name: get_weather description: Get current weather for a city schema: type: object properties: city: type: string description: The city name required: [city] execution: className: com.example.tools.WeatherTool singleton: true # 是否单例 timeoutMs: 5000 retryPolicy: maxAttempts: 3 backoff: EXPONENTIALJavaManus 启动时扫描该目录用 SnakeYAML 解析所有 YAML反射创建Tool实例并注册到ToolRegistry。关键点在于ToolRegistry的findMatchingTools(Intent intent)方法public ListTool findMatchingTools(Intent intent) { return tools.stream() .filter(tool - matchesConstraints(tool, intent.constraints)) .filter(tool - hasRequiredFields(tool, intent)) .sorted(Comparator.comparingInt(this::matchScore)) // 按匹配度排序 .limit(3) // 最多返回 3 个候选 .collect(Collectors.toList()); }matchScore()计算逻辑包括字段名相似度Levenshtein Distance约束关键词命中数如intent.constraints含 real-time则优先选get_weather_realtime工具历史成功率来自ToolMetrics这意味着当你新增一个get_weather_forecast工具并部署新 JAR 包后Agent 无需重启下次会话自动感知新能力。某次灰度发布中我们先上线get_weather_forecast工具观察其成功率 95% 后再通过调整matchScore权重逐步将流量从旧工具切过去——整个过程对用户完全透明。3.3 中断恢复当 JVM 挂了Agent 的“记忆”还在吗这是生产环境最致命的问题。JavaManus 的答案是状态快照 增量日志 两阶段提交。状态快照Snapshot每 5 分钟或每次PROVIDING_ANSWER状态后将完整的AgentState序列化为 Protobuf存入 PostgreSQL 的agent_state_snapshots表。表结构经过极致优化CREATE TABLE agent_state_snapshots ( id VARCHAR(36) PRIMARY KEY, -- conversationId version BIGINT NOT NULL, -- 乐观锁版本号 snapshot BYTEA NOT NULL, -- Protobuf 序列化数据 created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), INDEX idx_conversation_version (id, version) );使用 Protobuf 而非 JSON序列化体积减少 62%反序列化速度快 3.8 倍。增量日志Delta Log所有状态变更如toolCalls发起、toolResults返回都以追加方式写入agent_state_logs表每条日志包含conversationId,sequenceNumber,eventType,payload。日志表按月分区冷数据自动归档到对象存储。两阶段提交2PC当 Agent 完成一次完整会话进入IDLE状态执行Prepare Phase更新agent_state_snapshots.version插入一条COMMIT类型日志Commit Phase仅当数据库事务成功才通知消息队列发送SessionCommittedEvent。恢复流程如下JVM 重启后AgentManager扫描agent_state_logs找到最新COMMIT日志若无COMMIT则从最近快照重建AgentState并重放所有COMMIT之后的日志若有COMMIT则直接加载快照忽略后续日志保证幂等。实测在模拟 JVM crash 后Agent 会话可在 1.2 秒内完全恢复用户无感知。某次数据中心断电事故中327 个进行中的 Agent 会话全部在 3 秒内无缝续上用户看到的只是“稍作思考”而非“对话已中断”。4. 从零开始搭建手把手实现一个可运行的 JavaManus Demo现在让我们把理论落地。以下是一个最小可行 Demo它能在 15 分钟内跑起来展示 JavaManus 的核心工作流。所有代码基于 JDK 17、Spring Boot 3.2、Maven 3.8。4.1 项目初始化与依赖配置创建 Maven 项目pom.xml关键依赖dependencies !-- JavaManus 核心 -- dependency groupIdcom.javamanus/groupId artifactIdjavamanus-core/artifactId version0.8.2/version /dependency !-- Spring Boot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- LLM 客户端这里用 OpenAI 兼容的本地服务-- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-open-ai/artifactId version0.32.0/version /dependency !-- 工具执行所需 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-webflux/artifactId /dependency !-- 状态持久化 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jdbc/artifactId /dependency dependency groupIdorg.postgresql/groupId artifactIdpostgresql/artifactId /dependency /dependencies注意javamanus-core是我们内部发布的框架包实际使用时需替换为你的私有仓库地址。如果你希望完全开源可将javamanus-core替换为langchain4j的相关模块但需自行补全状态机和工具路由逻辑。4.2 定义第一个工具计算器工具创建CalculatorTool.javaComponent ToolComponent // 标记为可扫描的工具 public class CalculatorTool implements Tool { Override public String name() { return calculate; } Override public String description() { return Perform basic arithmetic operations. Input: {\expression\: \2 3 * 4\}; } Override public ToolSchema schema() { return ToolSchema.builder() .addStringField(expression, The arithmetic expression to evaluate, e.g., 10 - 3 * 2, true) .build(); } Override public CompletableFutureToolResult execute(ToolInput input) { try { // 使用安全的表达式解析器避免脚本注入 String expression input.getString(expression); BigDecimal result ExpressionEvaluator.evaluate(expression); // 自研安全解析器 return CompletableFuture.completedFuture( ToolResult.success({\result\: result.toPlainString() }) ); } catch (Exception e) { return CompletableFuture.completedFuture( ToolResult.error(Calculation failed: e.getMessage()) ); } } }ExpressionEvaluator是一个关键安全组件它不使用ScriptEngineManager存在 RCE 风险而是基于 Dijkstra 双栈算法实现的纯 Java 表达式求值器仅支持 - * / ( )和数字杜绝任意代码执行。4.3 配置 LLM 决策引擎创建DecisionEngineConfig.javaConfiguration public class DecisionEngineConfig { Bean public DecisionEngine openAiDecisionEngine( Value(${llm.api.key}) String apiKey, Value(${llm.api.base-url}) String baseUrl) { OpenAiChatModel model OpenAiChatModel.builder() .apiKey(apiKey) .baseUrl(baseUrl) // 可指向本地 Ollama: http://localhost:11434/v1 .modelName(llama3) // 或 gpt-3.5-turbo .temperature(0.3) // 降低随机性提高确定性 .maxTokens(512) .logRequests(true) // 开启请求日志便于调试 .logResponses(true) .build(); // 封装为 JavaManus 的 DecisionEngine return new LangChain4jDecisionEngine(model); } }LangChain4jDecisionEngine是一个适配器它将OpenAiChatModel的chat方法转换为 JavaManus 要求的consult()签名。核心逻辑是构造 system promptpublic CompletableFutureDecision consult(...) { String systemPrompt You are an AI assistant that helps users by calling provided tools. Your job is to decide which tool to call and with what arguments. Only use the tools listed below. Do not make up tools. If no tool is suitable, answer directly. Output format: {reasoning: ..., tool_calls: [...], final_answer: ...} ; // 构建 messages包含 history 和 availableTools 描述 ListChatMessage messages buildMessages(systemPrompt, history, availableTools, userQuery); return model.chat(messages).thenApply(response - { // 解析 response.text() 为 Decision 对象 return parseDecisionFromJson(response.text()); }); }4.4 启动 Agent 服务创建AgentController.javaRestController RequestMapping(/api/agents) public class AgentController { private final AIAgentService aiAgentService; public AgentController(AIAgentService aiAgentService) { this.aiAgentService aiAgentService; } PostMapping(/{agentId}/chat) public ResponseEntityChatResponse chat( PathVariable String agentId, RequestBody ChatRequest request) { // 创建会话上下文 AgentContext context AgentContext.builder() .conversationId(request.getConversationId()) .userId(request.getUserId()) .tenantId(default-tenant) .build(); // 执行 Agent 流程 ChatResponse response aiAgentService.process( agentId, context, request.getUserMessage() ); return ResponseEntity.ok(response); } }ChatRequest和ChatResponse是标准 DTOpublic record ChatRequest( String conversationId, String userId, String userMessage ) {} public record ChatResponse( String conversationId, String agentMessage, boolean requiresConfirmation, ListToolCall pendingToolCalls ) {}4.5 运行与验证启动 PostgreSQLDocker 快速启动docker run -d --name postgres-manus -e POSTGRES_PASSWORDmanus -p 5432:5432 -v $(pwd)/pgdata:/var/lib/postgresql/data postgres:15启动本地 LLM 服务Ollamaollama run llama3修改application.ymlllm: api: key: ollama # Ollama 无需 key base-url: http://localhost:11434/v1 spring: datasource: url: jdbc:postgresql://localhost:5432/manus_db username: postgres password: manus运行 Spring Boot 应用发送测试请求curl -X POST http://localhost:8080/api/agents/math/chat \ -H Content-Type: application/json \ -d { conversationId: conv-001, userId: user-123, userMessage: What is 15 multiplied by 8? }预期响应{ conversationId: conv-001, agentMessage: The result of 15 multiplied by 8 is 120., requiresConfirmation: false, pendingToolCalls: [] }测试工具调用curl -X POST http://localhost:8080/api/agents/math/chat \ -H Content-Type: application/json \ -d { conversationId: conv-001, userId: user-123, userMessage: Calculate 2 plus 3 times 4. }此时你会看到 Agent 先返回I will calculate that for you.然后在后台调用calculate工具最终返回The result is 14.。打开日志你能清晰看到状态机从PROCESSING_USER_INPUT→GENERATING_THOUGHT→EXECUTING_TOOLS→WAITING_FOR_TOOL_RESULT→PROVIDING_ANSWER的完整流转。实操心得第一次运行时如果遇到ToolNotFoundException大概率是ToolComponent扫描路径不对。检查resources/META-INF/tools/目录是否在 classpath 下且 YAML 文件名与Tool.name()严格一致大小写敏感。我踩过的坑是 IDE 没有自动复制META-INF目录到target/classes手动mvn clean compile即可解决。5. 生产级加固可观测性、安全与性能调优一个能跑通 demo 的框架离生产可用还有巨大鸿沟。JavaManus 在真实项目中沉淀了三套加固方案它们不是“锦上添花”而是“生死攸关”。5.1 全链路可观测性从“黑盒推理”到“白盒追踪”LLM 应用最大的痛点是“不知道为什么答错”。JavaManus 将可观测性深度融入每一层JFRJava Flight Recorder深度集成启用--XX:FlightRecorder -XX:StartFlightRecordingduration60s,filenamerecording.jfr,settingsprofile。JavaManus 的AgentState和ToolCall对象被标记为FlightRecorderObjectJFR 录制中可直接看到每个会话的完整状态变迁、工具调用耗时、内存分配热点。某次性能瓶颈定位中我们发现ToolArgumentResolver的HashMap初始化容量过小导致频繁 resizeJFR 的 Allocation Profiling 直接指出了问题类和行号。Micrometer Prometheus 指标体系JavaManus 暴露了 47 个核心指标分为四类类别示例指标用途会话指标javamanus.session.active.count,javamanus.session.duration.seconds监控并发压力与会话健康度工具指标javamanus.tool.call.total{toolcalculate,statussuccess},javamanus.tool.latency.seconds{toolweather}定位慢工具与故障点LLM 指标javamanus.llm.request.total{modelllama3,statuserror},javamanus.llm.token.usage{directioninput}控制成本与评估模型质量状态机指标javamanus.fsm.transition.total{fromWAITING_FOR_TOOL_RESULT,toERROR_HANDLING}发现异常状态流转这些指标通过MeterRegistry自动注册无需额外编码。Prometheus 抓取后Grafana 看板可一键生成某客户用它实现了“工具健康度红绿灯”绿色成功率 99.5%、黄色98~99.5%、红色98%自动触发告警。OpenTelemetry 分布式追踪JavaManus 的ExecutionContext携带TraceId和SpanId所有工具调用、LLM 请求、数据库操作都自动注入 trace context。当一个会话耗时突增你可以在 Jaeger 中看到完整调用链AgentController→AIAgentService.process()→DecisionEngine.consult()→OpenAiChatModel.chat()→HttpClient.execute()→PostgreSQL.query()。每个 span 标注了agent.conversation_id,tool.name,llm.model_name等业务标签排查效率提升 5 倍以上。5.2 安全加固对抗 Prompt 注入、越权与数据泄露AI Agent 是新的攻击面。JavaManus 内置了三层防御输入净化层Input Sanitization所有userMessage在进入规划层前经过InputSanitizer处理public class InputSanitizer { // 移除控制字符、零宽空格、Unicode 方向符 public String sanitize(String input) { return input.replaceAll([\\u200B-\\u200F\\u202A-\\u202E\\uFEFF], ); } // 检测潜在 Prompt 注入模式 public boolean containsInjectionPattern(String input) { return Pattern.compile((?i)(system|role|assistant|\\?php|eval\\(|exec\\(), Pattern.DOTALL).matcher(input).find(); } }一旦检测到注入模式立即返回预设安全响应“您的消息包含不支持的格式请用自然语言描述需求。”**工具访问控制