Skip to content

feat(core): add setIdProvider to control generated IDs - #1145

Open
Collin-Park wants to merge 1 commit into
google:mainfrom
Collin-Park:feat/id-provider
Open

Collin-Park wants to merge 1 commit into
google:mainfrom
Collin-Park:feat/id-provider

Conversation

@Collin-Park

Copy link
Copy Markdown

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

Problem:
Runtimes restored from one memory snapshot (Firecracker, Lambda MicroVMs, CRIU) share a copy of the same RNG state, so generated event, invocation and session IDs repeat across clones. Details and measurements are in #1144.

Solution:
Adds setIdProvider(), resetIdProvider() and newId() (plus an IdProvider type), same idea as adk-python's google.adk.platform.uuid. Event IDs, invocation IDs and session IDs (in-memory and database services) now all come from newId(). A platform can then plug in something unique per clone, for example:

// in the MicroVM /run hook, after restore
setIdProvider(() => `${microvmId}-${urandomHex(16)}`);

To be clear, this doesn't fix the collision on its own. With the default provider, clones still share the cached UUIDs. It gives platforms the hook they need to fix it.

One behavior change: default event IDs go from 8 random alphanumeric chars (Math.random) to v4 UUIDs from randomUUID(), which matches adk-python where events also go through the provider. Event ID columns are 191 chars so stored IDs fit fine, and explicit IDs (createEvent({id}), createSession({sessionId})) are untouched. I didn't mark this as breaking since the API doesn't change, but happy to switch the title to feat(core)!: if you see it differently.

I left the OAuth state in AuthHandler and A2A message IDs on randomUUID() on purpose, so a custom provider can never weaken a security-relevant value.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

New core/test/utils/id_provider_test.ts (9 tests): default UUIDs, custom provider, reset, event / invocation / in-memory session / database session IDs come from the provider, and two simulated clones with identical mocked random state still get distinct IDs. Updated event_test.ts for the UUID default.

npm run test:unit on Linux (Node 26): 6056 passed. The one failing file, dev/test/utils/agent_loader_test.ts, fails the same way on main for me. lint, format:check, docs:check and check_license.sh are clean. ts:check shows 5 @google/adk-devtools errors that also show up on main without a devtools build.

Manual End-to-End (E2E) Tests:

Bundled this branch into a node:24-alpine image running a real Runner + LlmAgent with a fake model. The app runs one turn during the image build, so the snapshot has warmed RNG state. Then I launched 5 Lambda MicroVMs from the same snapshot, and each one ran a turn with the default IDs and a turn with setIdProvider(() => `${microvmId}-${urandomHex(16)}`) installed from the /run hook.

unique across 5 MicroVMs default with provider
session IDs 1 / 5 5 / 5
invocation IDs 1 / 5 5 / 5
event IDs 2 / 10 10 / 10

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules. (none)

Additional context

CRIU repro, for anyone who wants to try it without AWS: start a Node process that calls Math.random() / crypto.randomUUID() once, criu dump it, criu restore it twice, and compare the next values. They match. /dev/urandom doesn't.

@google-cla

google-cla Bot commented Oct 24, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@Collin-Park

Copy link
Copy Markdown
Author

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

signed

Runtimes restored from one memory snapshot (Firecracker, Lambda
MicroVMs, CRIU) share a cloned RNG state, so Math.random() event IDs
and cached crypto.randomUUID() session IDs repeat across clones. With
InMemorySessionService a duplicate session ID silently replaces the
existing session.

Add setIdProvider(), resetIdProvider() and newId(), mirroring
adk-python's google.adk.platform.uuid. Event, invocation and session
IDs now come from newId(). Default event IDs change from 8 random
alphanumeric characters to v4 UUIDs, matching adk-python.
@Varun-S10 Varun-S10 self-assigned this Oct 26, 2026
@Varun-S10

Copy link
Copy Markdown
Contributor

Hi @Collin-Park, thank you for raising the PR to fix the issue. We have reviewed the code changes and it does resolve the issue. I will escalate the PR to the team to review, thank you for your patience and understanding.
Hi @kalenkevich, could you please take a look?

@Varun-S10 Varun-S10 added the needs review [Status] The PR/issue is awaiting review from the maintainer label Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs review [Status] The PR/issue is awaiting review from the maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generated IDs collide when many runtimes are restored from one memory snapshot (Firecracker / Lambda MicroVMs)

2 participants