How do you structure service catalogs for AI agents that work with local businesses?

Hi everyone,

I’m experimenting with AI agents that answer questions about local service businesses and help users find the right service based on natural language.

One challenge I’m running into is service normalization. Different businesses often describe the same service in different ways.

For example:

  • Pressure washing vs. power washing
  • Tree pruning vs. tree trimming
  • Estate cleanout vs. house cleanout
  • Debris hauling vs. junk removal

Right now I’m considering:

  • A predefined service taxonomy
  • Embeddings for semantic matching
  • Metadata filters (location, category, business type)
  • RAG for retrieving business-specific information

For those who have built similar systems:

  1. Do you normalize service names before indexing?
  2. How do you handle synonyms without creating duplicate matches?
  3. Would you rely more on embeddings, a taxonomy, or a hybrid approach?

I’d love to hear what has worked well in production.

Great problem. I’ve hit the same thing building local service agents.

Short answer: hybrid, not embeddings only.

1. Do you normalize before indexing?
Yes. I map every business listing to a canonical service_id (e.g. junk_removal, pressure_washing) and keep the original label too. Search and filter on the canonical ID; use the raw text for display and fallback recall.

2. How do you handle synonyms without duplicates?
Alias list per service ID. “Power washing” and “pressure washing” both map to pressure_washing. Each business gets tagged once per service, so you don’t get duplicate hits from different wording.

3. Taxonomy vs embeddings?
Taxonomy: what service the user actually wants (most important)
Metadata filters: location, category, etc.
Embeddings: fuzzy recall when wording is messy
RAG: business specific details (pricing, hours, policies) after you’ve narrowed candidates

Embeddings alone aren’t enough. They’ll miss obvious synonyms and sometimes blur related services (tree trimming vs tree removal).

What I’d actually build:
Parse the query → canonical service ID + location → metadata filter → vector search as fallback → RAG on the shortlist.

Biggest win for me was logging queries that didn’t map cleanly. That’s how the synonym list grows.

Happy to share a schema if helpful.

I agree with the hybrid approach, especially keeping the canonical service ID separate from the original business wording. In my experience working with local service websites, the difficult part isn’t always finding a semantic match — it’s making sure the normalized service still preserves the details that matter to the customer.

For example, two businesses may both use “junk removal,” but one may accept appliances, mattresses, and yard debris while another may have different restrictions. So I’d keep something like the canonical service ID, original label, category, location, and service-specific inclusions/exclusions as separate fields rather than relying on the normalized name alone.

I also like the idea of logging queries that don’t map cleanly. Those real queries can become a much better source for expanding the alias list than trying to predict every synonym in advance.

One thing I’d add to your pipeline is a service-scope check after normalization:

user query → canonical service → location/category filter → service scope check → vector retrieval → business-specific RAG

That extra check can prevent a semantically close match from being treated as an actual service the business provides. This seems particularly useful for local businesses where related services can have very different pricing, equipment, disposal requirements, or availability.

I’ve found it useful to keep a separate service scope reference for this reason — essentially documenting what falls under a service and what doesn’t. That gives the retrieval/RAG layer something more reliable than just the service name to work with.

Your point about tree trimming vs. tree removal is a good example of why this matters. They may be semantically close, but they shouldn’t necessarily resolve to the same service ID.

Overall, I’d also favor the hybrid model: taxonomy for identity, metadata for filtering, embeddings for recall, and RAG for the business-specific details. The query logs can then continuously improve the taxonomy and alias list.

@matthew, excellent, if this helped you can you mark the final reply as solution so this thread get’s closed.