Skip to content

feat(interactions): add automaticContinuation to Interactions.create in the Java SDK - #138

Open
copybara-service[bot] wants to merge 1 commit into
mainfrom
copybara/995657095
Open

copybara-service[bot] wants to merge 1 commit into
mainfrom
copybara/995657095

Conversation

@copybara-service

Copy link
Copy Markdown

feat(interactions): add automaticContinuation to Interactions.create in the Java SDK

Foreground Interactions.create() calls are capped per request by the server (32k output tokens unary, 64k streaming) and stop with status="requires_continuation" plus a continuation_token. Interactions.create, AsyncInteractions.create, CreateInteractionRequest, and CreateInteractionRequestBuilder now support automaticContinuation (default true) and chain continuation hops client-side so a plain create() returns the full decode.

Request chaining:

  • Each hop after the first sends the continuation_token from the previous hop. With store enabled (default) it sets previous_interaction_id to the hop that issued the token and omits input; with store=false it resends the original input.
  • Unary foreground model calls default generation_config.max_output_tokens to 65536 when unset without mutating caller request objects (streaming uses the server's 64k default). Explicit values are never overridden.
  • Stops on completed, incomplete (token preserved for manual resumption), requires_action, failed, cancelled, a missing token, or a repeated token. Skipped for CreateAgentInteraction requests and background=true; background=true with automaticContinuation=false throws IllegalArgumentException.

Unary (stream=false) merging:

  • Hops are merged into one Interaction: steps concatenated in hop order (leading user_input steps dropped on later hops), usage counts and per-modality breakdowns summed across hops with usage.initialInputTokens taken from hop 1, id / status / continuationToken / updated from the final hop, and previousInteractionId / created / input from hop 1.
  • continuationIds lists every hop id in order, de-duplicated with any server-provided ids. Output convenience helpers (outputText, etc.) are recomputed across hop boundaries.

Streaming (stream=true):

  • Events from all hops are yielded verbatim via ContinuationEventStream (sync and async). Consumers should treat interaction.completed with status="requires_continuation" as intermediate.
  • Mid-hop transport drops (IOException / UncheckedIOException) or premature EOF resume from the latest interaction.status_update checkpoint token when no content was yielded since that checkpoint (up to 3 no-progress reconnects). SSE error events are terminal; HTTP status retries stay with RetryConfig.

Timeouts and errors:

  • Per-call timeout(Duration) on CreateInteractionRequest / builders bounds the whole create() call across hops via CallDeadline, while client-level HttpOptions.timeout and RetryConfig apply per hop.
  • A failure or timeout after progress throws ContinuationInterruptedException (getCause() chained) carrying partialInteraction(), continuationToken(), interactionId(), and continuationIds() so billed work is preserved for manual resumption. First-hop failures propagate unchanged.

Opt-out:

  • automaticContinuation=false returns the single server response untouched (no budget injection, no merging) and logs a one-time WARNING if it stops at requires_continuation without a caller-supplied continuation_token.

Tests: InteractionContinuationConformanceTest (52 sync + 28 async streaming conformance cases) and InteractionContinuationTest (whole-call timeout, builder immutability, and warning tests).

…in the Java SDK

Foreground `Interactions.create()` calls are capped per request by the server (32k output tokens unary, 64k streaming) and stop with `status="requires_continuation"` plus a `continuation_token`. `Interactions.create`, `AsyncInteractions.create`, `CreateInteractionRequest`, and `CreateInteractionRequestBuilder` now support `automaticContinuation` (default `true`) and chain continuation hops client-side so a plain `create()` returns the full decode.

Request chaining:
- Each hop after the first sends the `continuation_token` from the previous hop. With `store` enabled (default) it sets `previous_interaction_id` to the hop that issued the token and omits `input`; with `store=false` it resends the original `input`.
- Unary foreground model calls default `generation_config.max_output_tokens` to 65536 when unset without mutating caller request objects (streaming uses the server's 64k default). Explicit values are never overridden.
- Stops on `completed`, `incomplete` (token preserved for manual resumption), `requires_action`, `failed`, `cancelled`, a missing token, or a repeated token. Skipped for `CreateAgentInteraction` requests and `background=true`; `background=true` with `automaticContinuation=false` throws `IllegalArgumentException`.

Unary (`stream=false`) merging:
- Hops are merged into one `Interaction`: `steps` concatenated in hop order (leading `user_input` steps dropped on later hops), `usage` counts and per-modality breakdowns summed across hops with `usage.initialInputTokens` taken from hop 1, `id` / `status` / `continuationToken` / `updated` from the final hop, and `previousInteractionId` / `created` / `input` from hop 1.
- `continuationIds` lists every hop id in order, de-duplicated with any server-provided ids. Output convenience helpers (`outputText`, etc.) are recomputed across hop boundaries.

Streaming (`stream=true`):
- Events from all hops are yielded verbatim via `ContinuationEventStream` (sync and async). Consumers should treat `interaction.completed` with `status="requires_continuation"` as intermediate.
- Mid-hop transport drops (`IOException` / `UncheckedIOException`) or premature EOF resume from the latest `interaction.status_update` checkpoint token when no content was yielded since that checkpoint (up to 3 no-progress reconnects). SSE `error` events are terminal; HTTP status retries stay with `RetryConfig`.

Timeouts and errors:
- Per-call `timeout(Duration)` on `CreateInteractionRequest` / builders bounds the whole `create()` call across hops via `CallDeadline`, while client-level `HttpOptions.timeout` and `RetryConfig` apply per hop.
- A failure or timeout after progress throws `ContinuationInterruptedException` (`getCause()` chained) carrying `partialInteraction()`, `continuationToken()`, `interactionId()`, and `continuationIds()` so billed work is preserved for manual resumption. First-hop failures propagate unchanged.

Opt-out:
- `automaticContinuation=false` returns the single server response untouched (no budget injection, no merging) and logs a one-time `WARNING` if it stops at `requires_continuation` without a caller-supplied `continuation_token`.

Tests: `InteractionContinuationConformanceTest` (52 sync + 28 async streaming conformance cases) and `InteractionContinuationTest` (whole-call timeout, builder immutability, and warning tests).
PiperOrigin-RevId: 995657095
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant