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 :

findPeopleBen

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