The Shorter Call Is the Wrong Call
Calling a speech provider directly is a handful of lines: authenticate, post the text, receive audio. Routing through a sibling is not obviously better — it adds a hop, a dependency, and a service that has to be running. On line count alone, the direct call wins.
It loses on everything the line count does not show. Producing narration is not one operation; it is four concerns bundled together, and only one of them is "send text to a provider."
- Identity resolution — a name maps to a specific voice on a specific account. That mapping is a fact about who is speaking, not a parameter.
- Normalization — what happens to the text before synthesis: how numbers are spoken, how abbreviations expand, which punctuation becomes a pause.
- The cache contract — what counts as the same request, and therefore when a previous take is returned instead of a new one.
- The provider call — the only part the direct version actually replaces.
What Two Implementations Would Do
Fork those concerns across two tools and they drift, quietly, in a way that is hard to attribute. One tool expands an abbreviation and the other spells it out. One treats a semicolon as a pause and the other doesn't. One caches on exact text and the other on normalized text, so identical-looking requests behave differently. The symptom is not a crash — it is narration that sounds subtly unlike itself depending on which tool produced it, and by the time anyone notices, both implementations have users.
This is the consumer's view of capability extraction. The usual framing is from the producer's side: pull the shared thing out, give it an owner, let callers depend on it. Standing on the caller's side, the discipline feels different — it is the daily refusal of a shorter path, and it holds only because the rule is written down as ownership rather than left as a preference.