Spanish-First AI Products: Notes From Building in Panama
TL;DR
Spanish is not one language setting. A product that serves Panama, Mexico, and Spain is serving three audiences with different words, different levels of formality, and different things that sound rude. Most models are English-native and will default to a neutral, slightly foreign Spanish unless you are explicit about region and register. Users here code-switch between Spanish and English mid-sentence, and the product should follow them instead of correcting them. Spanish also tends to cost more tokens than English for the same content, which matters at volume. Voice adds another layer: speech recognition that handles a textbook accent can stumble on a Caribbean one. The fix is not a better translation step. It is treating Spanish as a first-class product: native prompts and examples, an explicit locale profile, and an eval set written and graded in Spanish by people who speak it.
The first Spanish voice prototype I built at Shining Image was technically perfect. It understood the question, found the open slot, confirmed the address, and booked the appointment. A Spanish-speaking caller in Texas tested it for us, and when she hung up she laughed and said, "It sounds like a dubbed movie."
She was right. The agent spoke a careful, neutral, slightly formal Spanish, the kind you hear in a documentary narrated for an entire continent at once. It used usted with a tone that felt more like a bank than a local cleaning business. It said things in a way nobody she knew would say them. Nothing it said was wrong. All of it was a little bit foreign.
I have lived with that comment for years now, building from Panama City. Most of the AI products I see treat Spanish as a setting: build in English, add a translation step, ship to "LATAM." That works about as well as you would expect. These are the notes I wish I had before that first prototype.
1. The Model Is a Native English Speaker Who Learned Spanish Very Well
Start with the honest framing. Most frontier models are trained on far more English than Spanish. They are very good at Spanish, genuinely, but English is their home. That shows up in small ways:
- Sentence structures that are grammatical but shaped like English.
- Literal calques: "aplicar para un trabajo" instead of "solicitar un empleo," "hace sentido" instead of "tiene sentido."
- A default toward a placeless, slightly formal register when nothing tells it otherwise.
- Less depth on regional vocabulary, especially for smaller countries like Panama.
None of this is a dealbreaker. It just means the model will not make Spanish product decisions for you. If you do not specify, it picks a default, and its default is "Spanish as written by someone careful who is not from here."
Default Spanish is nobody's Spanish
When you do not tell a model which Spanish you want, it gives you the safest average. That average is fine for a help article. In a conversation, it reads as distant, and in a voice call it sounds like a dubbed movie. Decide on a region and register on purpose.
2. Region Is a Product Decision, Not a Translation Detail
Spanish across Panama, Mexico, and Spain shares a grammar and diverges in a hundred small, important ways. A few that bite AI products:
concept Panama Mexico Spain
───────────── ────────────── ────────────── ──────────────
"you all" ustedes ustedes vosotros
"car" carro carro / coche coche
"computer" computadora computadora ordenador
"cool / great" chévere padre / chido guay / genial
"to park" parquear estacionar aparcar
Some of these are just flavor. Some are not. There are everyday Spanish words that are perfectly innocent in one country and vulgar in another. A model that defaults to Spain's casual vocabulary will occasionally say something that makes a Mexican user wince, and it will have no idea it did.
So the locale is not a string like es. It is a profile:
type SpanishLocaleProfile = {
region: "PA" | "MX" | "CO" | "ES" | "neutral-latam";
register: "tu" | "usted";
pluralYou: "ustedes" | "vosotros";
preferredTerms: Record<string, string>; // "computer" -> "computadora"
bannedTerms: string[]; // words to never use in this market
allowEnglishLoanwords: boolean; // "el meeting", "el link"
};
const panamaConsumer: SpanishLocaleProfile = {
region: "PA",
register: "tu",
pluralYou: "ustedes",
preferredTerms: { computer: "computadora", car: "carro" },
bannedTerms: [],
allowEnglishLoanwords: true,
};That profile goes into the system prompt as explicit instructions, and it also feeds the automated checks in the eval. If the product serves multiple markets, the profile is selected per tenant or per user, not hardcoded once.
3. Tú vs. Usted Is a Tone Decision, and It Has to Be Consistent
In English, "you" is "you." In Spanish, choosing tú or usted says something about the relationship before the sentence even gets going. Usted can mean respect, distance, or formality. Tú can mean warmth, closeness, or, to some users, a lack of respect.
There is no universal right answer. A consumer finance app for young professionals in Panama probably wants tú. A product used by older business owners, or anything clinical, probably wants usted, at least at first. Some products mirror the user: if they write in tú, the product follows.
What is never acceptable is mixing them. Models drift. A response that starts with usted and ends with "¿quieres que te ayude con algo más?" reads as sloppy at best and confused at worst. I check this explicitly:
import re
TU_MARKERS = [r"\bquieres\b", r"\bpuedes\b", r"\btienes\b", r"\bte\b", r"\btu\b"]
USTED_MARKERS = [r"\bdesea\b", r"\bpuede usted\b", r"\btiene usted\b", r"\ble\b", r"\bsu\b"]
def register_consistency(text: str, expected: str) -> bool:
"""Rough heuristic: flag responses that use markers of the other register."""
lowered = text.lower()
other = USTED_MARKERS if expected == "tu" else TU_MARKERS
hits = sum(1 for pattern in other if re.search(pattern, lowered))
return hits == 0It is a crude heuristic, and it misfires (le and su show up in plenty of tú sentences talking about a third person). So it flags cases for human review rather than failing them automatically. Even crude, it catches the drift that nobody notices in a demo and everyone notices in week two.
4. Users Code-Switch, and the Product Should Follow
In Panama, a lot of people move between Spanish and English inside the same sentence. "Mándame el link del meeting antes del lunch." That is not an error. It is how people talk, especially in business, tech, and anywhere close to the Canal and the banking sector.
The bad pattern is a product that "corrects" the user, answering in rigid Spanish with every loanword replaced by a dictionary equivalent, or worse, switching fully into English because it saw three English words. Both feel like the product is not listening.
My rule is simple: respond in the user's dominant language, keep the loanwords they used, and do not introduce new ones they did not. If someone writes mostly in Spanish with "meeting" and "link," the answer is in Spanish and says "meeting" and "link." If they switch fully to English mid-conversation, follow them.
Mirror, do not correct
Code-switching is a signal about who your user is, not a mistake to fix. Answer in their dominant language, reuse their loanwords, and never "translate" a user's own words back at them. Nobody likes being corrected by software.
5. Spanish Costs More Tokens
This one is quiet and shows up on the invoice. Tokenizers are generally tuned for English, and Spanish text usually needs noticeably more tokens than English text carrying the same meaning. Longer words, more inflection, accents, and less common subword patterns all add up.
For a single request, nobody cares. At volume, it matters in three places:
where the Spanish token tax shows up
─────────────────────────────────────────────────────────────
cost same feature, same traffic, higher bill per request
context long Spanish documents fill the window sooner
latency more output tokens means a longer wait to finish
I treat context as a budget for exactly this reason, and I have written about that in context windows are a budget. When you size a feature, estimate it on Spanish samples, not on the English prototype. Your margins were calculated on the wrong language otherwise.
6. Voice Makes Everything Harder
Text is forgiving. Voice is not.
Speech-to-text models have come a long way, and Whisper handled Spanish far better than what we had before. But "Spanish" in a speech dataset tends to lean toward certain accents, and Caribbean Spanish, including a lot of Panamanian speech, does things that trip recognizers up: dropped or aspirated final s, clipped endings, fast speech, and English words dropped into the middle of sentences.
In the Shining Image voice agents, the failures I saw were not dramatic. They were small and expensive: a street name misheard, a number swallowed, a "sí" that sounded like a hesitation. Each one turned a confident booking into a wrong booking. The fixes were mostly product fixes:
- Read back anything that commits. Addresses, dates, phone numbers. Always confirm out loud before acting. I wrote more about this kind of pacing in voice agents and turn-taking.
- Prefer structured answers to open ones for critical fields. "¿Es el martes o el miércoles?" beats "¿Qué día le conviene?"
- Test with real accents. Recordings from people who actually sound like your callers, not a polished studio sample.
- Make the human fallback easy and early. A caller who is repeating themselves for the third time should hear an offer to leave a message, not a fourth attempt.
Your STT eval needs your callers' accents
A speech recognizer that tests well on clear, standard Spanish can still struggle with the specific way your users talk. If your voice eval does not include recordings that sound like your actual callers, with their speed, their accents, and their background noise, you are evaluating the wrong product.
7. Translated Prompts vs. Native Prompts
The most common shortcut I see: write the prompt in English, test it in English, then translate it to Spanish (often with the model itself) and ship. The output is usually grammatical and almost always slightly off.
What I do now is split the prompt into two layers:
layer language why
────────────────────── ───────────── ─────────────────────────────────
instructions / rules English is ok models follow English instructions
very reliably
locale profile explicit region, register, terms, loanwords
few-shot examples native Spanish the model copies examples; translated
examples produce translated output
tone references native Spanish written by a native speaker from the
target region
The examples are the part that matters most. A model imitates its examples much more closely than it follows abstract style instructions. If the examples were written by a Panamanian, the output starts to sound like it is from somewhere. If they were run through a translator, the output sounds like it was too.
This is not a universal rule, and I hold it loosely. For some tasks, a fully Spanish prompt does better. That is why the decision comes from the eval, not from my preference.
8. The Eval Has to Be in Spanish Too
Everything above collapses if the eval set is in English.
I have seen it more than once: a team builds a Spanish product, writes the evaluation cases in English because that is what the team speaks, translates the inputs, and grades the outputs with an English-language rubric. The scores look great. Native speakers who use the product think it sounds robotic. Both things are true, because the eval is measuring whether the output is correct, not whether it sounds right.
A Spanish eval set needs:
- Inputs written by native speakers, including slang, typos, missing accents, and code-switching. Real users do not type "¿Podría usted indicarme...?" They type "cuanto cuesta el servicio" with no accents and no question marks.
- Automated checks for response language, register consistency, banned regional terms, and preferred vocabulary from the locale profile.
- Human grading by someone from the target region on a meaningful slice, focused on "would a person from here say this?"
That last one cannot be skipped. I have argued that the eval set is the spec. If the spec is written in English, the product will be English in disguise.
An English rubric will certify a foreign-sounding product
If the people writing and grading your eval do not speak the target language natively, your scores measure grammar and correctness, not naturalness. That is exactly the gap users feel first. Pay for native graders. It is cheaper than the churn.
The Throughline
If I had to compress all of this into one sentence: Spanish is not a translation of your product, it is a version of your product, and it needs its own decisions.
Which region. Which register. Which words never to say. How to follow users who switch languages. What the token tax does to your margins. How the recognizer handles the way people here actually speak. And an eval written and graded by people who would notice the difference.
The caller who said our agent sounded like a dubbed movie was giving me the best possible feedback. The product worked. It just did not belong to anyone. Spanish-first means building something that sounds like it belongs to the people using it.
If you are building an AI product for Spanish-speaking users and want a second pair of ears on how it sounds, reach out. I am happy to talk regions, register, and evals, in whichever language you prefer.
Frequently Asked Questions
Related Articles
AI Engineering in Panama: Building the Future From Latin America
Osvaldo Restrepo — AI engineer, PhD, and full-stack developer based in Panama — shares what it's like building production AI systems from Latin America, why Panama is an emerging tech hub, and what the AI engineering landscape looks like in Central America.
Shipping AI to Non-Technical Users: Five Things I Wish Someone Told Me
Engineering AI features for people who don't know — and shouldn't have to know — what an LLM is. Five rules earned from MILA, voice agents for small businesses, and watching kids try AI tools at Waldo's Code Lab. Say what it can't do on the first screen, hand off every output, treat latency as a feature, suggest examples that prove the boundary, and never fail with the word 'model.'
The Hard Part of Voice Agents Isn't the LLM. It's Turn-Taking.
Building voice agents for small businesses at Shining Image taught me that the language model is the easy part. The hard part is the half-second rules of human conversation: knowing when the caller has finished talking, letting them interrupt, filling silence without lying, and fitting STT, LLM, and TTS into a latency budget a human will tolerate. Endpointing, barge-in, filler acknowledgments, and what to do with people who talk over the bot.
Don't miss a post
Articles on AI, engineering, and lessons I learn building things. No spam, I promise.
Osvaldo Restrepo
Senior Full Stack AI & Software Engineer. Building production AI systems that solve real problems.