Interface AiServiceStreamingEvent

All Known Implementing Classes:
AiServiceStreamingEvent.AbstractEvent, AiServiceStreamingEvent.AfterToolExecutionEvent, AiServiceStreamingEvent.BeforeToolExecutionEvent, AiServiceStreamingEvent.CompleteToolCallEvent, AiServiceStreamingEvent.FinalResponseEvent, AiServiceStreamingEvent.IntermediateResponseEvent, AiServiceStreamingEvent.PartialResponseEvent, AiServiceStreamingEvent.PartialThinkingEvent, AiServiceStreamingEvent.PartialToolCallEvent, AiServiceStreamingEvent.RawEvent, AiServiceStreamingEvent.RetrievedContentsEvent, AiServiceStreamingEvent.ToolCompensatedEvent

@Experimental public interface AiServiceStreamingEvent
An event emitted by the reactive stream of a non-blocking streaming AI Service — that is, an AI Service method declared to return a Flow.Publisher of AiServiceStreamingEvent.

This is a high-level, AI-Service-scoped vocabulary, deliberately distinct from the low-level, per-LLM-call ChatModelStreamingEvent emitted by StreamingChatModel.chat(dev.langchain4j.model.chat.request.ChatRequest). It covers a whole agentic interaction: the token-level chunks of every round, the tool-execution lifecycle, the distinction between an intermediate (tool-calling) round and the final answer, and retrieved RAG content. It mirrors everything the handler-based TokenStream surfaces today.

Every event carries the InvocationContext of the AI Service invocation that produced it.

Threading — do not block in onNext. Events are delivered on whichever thread produced them: the model's transport I/O worker for the token-level events, or the thread that completed a tool call for the tool-execution events. None of those belong to the subscriber, and blocking or doing heavy work in onNext stalls the interaction and, under concurrency, degrades throughput for every in-flight call — offload such work to your own Executor. The stream relays events through a bounded buffer, so a subscriber that falls far enough behind terminates with an IllegalStateException rather than buffering without limit; the size is configurable via AiServices.streamingBufferSize(int).

The set is intentionally not sealed: new event types may be introduced over time. Consumers must therefore handle unrecognized subtypes gracefully (e.g. a default branch in a type switch) rather than assume the listing below is exhaustive. Each event is a nested class (so it stays discoverable from this one entry point and namespaced against similarly-named types elsewhere, e.g. the observability ToolCompensatedEvent); an existing event grows non-breakingly by adding an accessor (and, if needed, an overloaded constructor that keeps the old one) — deliberately classes rather than records, whose canonical constructor and deconstruction patterns could not evolve without breaking callers.

Since:
1.20.0