How can I capture or listen to the event when a tool is actually invoked? I would like to wrap some custom tags or markers before and after the tool execution.
such as :
Comment From: Jisprincess
For example, I want to wrap the tool’s name, input, and output with tags. Since some tools take a long time to execute, having these tags would allow me to detect when a tool is being used and implement a waiting behavior accordingly — similar to how tool events work in CrewAI.
Comment From: YunKuiLu
You can try my solution.
Inject your custom ObservationHandler
Bean into your app.
@Configuration
public class MyObservationConfig {
@Bean
ToolExecuteObservationHandler toolExecuteObservationHandler() {
return new ToolExecuteObservationHandler(List.of(ToolCallingObservationContext.class));
}
@Slf4j
public static class ToolExecuteObservationHandler implements ObservationHandler {
private final List<Class<? extends Observation.Context>> supportedContextTypes;
public ToolExecuteObservationHandler(List<Class<? extends Observation.Context>> supportedContextTypes) {
Assert.notNull(supportedContextTypes, "SupportedContextTypes must not be null");
this.supportedContextTypes = supportedContextTypes;
}
@Override
public boolean supportsContext(Observation.Context context) {
return (context == null) ? false : this.supportedContextTypes.stream().anyMatch(clz -> clz.isInstance(context));
}
@Override
public void onStart(Observation.Context context) {
log.info("onStart: {}", context);
}
@Override
public void onEvent(Observation.Event event, Observation.Context context) {
log.info("onEvent: {} {}", event, context);
}
@Override
public void onStop(Observation.Context context) {
log.info("onStop: {}", context);
}
@Override
public void onError(Observation.Context context) {
log.error("onError: {}", context);
}
}
}
Now, you will receive onStart
, onStop
and other notifications when the tool is executed.
Comment From: Jisprincess
@YunKuiLu Thank you very much, but what I want is for the model tool invocation to be shown in the stream output, with tool usage wrapped in tags indicating the start and end of the invocation. I don't want it done via prompt constraints, because prompt constraints only summarize after the tool is finished — they don't reflect the tool invocation process in real time.
Flux<String> callTools = clientIng.build()
.prompt("what today weather is ?")
.stream()
.content();
Output example:
hello
<tool><tool name>query weather</tool name><tool content>rain</tool content></tool>
weather is rain today