ADR-226: Gemini correlates native function-call IDs
- Status
-
Accepted
- Date
-
2026-10-10
- Authors
-
Netresearch DTT GmbH
- Amends
-
ADR-222 (private native-call correlation metadata)
Context
Google's Generate Content contract defines an optional
Function and requires its matching Function when
populated. Controlled actual response-to-request probes retain the native call
ID on replay but omit it from the result: three assertion failures, two ID-less
positive controls, zero framework errors. This is no live API acceptance claim.
The public adapter synthesizes conversation-unique ToolCall IDs. A positional join to native parts cannot preserve association when two identical parallel calls have different native IDs and the generic list is reordered. Rejecting those fresh parallel calls would reject a supported response.
A repeated actual HTTP capture-to-next-request probe also shows three valid
numeric replies refused by strict PHP integer/float equality: 1., -3.
and negative zero normalize to integers in generic argument serialization,
while their freshly captured native parts retain floats. A fractional-float
control stays accepted. These are three assertion failures with zero framework
errors on the proposed implementation, not live API failures.
Decision
Keep public synthesized ToolCall IDs and capture their association with
populated native IDs at the actual parser. Extend only the existing owned
opaque capsule with optional tool_ entries containing
tool_ and native_. Preserve native parts. Validate the owning
turn, one-to-one IDs, complete coverage and matching decoded call
names/arguments before consuming the association. The existing private
transcript prescan can carry name and native ID together; an additional public
scanner is unnecessary.
Compare existing decoded argument maps without inventing lost JSON kinds.
Treat integer/float pairs as the same numeric value only when their conversion
is exact and reversible; preserve strict separation from strings, booleans and
other scalar kinds. This permits the inherited 1. to 1 and negative-zero
to zero normalization without accepting rounded large-integer mismatches. Apply
that comparison recursively to decoded arguments for captured and legacy
associations.
Echo only that native ID in the matching Gemini result. An absent native ID stays absent; a present ID on an accepted named call must be a nonempty string. Malformed or duplicate native IDs in the tool parser or a correlated replay turn are refused with an existing typed provider exception. IDs may recur in later turns without replacing the conversation-unique public IDs. A public ID involved in native association must not identify another call in the transcript.
Older capsules without bindings may recover only an unambiguous name/decoded argument association. Never infer by position; identical parallel signatures with populated native IDs must fail before contact. Entirely ID-less and unambiguous older owned turns remain compatible. Native-parts-only and wholly ID-less replay adds no generic call-list requirement; plain signed capture does not manufacture generic calls. Always structurally validate a present binding field: those compatible turns permit only a valid empty list. A nonempty or malformed field is refused with a typed exception before contact. Extra association checks concern owned generic turns requiring native ID correlation. Foreign/generic turns provide no native binding, and other provider payloads contain no capsule or binding.
Use the same association on closing and streaming requests carrying existing state. Real encrypted SQL suspension/resume must preserve captured bindings, signatures, known Struct objects and approval identity. No public field, signature or schema change is introduced. Correlation does not establish trust, authentication or authorization, and validation must not expose native content.
Consequences
Fresh same-name/same-argument parallel calls can be answered unambiguously even when their generic list is reordered. Ambiguous older state cannot be repaired by guessing and is refused. Current decoded equality does not restore nested JSON kinds lost earlier; that finding remains open.
Actual HTTP wire and durable SQLite/MariaDB oracles, selected assertion faults, independent whole-diff review and complete gates are required. The separate decision depends on the published Struct implementation; its implementation must start from the published decision. Native text extraction, new streamed capture and live availability remain separate.