Feat: Support ttl and expireTime session-expiration options in VertexAiSessionService.createSession - #561
Open
AmaadMartin wants to merge 6 commits into
Open
Conversation
added 6 commits
July 28, 2026 23:04
…createSession Agent Engine Sessions accepts a relative ttl or an absolute expireTime when creating a session, but createSession forwarded neither, so every session got the service default lifetime. Add both as optional, Vertex-specific options via a VertexAiCreateSessionRequest that extends CreateSessionRequest, keeping the shared request type free of fields the in-memory and database services cannot honor. Specifying both throws before any RPC, matching adk-python.
…body The unit tests assert the config object handed to the SDK, which cannot catch a field the SDK converter would drop. Drive the real Sessions client against a loopback HTTP server and assert the serialized request body itself.
Drop the unit tests that re-asserted object-spread semantics with distinct keys, keep the loopback test focused on the two wire-format cases the mocked unit tests cannot reach, and stop restating the mutual-exclusion rule in three doc comments.
State the mutual-exclusion rule once, assert what the explicit-undefined case actually pins (that it does not throw, since toHaveBeenCalledWith ignores undefined properties), and answer unparseable loopback requests so an unexpected call fails an assertion instead of hanging.
createSession destructures its request, so {ttl: undefined} and an omitted ttl
produce identical locals - the case could only fail if createSession failed for
every caller. Correct the wire test's rationale to what it actually covers:
serialization by the SDK, which the mocked unit tests never reach.
The stub completes the operation inline so the poll loop never runs and only one request reaches the server; the parse-failure branch and the close-error branch could not be hit.
kalenkevich
approved these changes
Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
No existing issue.
2. Or, if no issue exists, describe the change:
Problem:
VertexAiSessionService.createSessionforwards onlysessionStateandsessionIdto the Agent Engine Sessions API, so every session is created with the service default lifetime. There is no way to create a session that expires after a relativettl(e.g.'7200s') or at an absoluteexpireTime(e.g.'2025-10-01T00:00:00Z'), even though the Agent Engine Sessions resource supports both andadk-python'screate_sessionalready exposes them. This is a cross-language parity gap.Solution:
Accept both options on the Vertex service and forward them verbatim into the
configpassed to the Sessions client:Design notes:
CreateSessionRequestis deliberately untouched.ttl/expireTimeare Agent Engine concepts;InMemorySessionServiceandDatabaseSessionServicehave no way to honor them and would silently drop them. Instead the Vertex service narrows its override to a newVertexAiCreateSessionRequest extends CreateSessionRequest, exported from@google/adkso the public signature stays documentable. Narrowing a method parameter in a subclass override typechecks under--strict(TypeScript method parameters are bivariant), so no suppression of any kind was needed anywhere in this change.createSession, mirroringadk-python'sValueError, so an invalidappNamecannot mask it and no request is issued.ttl != null/expireTime != null(loose) is intentional, matching the siblingcore/src/memory/vertex_ai_memory_bank_service.ts, which treatsnullandundefinedidentically as "not set" for these same two fields, and matchingadk-python'sis not None.@google-cloud/vertexai@1.12.0(already pinned in the lockfile) declaresttl?: stringandexpireTime?: stringonCreateAgentEngineSessionConfig, so the native SDK type is used as-is.BaseSessionService.getOrCreateSessiontakes aCreateSessionRequest, so these options cannot be passed through it. Callers who need an expiring session must callcreateSessionon aVertexAiSessionServicereference directly; wideninggetOrCreateSessionwould mean changing the base contract for services that cannot honor it....(ttl != null ? {ttl} : {})) to match the two lines above them in the same literal and to keep the outgoingconfigfree ofundefined-valued keys. The trade-off is that TypeScript does not excess-property-check spread members, so a misnamed field would compile; that is what the wire-level test below is for (verified by mutation: renaming the key tottlSecondsproduces zero compiler errors but fails both a unit test and the wire test).Reference: https://cloud.google.com/vertex-ai/generative-ai/docs/reference/rest/v1beta1/projects.locations.reasoningEngines.sessions
Testing Plan
Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes.
Unit Tests:
Added to
core/test/sessions/vertex_ai_session_service_test.ts(existingMockSessionsfixture, no new mock):forwards ttl to the create config— exact-equality on the create call, which also proves noexpireTimekey is emitted.forwards expireTime to the create config— the mirror case.throws when both ttl and expireTime are specified— asserts the message andexpect(createInternal).not.toHaveBeenCalled(), pinning the guard ahead of the RPC.Added
tests/integration/sessions/vertex_ai_session_service_test.ts, which drives the realSessionsclient against a loopback HTTP server and asserts the serialized request body ({userId, ttl}/{userId, expireTime}). Nothing is mocked; the only stub is the credential provider, since a loopback server has no identity to assert. This covers what the mocked unit tests structurally cannot: that the SDK actually serializes the two fields.New lines and branches in
createSessionare at 100% (v8 coverage over the changed file reports no uncovered statement and no partially-covered branch in the new range).Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any
necessary setup or configuration.
Against a real Agent Engine instance (billable, therefore not automated):
Then fetch the session through the Agent Engine Sessions REST API and confirm its
expireTimeis roughly two hours after itscreateTime. Repeat withexpireTime: '<future RFC 3339 timestamp>'and confirm the value is stored verbatim. Passing both at once should reject locally withCannot specify both 'ttl' and 'expireTime' simultaneously.without issuing a request.Checklist
Additional context
None.