TL;DR
The study shows that checking "one node at a time" can't see the main defects of a generated category tree. The authors replaced it with whole-tree checks: what share of leaf names repeat their ancestors' names, how varied the vocabulary is, how each level branches, and how many records land in several branches at once. These metrics are computed by a plain script, no LLM judge needed.
A typical pain point: an agent (Codex on GPT-5.x) builds a category hierarchy for customer feedback. An LLM judge checks each node separately: "the name fits the description," "the parent is correct." Everything passes at 0.97–1.00, and the tree looks professional. But almost every leaf's name is just its ancestor's name glued to one new word. On one level, each of the 158 parents has exactly one child, meaning the tree is made of "wrappers." The judge can't see this because it looks at one node at a time, and the defect exists only at the level of the whole tree.
The method: after generation, don't trust local checks; run two sets of whole-tree checks instead. The first is structural "template detectors": ancestor repetition, vocabulary diversity, a branching ceiling, absence of shared nodes. The second is "separability by team": how often a single record lands in several top-level branches.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Method Blueprint
STEP 1: Generate the tree (agent or LLM) → taxonomy.json / list of paths
STEP 2: Structural checks (no LLM judge, from the tree file):
• ancestor name repeated in the leaf name (share of leaves)
• information gain of a name = 1 − share of words already used by ancestors
• vocabulary diversity by level (unique words / all words)
• branching: how many children each parent has on each level
(flag: ≥10 parents and none with more than 3 children)
• shared nodes under several parents (how many)
STEP 3: Separability checks (requires all records to be labeled against the tree):
• leakage = share of records that land in >1 top-level branch
• record purity = share of its paths in the main branch
• modularity by leaf co-occurrence (Q>0 means branches hold together)
STEP 4: Compare with a reference or a repeat run → decide whether the tree is usable
Example in Practice
Task: A product manager at Instacart asks Claude Code to build a category tree for 3,000 app reviews: order picking, shoppers, payment, promotions, support. The result has to be split across teams. It looks great, but you can't check 800 leaves by hand. You need to find hidden defects before the tree goes into analytics.
Prompt:
Below is a category tree for reviews of a grocery delivery app. It is the path to each leaf joined with " > " (L1 > L2 > L3 > Subtopic).
Do not rate each node "good / bad." Check the tree AS A WHOLE and compute:
1. The share of leaves whose name fully contains the name of any ancestor. Give the 5 worst examples.
2. For each leaf: information gain = 1 − (number of the leaf's meaningful words already used by ancestors) / (number of the leaf's meaningful words). Give the tree-wide average.
3. Vocabulary diversity for each level: number of unique words in the level's names / total number of words in the level's names.
4. For each pair of adjacent levels: how many children each parent has (min / median / max). "Ceiling" flag: ≥10 parents and none with more than 3 children.
5. How many nodes sit under more than one parent.
Return a table, then 3–5 lines of conclusions: which systemic defects are visible (templated names, single-child chains, the same concept duplicated in different branches). If you can't compute something exactly, say so and propose a Python script.
Tree:
{tree_paths}
Result: The model returns a table with five metrics and examples of the worst leaves. In its conclusions it names systemic patterns: glued-together names, a branching ceiling, no shared nodes. On a large tree it will most likely propose a Python script. You can run it as is.
Why It Works
The weakness: an LLM judge answers local questions: "does the name fit the description." Each answer is correct, but they get aggregated into a single pass rate. Properties of the whole tree don't belong to any single node: a naming template, a rigid branching ceiling, records leaking between branches. So the judge doesn't detect them.
The strength: whole-tree metrics are computed with simple string, set and graph operations: a substring, a ratio, a child count. A script can produce them without an LLM, and they give a yes/no answer rather than an eyeball estimate. Here the LLM is just a helper that writes the script and interprets the result.
Knobs to turn: - The ceiling flag threshold (≥10 parents, ≤3 children): raise or lower it for small trees. The authors got one false alarm on a reference tree. - Which levels to check: for routing to teams look at L1–L2, for topic analytics look at the leaves. - The reference: take a vetted tree or a second run of the same generation. The metrics show the difference, not an absolute. - Tree size: a few hundred nodes are fine in chat; for thousands, ask for a script.
Prompt Template
Role: category hierarchy auditor. You do NOT rate nodes one by one.
You look for properties that are visible only across the whole tree.
<Input>
Tree: {tree_as_paths}
Number of records (if labeled): {num_records}
Reference tree for comparison (if any): {reference}
</Input>
<Checks>
1. containment = share of leaves where the full name of any ancestor (≥2 words) appears as a substring of the leaf name
2. gain(n) = 1 − |words(n) ∩ words(ancestors of n)| / |words(n)|; output the average
3. TTR(level) = unique words / all words in the level's names
4. fan-out for each pair of levels: min / median / max children;
cap-suspect if parents ≥ {parent_threshold} and none has children > {child_threshold}
5. reuse = number of nodes with more than one parent
6. (if records are labeled with paths)
leakage = share of records touching >1 top-level branch
purity = average share of a record's paths in its main branch
</Checks>
<Output>
Metrics table → 5 worst containment examples → conclusion: which defects are systemic.
If you can't compute something exactly, say so and give a Python script.
Don't write "the tree looks good" without numbers.
</Output>
Fill in: {tree_as_paths} is lines like "Delivery > Shopper > Late arrival"; {parent_threshold} and {child_threshold} default to 10 and 3.
🚀 Quick start: paste this into the chat:
Here is a template for checking a category hierarchy as a whole. Adapt it to my task: {my task: what kind of tree, what it's for}.
Ask me questions to fill in the fields.
[paste the template above]
The LLM will ask what format your tree is in, whether your records are labeled, and whether you have a reference to compare against. It needs this to figure out which checks it can compute and which it can't: leakage can't be computed without labels. It will take the pattern from the template and build a prompt or script for your data.
Limitations
⚠️ One agent harness: all the generated trees came from the same agent (Codex on GPT-5.x). Other agents and prompts may produce different defects.
⚠️ Private and limited data: two feedback datasets from two commercial products, six trees. The pattern repeated on both datasets and in every run, but the sample is small.
⚠️ The references aren't a clean control: the customer's production trees were built with checks similar to the new metrics, so their good profile is partly baked in. The most reliable comparison is between two runs of the same agent.
⚠️ Separability metrics depend on the labeling: records are classified against each tree separately, and the result depends on the quality of that classification, not just on the tree.
⚠️ The metrics catch defects; they don't prove usefulness: "no repeated ancestors" doesn't mean the tree is good. If you optimize generation for these metrics, they'll stop reflecting quality (Goodhart's law). Some numbers, like the maximum number of children, only give context, not a score. The "ceiling" threshold produces false positives.
⚠️ The paper text cuts off: the modularity formula and the separability table aren't fully visible. The separability effect relies on conclusions from the abstract and introduction.
How They Studied It
Researchers from Enterpret took two customer feedback datasets from real products (1,940 and 5,000 records). For each dataset they assembled three trees: the customer's production tree and two independent runs of the same agent on an identical task. The task described a five-level schema and a "no duplicates" rule. Everything went through ordinary LLM checks: does the name fit the description, is the parent correct, are siblings distinguishable. All six trees passed at 0.92–1.00. A deeper check of product-term coverage even preferred the generated trees over the references.
Then the authors computed whole-tree metrics, and the picture changed. In the generated trees, 97.7% to 100% of leaf names repeat an ancestor, versus 13.9% and 2.9% in the references. In one tree, all 158 parents on a level have exactly one child each. The generated trees have no shared nodes under multiple parents at all; the references have 48 and 73. When real records were routed, between a third and three quarters of records in the generated trees landed in several top-level branches, versus about a fifth for the references. Two runs of the same harness, which ordinary checks rate as equally correct, differ by 27 percentage points in cross-branch leakage. One of them splits related topics worse than a random partition.
The surprise: repeat runs of the same agent on the same task produce different trees, and local checks don't notice. The practical takeaway: node-level grading creates a false sense of reliability, so you need to measure the tree as a whole.
Adaptations and Extrapolations
Below are my own ideas inspired by the paper; the authors didn't test them.
🔧 Technique: add prohibitions to the generating agent's task → fewer templated names
In the system prompt or
CLAUDE.mdfor the agent that builds the taxonomy:Naming and structure rules: - A leaf name must not fully contain an ancestor's name. - Don't create a level where every parent has exactly one child. - If one concept belongs to several branches, make one shared node with several parents, not copies.
🔧 Technique: a self-check at the end of the task → the defect is caught before handoff
After building the tree, compute: the share of leaves that repeat an ancestor's name; the number of parents with a single child on each level; the number of nodes with several parents. If the repeat share is >30% or there's a level where everyone has one child, rebuild that level and show the metrics before and after.
Resources
- Paper: From Plausible Hierarchies to Useful Taxonomies: Evaluating Agentic Harnesses on Customer Feedback. Authors: Prabhath Chellingi, Raviraja G, Viraj Bagal (Enterpret).
- Related work cited in the paper: TnT-LLM (evaluating taxonomies with LLM judges), InsightNet (taxonomy from reviews), Newman modularity.
- Harness used: Codex, GPT-5.x; LLM judges: gpt-5.4-mini and gpt-5.5.