Hook 概述
AgentScope Java 使用统一事件模型,所有 Hook 都需要实现onEvent(HookEvent) 方法:
- 基于事件:所有智能体活动生成事件
- 类型安全:对事件类型进行模式匹配
- 优先级排序:钩子按优先级执行(值越小优先级越高)
- 可修改:某些事件允许修改执行上下文
支持的事件
| 事件类型 | 时机 | 可修改 | 描述 |
|---|---|---|---|
| PreCallEvent | 智能体调用前 | ✅ | 智能体开始处理之前(可修改输入消息) |
| PostCallEvent | 智能体调用后 | ✅ | 智能体完成响应之后(可修改最终消息) |
| PreReasoningEvent | 推理前 | ✅ | LLM 推理之前(可修改输入消息) |
| PostReasoningEvent | 推理后 | ✅ | LLM 推理完成之后(可修改推理结果) |
| ReasoningChunkEvent | 推理流式期间 | ❌ | 流式推理的每个块(仅通知) |
| PreActingEvent | 工具执行前 | ✅ | 工具执行之前(可修改工具参数) |
| PostActingEvent | 工具执行后 | ✅ | 工具执行之后(可修改工具结果) |
| ActingChunkEvent | 工具流式期间 | ❌ | 工具执行进度块(仅通知) |
| PreSummaryEvent | 摘要生成前 | ✅ | 达到最大迭代次数时,摘要生成之前 |
| PostSummaryEvent | 摘要生成后 | ✅ | 摘要生成完成之后(可修改摘要结果) |
| SummaryChunkEvent | 摘要流式期间 | ❌ | 摘要流式生成的每个块(仅通知) |
| ErrorEvent | 发生错误时 | ❌ | 发生错误时(仅通知) |
创建 Hook
基础 Hook
import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import io.agentscope.core.hook.PreCallEvent;
import io.agentscope.core.hook.PostCallEvent;
import reactor.core.publisher.Mono;
public class LoggingHook implements Hook {
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
if (event instanceof PreCallEvent) {
System.out.println("智能体启动: " + event.getAgent().getName());
return Mono.just(event);
}
if (event instanceof PostCallEvent) {
System.out.println("智能体完成: " + event.getAgent().getName());
return Mono.just(event);
}
return Mono.just(event);
}
}
带优先级的 Hook
public class HighPriorityHook implements Hook {
@Override
public int priority() {
return 10; // 数字越小优先级越高(默认为 100)
}
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
// 此钩子在优先级 > 10 的钩子之前执行
return Mono.just(event);
}
}
修改事件
某些事件允许修改:import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import io.agentscope.core.hook.PreReasoningEvent;
import io.agentscope.core.message.Msg;
import io.agentscope.core.message.MsgRole;
import io.agentscope.core.message.TextBlock;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
public class PromptEnhancingHook implements Hook {
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
if (event instanceof PreReasoningEvent e) {
List<Msg> messages = new ArrayList<>(e.getInputMessages());
messages.add(0, Msg.builder()
.role(MsgRole.SYSTEM)
.content(List.of(TextBlock.builder().text("逐步思考。").build()))
.build());
e.setInputMessages(messages);
return Mono.just(event);
}
return Mono.just(event);
}
}
在智能体中配置 Hook
在构建智能体时注册 Hook:import io.agentscope.core.ReActAgent;
import java.util.List;
ReActAgent agent = ReActAgent.builder()
.name("Assistant")
.model(model)
.toolkit(toolkit)
.hooks(List.of(
new LoggingHook(),
new HighPriorityHook(),
new PromptEnhancingHook()
))
.build();
Hook 示例
监控工具执行
跟踪工具调用:import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import io.agentscope.core.hook.PostActingEvent;
import io.agentscope.core.hook.PreActingEvent;
import io.agentscope.core.message.TextBlock;
import reactor.core.publisher.Mono;
public class ToolMonitorHook implements Hook {
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
if (event instanceof PreActingEvent e) {
System.out.println("调用工具: " + e.getToolUse().getName());
System.out.println("参数: " + e.getToolUse().getInput());
return Mono.just(event);
}
if (event instanceof PostActingEvent e) {
String resultText = e.getToolResult().getOutput().stream()
.filter(block -> block instanceof TextBlock)
.map(block -> ((TextBlock) block).getText())
.findFirst()
.orElse("");
System.out.println("工具结果: " + resultText);
return Mono.just(event);
}
return Mono.just(event);
}
}
监控错误
监控和处理错误:import io.agentscope.core.hook.ErrorEvent;
import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import reactor.core.publisher.Mono;
public class ErrorHandlingHook implements Hook {
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
if (event instanceof ErrorEvent e) {
System.err.println("智能体错误: " + e.getAgent().getName());
System.err.println("错误消息: " + e.getError().getMessage());
return Mono.just(event);
}
return Mono.just(event);
}
}
完整示例
查看完整的 Hook 示例: 运行示例:cd agentscope-examples/documentation/quickstart
mvn exec:java -Dexec.mainClass="io.agentscope.examples.quickstart.HookExample"
内置 JSONL 跟踪导出器
为了便于本地调试和离线排障,AgentScope Java 提供了一个内置的 JSONL 导出器:警告:JSONL 跟踪导出器会将完整的 prompt、消息、工具输入以及错误堆栈 写入本地文件。这些记录可能包含敏感用户数据、凭据或其他机密信息, 因此只能在受信任的环境中启用,并应将输出文件按敏感数据处理。
import io.agentscope.core.ReActAgent;
import io.agentscope.core.hook.recorder.JsonlTraceExporter;
import io.agentscope.core.model.Model;
import io.agentscope.core.tool.Toolkit;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
public class JsonlTraceExample {
public void run(Model model, Toolkit toolkit) throws IOException {
try (JsonlTraceExporter exporter =
JsonlTraceExporter.builder(Path.of("logs", "agentscope-trace.jsonl"))
.includeReasoningChunks(true) // 可选
.includeActingChunks(true) // 可选
.build()) {
ReActAgent agent = ReActAgent.builder()
.name("Assistant")
.model(model)
.toolkit(toolkit)
.hooks(List.of(exporter))
.build();
// 在 exporter 关闭前使用 agent
}
}
}