Agent 工具调用
工具参数校验、权限检查、超时处理与幂等重试。
模型请求与工具执行
模型输出工具名称和参数,应用找到已注册的处理器,校验参数与权限后执行,再把结果关联到原调用。执行权限由应用中的登录会话等可信上下文提供。
注册工具时,确定名称、参数、返回结构和副作用范围,并将名称映射到固定处理器。账号、租户和权限从已认证会话取得,不能使用模型提交的身份字段授予权限。
调用标识用于关联模型请求和工具响应;业务操作标识用于追踪同一次业务操作及其重试。多个工具并发返回时按调用标识匹配结果,重复执行同一业务操作时沿用业务标识。
校验参数和权限
先检查字段类型、长度、允许值和未知字段,再检查目标对象是否存在、当前用户是否有权访问。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 属于其他用户 | 不泄露状态,不信任模型自报身份 |
| 响应丢失后重试写入 | 复用业务幂等键,查询既有结果或标为未知 |
| 同一键带不同请求体 | 冲突被拒绝,不能误用旧结果 |
| 工具返回超大正文或指令文本 | 限制体量,把内容当数据处理 |
| 模型反复调用失败工具 | 调用次数与时间预算终止循环 |