UUIDs are not great for agent use

but not necessarily for the reasons I thought

I set out to experiment whether using UUIDs in my agent's results would be affected by using these long IDs in the agent's workflow. I already had a suspicion these IDs would be problematic given how many tokens a UUID (~20 tokens, equivalent to a short-ish sentence) represents. I also saw this blog quantify just how much of an impact UUIDs had on agent performance, and I also was aware of this project that attempted to shrink the number of tokens of an ID. LLMs have also traditionally been bad at referencing things buried in the middle of their context window, which surely would be (unnecessarily) more complicated with complex IDs.

Pasted image 20260629225746

ChatGPT's interpretation of UUID tool calling

The problem was that up until now, the vibes of using UUIDs were fine. In using frontier models to prove a functional system, I never noticed an LLM mess up because of UUIDs being returned and passed around — no weird data or funky logs. Just like Simon Willison had indicated LLMs are getting better at following instructions, I've been having the same feeling about using UUIDs and how the frontier LLMs are getting quite good at using them in tools...I sure hope they are, as I am building a whole bunch of stuff on the assumption they can (eventually?) handle this effortlessly.

However, with Codex at my disposal I set it to try to build me some experimental conditions to test the hypothesis. We generated a deterministic employee directory with employee, manager, position, team, app, and role IDs. The agent had to call tools using exact IDs. We tested different ID types and measured how well the agent performed with each.

Results

Below is the results summary for gpt-5.4-nano:

ID strategy Correct Accuracy Invalid IDs Wrong ID values Cost
Raw UUID 11/20 55% 4 5 $0.2052
Integer remap 19/20 95% 0 1 $0.0752
EMP-00001 typed sequence 17/20 85% 0 2 $0.0886
Readable hash 12/20 60% 0 9 $0.1054

The more complex an ID, the worse the agent performed.

Why not compare gpt-5.5? It got everything right, regardless of the ID type (it also cost sooo much more to run). This was annoying, and I am sure this is too basic an experiment to test this frontier model thoroughly, but this was an interesting observation in its own right - not that it got it right, but weaker (and cheaper) models are impacted by the choice of ID, and these are the models we eventually want to use.

Bias Disclosure

While this was happening, I decided to implement the human-agent readable external identifier in my CRM app. I knew the result of the experiment (classic experimental bias) - it just made too much sense that an LLM will inevitably trip up on passing UUIDs to tools. So today was spent performing the public identifier boundary migration to expose public_ref on all agent-facing tables. I ran (and guided) the experiment towards demonstrating the poorer performance of UUIDs - a terrible scientific mindset. I also only took a cursory glance at the experimental code. However, I still learnt a bunch — see below. I just wouldn't quote this as any definitive evidence.

Public Refs are a good idea

Putting my poor experimental method aside, what I didn't appreciate was the cost impact, both directly (cost of UUID tokens) and indirectly (less confident using weaker models using UUIDs). Assuming even if the frontier models are superhuman at referencing the right UUID, using more readable and smaller IDs helps with 3 things:

  1. Easier for us (humans) to troubleshoot
  2. Token (and thus cost) effective
  3. More confident using weaker-but-cheaper models that do struggle using UUIDs, which is the ultimate goal - to use cheaper models within this CRM harness

If the public ref has a prefix like ACCT-, these typed prefixes also enable simple runtime validation to catch wrong-type tool arguments.

And depending on how you build the app, you don't even need to replace these UUIDs. If all of your database interactions and tool calls go through strictly defined functions, those functions become the boundary, meaning they expose the public ref to the agent while UUIDs stay internal as primary keys essential for preserving referential integrity.