Agent 工具调用

Java / AI Agent / 可靠性2026.09.148 分钟阅读

工具参数校验、权限检查、超时处理与幂等重试。

模型请求与工具执行

模型输出工具名称和参数,应用找到已注册的处理器,校验参数与权限后执行,再把结果关联到原调用。执行权限由应用中的登录会话等可信上下文提供。

注册工具时,确定名称、参数、返回结构和副作用范围,并将名称映射到固定处理器。账号、租户和权限从已认证会话取得,不能使用模型提交的身份字段授予权限。

调用标识用于关联模型请求和工具响应;业务操作标识用于追踪同一次业务操作及其重试。多个工具并发返回时按调用标识匹配结果,重复执行同一业务操作时沿用业务标识。

校验参数和权限

先检查字段类型、长度、允许值和未知字段,再检查目标对象是否存在、当前用户是否有权访问。JSON Schema 校验通过后,仍需做权限检查。

import java.util.Map;

public class TicketTool {
    record Ticket(String owner, String status) {}
    record Result(boolean ok, String code, String status) {}
    private static final Map<String, Ticket> DATA = Map.of(
        "T-42", new Ticket("demo-user", "OPEN"));

    static Result lookup(String id, String authenticatedUser) {
        if (id == null || !id.matches("T-[0-9]{1,8}")) {
            return new Result(false, "INVALID_ARGUMENT", null);
        }
        Ticket ticket = DATA.get(id);
        if (ticket == null || !ticket.owner().equals(authenticatedUser)) {
            return new Result(false, "NOT_FOUND", null);
        }
        return new Result(true, "OK", ticket.status());
    }

    public static void main(String[] args) {
        System.out.println(lookup("T-42", "demo-user"));
        System.out.println(lookup("T-42", "other-user"));
        System.out.println(lookup("../secret", "demo-user"));
    }
}

将示例保存为 TicketTool.java,使用 Java 21 运行。工单保存在内存中,模型只提交 id,执行器从可信会话注入 authenticatedUser。工单不存在或无权访问时,都返回 NOT_FOUND,避免泄露其他用户的工单状态。

返回结果只保留成功标志、错误码和所需状态。接入 JSON 解析与序列化时,拒绝未知字段、错误类型和超长输入。

参数错误需要修正输入,授权失败不能靠重试解决。临时服务故障则可以按操作语义有限重试,因此错误码要能区分这些情况。

超时与重试

Java 21 HttpClient 设置连接超时,HttpRequest 设置请求超时。执行器还要限制整轮任务的时长和调用次数,防止多次请求拖住整个任务。

// Java 21:HTTP 适配器中的配置片段
var client = java.net.http.HttpClient.newBuilder()
    .connectTimeout(java.time.Duration.ofSeconds(2))
    .build();
var request = java.net.http.HttpRequest.newBuilder(
        java.net.URI.create("https://example.com/status"))
    .timeout(java.time.Duration.ofSeconds(5))
    .GET().build();

超时后,写入可能已经提交,只是响应丢失;取消本地等待也不会自动回滚远端。因此要区分成功、失败和结果未知。遇到未知结果,先按业务操作标识查询。

只读请求可以在时间预算和限流允许的范围内重试。写操作重试时复用同一幂等键,服务端按租户、操作类型和键建立唯一约束,保存请求摘要、状态和结果。同一键带来不同请求内容时,返回冲突。

幂等记录与实际副作用必须具有一致的提交关系。同库操作可放入同一事务;跨系统操作需要下游幂等支持、可靠任务记录或补偿设计。单纯先查询键是否存在再执行,会在并发下产生竞态;进程内缓存也无法覆盖重启和多实例场景。

需要人工批准的写操作,应展示具体参数和作用范围。参数变化后重新批准,执行前再次检查权限。

返回结果与排查故障

工具响应经过大小限制和结构校验后再交给模型,并通过调用标识匹配请求。工单正文、网页和日志都是外部数据,其中的指令不能赋予工具额外权限。

日志通过业务操作标识和调用标识串起各次尝试,记录工具名、耗时、错误码和最终状态,省去无关的敏感正文。预算耗尽或只完成一部分时,在结果里列出尚未确认的操作。

案例应观察到的行为
id 格式错误或额外参数拒绝执行,返回可识别的参数错误
合法 id 属于其他用户不泄露状态,不信任模型自报身份
响应丢失后重试写入复用业务幂等键,查询既有结果或标为未知
同一键带不同请求体冲突被拒绝,不能误用旧结果
工具返回超大正文或指令文本限制体量,把内容当数据处理
模型反复调用失败工具调用次数与时间预算终止循环
— 本页完 —
← 返回文章列表

搜索内容

输入关键词搜索文章、笔记与随笔。