Summary:
When using ChatClient.prompt().toolContext(Map
I'm building a Spring AI application where:
I secure the application using Spring Security (OAuth2 resource server),
I capture the authenticated user's SecurityContext using ReactiveSecurityContextHolder.getContext(),
I pass that into .toolContext(...) when starting a chatClient.prompt() request,
Inside my tool callback (e.g., to call a backend API using WebClient), I expect that ReactiveSecurityContextHolder.getContext() would work,
However, it fails because tool execution happens on a separate thread, and .toolContext(...) is not injected into the Reactor context.
🔍 Expected Behavior:
chatClient.prompt()
.user("some prompt")
.toolContext(Map.of("securityContext", ctx)) // injected at prompt start
...
➡️ When the tool is later executed, the value "securityContext" should be available via:
ReactiveSecurityContextHolder.getContext()
Or at least be restored into the Reactor Context, so a WebClient ExchangeFilterFunction that depends on the SecurityContext can access it.
🚫 Actual Behavior:
The tool executes on another thread (e.g. boundedElastic),
The Reactor Context is empty (no security context),
ReactiveSecurityContextHolder.getContext() returns Mono.empty(),
My WebClient authentication filter fails to attach the Authorization header.