在这里插入图片描述
昨天发了AgentScope从零搭建(文末合集可看),后台收到最多的私信是同一个问题:“我照着搭出来的Agent只会聊天,一问业务就傻眼,这玩意儿能干嘛?”
你的 Agent 没有"手"。它看着像智能体,实际是个只会动嘴的客服。真正的 Agent 得能查订单、能退款、能搜资料——把业务系统接进去,这就是工具系统(Tool System)干的事。

不这么做你会踩什么坑? 我见过一个团队手写 Function Calling:自己拼 JSON Schema、自己写工具分发 if-else、自己处理参数校验,200 行起跳,换一个模型厂商全部重写。上线两周,模型漏传一个参数,订单查成别人的。这就是"裸写 Function Calling"的代价——模型行为不可控,你的代码越写越多,事故越来越多。

用 AgentScope,一个方法就是一个工具,框架自动生成 JSON Schema 暴露给大模型,大模型在推理中自主决定"调哪个、传什么"。Java 后端不需要学任何新东西。

public class OrderTools {

    @Tool(name = "order_query",
          description = "根据订单号查询订单状态和物流信息。用户问'我的订单到哪了'时使用。",
          readOnly = true, concurrencySafe = true)
    public String queryOrder(
            @ToolParam(name = "orderId", description = "订单号,ORDER开头")
            String orderId) {
        return ORDERS.getOrDefault(orderId, "未查询到订单" + orderId);
    }

    @Tool(name = "refund_apply",
          description = "为用户申请退款。用户明确要求退款时使用。",
          readOnly = false)
    public String applyRefund(
            @ToolParam(name = "orderId", description = "要退款的订单号"),
            @ToolParam(name = "reason", description = "退款原因"))
            ...
}

注册进 Toolkit,Agent 立刻"长出双手":

Toolkit toolkit = new Toolkit();
toolkit.registerTool(new OrderTools());   // 反射注册,自动生成Schema
toolkit.registerTool(new WebSearchTool()); // 高级工具:自定义权限

ReActAgent agent = ReActAgent.builder()
        .name("customer-assistant")
        .sysPrompt("你是电商客服助手。查订单用order_query,退款用refund_apply。")
        .model("dashscope:qwen-plus")
        .toolkit(toolkit)
        .build();

RuntimeContext ctx = RuntimeContext.builder()
        .userId("alice").sessionId("session-001").build();
agent.call(List.of(new UserMessage("帮我查下订单 ORDER20261001001 到哪了?")), ctx).block();

看到区别没有?你没有写一行"模型该调哪个工具"的代码。模型读到工具描述,自己决定调 order_query,自己从用户话里提取 orderId 填进去。这就是 Function Calling 的框架内实现。

什么时候要继承 ToolBase 而不是用注解? 三个信号:需要自定义权限检查(覆写 checkPermissions)、需要复杂 JSON Schema、需要异步执行。上面代码里的 WebSearchTool 就是这种——只读工具直接在 checkPermissions 里放行,生产版把参数校验和敏感词过滤放进去,这个方法是不可绕过的:

@Override
public Mono<PermissionDecision> checkPermissions(
        Map<String, Object> toolInput, PermissionContextState context) {
    return Mono.just(PermissionDecision.allow("read-only"));
}

还有一个生产必备:MCP 协议。公司里的天气服务、内部知识库、第三方 API,只要实现了 MCP,一行接入:

McpClientWrapper weather = McpClientBuilder.streamableHttp()
        .name("weather").url("[https://api.weather.com/mcp](https://api.weather.com/mcp)")
        .header("Authorization", "Bearer xxx").build();
toolkit.registerMcpClient(weather).block();

工具在 Toolkit 里的命名空间是 mcp__{server}__{tool},不会和本地工具撞名。

我的观点:工具系统是 Agent 从"demo"到"能用"的分水岭。评判一个 Agent 框架值不值得用,先看它的工具注册写起来痛不痛苦——注解一行注册的,和手拼 Schema 的,差的是整个工程效率。完整源码在公众号回复关键词领取,导入 IDEA 直接跑,README 里写了简历写法。

面试话术模板(刷题营特色模块):“我基于 AgentScope 实现了工具系统,通过 @Tool 注解把订单查询/退款申请注册进 Toolkit,模型在 ReAct 循环中自主完成工具选择与参数提取;对需要权限控制的工具继承 ToolBase 覆写 checkPermissions 做运行时校验,并支持 MCP 协议接入第三方工具。”

📦 落地资源推荐

跑AgentScope应用(含工作区+状态持久化)建议使用云服务器,能大大提高我们学习AI的效率,免除后顾之忧,新用户首年特惠,直达活动,无需求忽略。https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=fzoabro9

💡领取完整工程

找到图片上的水印,写出【AgentScope】即可。在这里插入图片描述

下期预告

单Agent会了,业务一复杂就卡壳——代码评审、搜索、写作全挤在一个上下文里互相干扰?下一期讲AgentScope子Agent编排:一个主管把任务拆给多个子Agent,独立工作区互不污染,后台任务完成自动推回。

本文属于「AgentScope生产实战」合集

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐