Use stream(DeepRequest) for a cold run and resumeStream(threadId, decisions) after an approval. Both return a Flow.Publisher<DeepEvent> and finish with Completed, Interrupted, or Failed. If the configured model implements StreamingChatModel, the same stream carries incremental TextDelta events; non-streaming models still publish the remaining lifecycle events.
agent.stream(new DeepRequest("research-42", "Summarize the workspace findings."))
.subscribe(new Flow.Subscriber<DeepEvent>() {
public void onSubscribe(Flow.Subscription subscription) { subscription.request(Long.MAX_VALUE); }
public void onNext(DeepEvent event) { render(event); }
public void onError(Throwable error) { report(error); }
public void onComplete() { }
});DeepEvent makes the lifecycle observable without depending on a provider-specific event format:
| Event | Meaning |
|---|---|
TextDelta |
Incremental assistant text from a streaming model turn. |
Message |
A complete assistant model message. |
ToolCallRequested / ToolResult |
A tool call and its resulting message. |
TodosUpdated |
The durable task plan changed. |
ContextOffloaded |
A large tool result was preserved in the workspace. |
SubagentStarted / SubagentCompleted |
A delegated task started or returned its report. |
ApprovalRequested |
One or more sensitive actions need a decision. |
Completed / Interrupted / Failed |
The terminal outcome. |
For separate nested-agent observability, subscribe to agent.childStreams(). Each DeepAgentChildStream provides its own event publisher plus focused message, tool-call, output, and nested-child publishers.
Normal invoke and resume also create internal graph checkpoints. Use history(threadId) to inspect those checkpoints; a pending approval is represented as a durable graph interrupt. See context management for long-running conversation limits.