A team debate over how tools should reference content (a structured object vs. a plain "type:key" string) was settled with a controlled experiment instead of taste. Two sub-agents built the same consumer in isolation, one per format, against a shared contract and adversarial fixtures, and a third audited the equivalence. Both formats turned out equally correct, and the experiment surfaced real bugs in the library underneath, which was the more useful result.
Outcome: Both formats passed all deterministic cases (29/29 and 30/30 + 1 strict xfail) with 0 malformed refs in 14 agent runs; 3 library defects found and reproduced.
Technical detail
Design: coordinator fixed fixtures, a functional contract and common criteria first; implementers A (JSON object) and B (string) worked in separate directories without reading each other's code; an auditor ran adversarial cases. Both pinned to the same library revision (not the local checkout, not an open PR). Fixtures made the stable key, typed ref and graph record ID deliberately different, with hostile keys (:/::, Unicode, spaces, record-ID lookalikes, key equal to the type name, same key in two types, composite key).
Deterministic layer: 29 and 30 tests passed respectively, covering round-trip search→open→navigate→cite, malformed/unknown/incompatible refs, source removed after search, content change with stable identity, and a closed error vocabulary so none of them collapses into "no information".
Agent layer: 7 tasks × 2 scenarios, fresh claude -p sessions, same model, alternating order, stream-json transcripts. Round 1: 6/7 vs 7/7 round-trips, zero malformed or altered refs in 14 runs, 100% valid citations. The single failure was giving up after empty searches (BM25 AND semantics vs. Portuguese queries), not the format. Replications with a second order and a weaker model were still pending when the session ended, so the report marks them as such.
Findings owned by the library, not the format: the evidence link unit was inferred from the key by regex (a key shaped like a record ID produced a pointer to the wrong record); cite and validate_claims disagreed on whether a candidate is citeable; accepted ref shapes were inconsistent across three entry points.
Recommendation: no experimental basis to prefer either; decide on what the experiment doesn't measure (the library already speaks type:key; the object allows closed schemas), and fix the inference bug regardless.