Migrating from 0.7 to 0.8¶
0.8 is the API stabilisation release on the road to 1.0: it removes duplicated and legacy entry points so that the 1.0 API can be frozen. Every change below is a compile error, not a silent behaviour change, except the three flagged Behaviour.
AgentGraph run and resume options¶
Per-run settings now go through RunOptions, resume settings through ResumeOptions. invoke(ctx) and resume(runId) are unchanged.
| 0.7 | 0.8 |
|---|---|
graph.invoke(ctx, "run-42") |
graph.invoke(ctx, RunOptions.ofRunId("run-42")) |
graph.invoke(ctx, Duration.ofMinutes(5)) |
graph.invoke(ctx, RunOptions.ofTimeout(Duration.ofMinutes(5))) |
| no equivalent | RunOptions.ofRunId("run-42").withTimeout(Duration.ofMinutes(5)) |
graph.resumeWithApproval("run-42", "transfer") |
graph.resume("run-42", ResumeOptions.ofApproval("transfer")) |
graph.resume("run-42", msg) |
graph.resume("run-42", ResumeOptions.ofMessages(msg)) |
invokeStream(ctx, RunOptions) takes the same options: a streamed run can now be checkpointed, resumed and bounded by a timeout.
ErrorPolicy.RETRY_ONCE removed¶
Behaviour: RETRY_ONCE kept going to the next node when the retry failed too. RetryPolicy.once() keeps the default FAIL_FAST, so the run now stops. Add .errorPolicy(ErrorPolicy.SKIP_NODE) to keep the old behaviour.
RetryPolicy.retryOn and RetryPredicates removed¶
Retry decisions are made by the FailureClassifier only.
| 0.7 | 0.8 |
|---|---|
RetryPredicates.always() |
FailureClassifier.defaults().orElse(FailureClassifier.alwaysTransient()) |
RetryPredicates.transientIo() |
FailureClassifier.defaults() |
RetryPredicates.never() |
FailureClassifier.defaults() |
new RetryPolicy(n, base, max, mult, jitter, predicate) |
new RetryPolicy(n, base, max, mult, jitter, classifier) |
custom Predicate<Throwable> |
cause -> matches(cause) ? FailureClassification.transientFailure() : null |
Behaviour: a failure that no classifier recognises is now PERMANENT. RetryPolicy.once().withClassifier(custom) no longer retries unknown failures unless custom ends with .orElse(FailureClassifier.alwaysTransient()).
Denied tool calls no longer fail the node¶
Behaviour: in 0.7, a call refused by ToolPolicy threw ToolPolicyViolation, which Spring AI does not handle: the whole ChatClient call failed, the node failed, and the tool calls recorded so far were lost. In 0.8 the denial is a ToolExecutionException whose cause is the ToolPolicyViolation: the model receives the denial reason as the tool result and carries on, and the denied attempt stays in AgentResult.toolCalls().
If you caught ToolPolicyViolation around a tool callback, catch ToolExecutionException and read getCause(). To stop the run on a denial, route on the failed ToolCallRecord with an Edge.onResult.
Internal types no longer public¶
CheckpointDto, MessageDto, StateEntryDto, ToolCallDto and Node.AgentNode are package-private. Use CheckpointCodec and Node.of(...).
@Experimental APIs¶
AgentSquad, ParallelAgent, BudgetAwareRouter, CliAgentNode and the agentflow4j.squad.* properties are marked @Experimental: they may change in any release before and after 1.0.
New in 0.8¶
These are additions; nothing to migrate.
invokeStreamnow enforcesApprovalGate,StatePolicyand checkpoints, likeinvoke.AgentListenergainsonCheckpoint,onToolCall,onApprovalRequiredandonBudgetExceeded. See Observability.ExecutorAgent.Builder.toolProviders(...)governs MCP tools. See MCP tools.