Repository navigation
feat(core): add setIdProvider to control generated IDs - #1145
Collin-Park wants to merge 1 commit into
Conversation
|
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.
fbb30cd to
8fbdcdb
Compare
|
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. |
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()andnewId()(plus anIdProvidertype), same idea as adk-python'sgoogle.adk.platform.uuid. Event IDs, invocation IDs and session IDs (in-memory and database services) now all come fromnewId(). A platform can then plug in something unique per clone, for example: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 fromrandomUUID(), 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 tofeat(core)!:if you see it differently.I left the OAuth
stateinAuthHandlerand A2A message IDs onrandomUUID()on purpose, so a custom provider can never weaken a security-relevant value.Testing Plan
Unit Tests:
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. Updatedevent_test.tsfor the UUID default.npm run test:uniton Linux (Node 26): 6056 passed. The one failing file,dev/test/utils/agent_loader_test.ts, fails the same way onmainfor me.lint,format:check,docs:checkandcheck_license.share clean.ts:checkshows 5@google/adk-devtoolserrors that also show up onmainwithout a devtools build.Manual End-to-End (E2E) Tests:
Bundled this branch into a
node:24-alpineimage running a realRunner+LlmAgentwith 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 withsetIdProvider(() => `${microvmId}-${urandomHex(16)}`)installed from the/runhook.Checklist
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 dumpit,criu restoreit twice, and compare the next values. They match./dev/urandomdoesn't.