jcardena.com Blog Building my first API that another team depended on
145 posts
EN ES

Building my first API that another team depended on

Software

A lesson from a first-generation microservice API about contracts and versioning, and why those same principles are non-negotiable for building reliable LLM agents.

Building my first API that another team depended on

An LLM agent is the most pedantic, least forgiving API consumer I have ever seen. It has zero intuition. It cannot infer intent. A field renamed from user_id to id doesn't cause a helpful compile error; it causes a silent, baffling failure in a production workflow. This unforgiving rigidity reminds me of the most important lesson of my career, learned years ago when I handed my first real API to another team.

That final 5% of the project—moving from "my code works" to "your code can depend on mine"—was where the real work began. The principles I learned through painful trial-and-error are the very same ones that separate functional AI demos from production-ready agentic systems today.

Service ExposesEndpointMobile AppConsumes StableContractLLM Agent ConsumesBrittle ToolSignature
Two Generations of API Consumers

The Contract is the Product, Then and Now

My first API's "documentation" was a Slack message. The mobile team, my first consumer, immediately hit a wall of small mismatches. I sent a user ID as an integer; their code expected a string. I included null fields; their parser broke. My product wasn't the service I had written; it was the contract, and I had failed to define it.

The core lesson landed hard: for a consumer, the implementation is an irrelevant black box. Their world is defined entirely by the interface. This principle is amplified with an LLM agent. An agent doesn't just consume a data structure; it consumes a function signature, often defined via an OpenAPI specification, which becomes part of its effective prompt. The agent's ability to reason and act depends entirely on the precision of that contract. A vague schema or a poorly defined field isn't a minor inconvenience; it's a source of catastrophic hallucinations.

Documentation as a Functional Spec

My initial defensiveness—"just read the code"—was pure hubris. Nobody wants to read your code to use your API. They want a clear manual. This led me to a mindset shift: good documentation is an act of empathy that anticipates the consumer's questions.

For an LLM agent, this empathy becomes a functional requirement. The description field for a parameter isn't just helpful context for a human; it is the primary instruction the model uses to decide *how* and *when* to use that parameter. A description like user_id: string is useless. A better one, user_id: string, the unique identifier for a user, starting with 'usr_', gives the agent the semantic understanding it needs to correctly formulate a tool call. If a question about your API is asked twice by a human, the docs have failed. If an agent misuses a tool, the tool's definition has failed.

Versioning: The Unbreakable Promise

The most painful lesson came when I renamed a field and pushed it to production. My "trivial" change broke the mobile app horribly, because I had violated the existing contract without warning. It was a hard introduction to the necessity of API versioning.

This forced us to adopt a `/v2` strategy, decoupling our release cycle from our consumers'. As Stripe's API philosophy has long demonstrated, robust versioning isn't a tax; it's a feature that enables stability and trust. For an agentic system, this is non-negotiable. You cannot simply update a tool's signature and expect all a-synchronously operating agents to adapt. You must treat every agent as an external customer running a legacy client. A breaking change requires a new tool version, allowing you to migrate agents gracefully instead of causing a fleet-wide incident.

This approach formalizes the relationship between systems, moving from implicit assumptions to explicit agreements. It's the core idea behind patterns like Consumer-Driven Contracts, where the consumer's needs codify the contract the provider must uphold. The consumer just happens to now be a piece of silicon.

The Dependency Mindset Endures

The technologies change, but the physics of dependencies do not. An LLM agent calling a tool is functionally identical to that mobile app calling my first service. Both are external systems that depend on a stable, predictable, and well-documented interface to do their job.

Building for dependency demands a shift from focusing only on implementation to obsessing over the interface. It requires craftsmanship in the boring places: the clarity of schemas, the empathy of descriptions, and the discipline of versioning. These durable patterns don't make for flashy demos, but they are what keep complex systems of agents and automation working together, long after the initial hype has faded.

SOURCESUser PromptsStreaming EventsVector StoresPROCESSING FABRICDeterministicPipelineLLM Agent CoreTool DefinitionsState ManagementSERVING LAYERVersioned ToolAPIsStructured OutputsObservabilityHooks
Architecture for Hybrid Agentic Systems

What This Means for Building Today

My takeaways from that early project have become my foundational rules for building modern systems where software, data, and AI cooperate:

  • An agent's tool definition is a production API contract. Treat its schema, parameters, and descriptions with the same rigor you would for a public-facing, versioned API.
  • Your documentation is part of the prompt. The clarity and semantic richness of your field descriptions directly influence the agent's performance and reliability. Write them for the machine.
  • Every consumer is an external consumer. Whether it's another team's service or your own fleet of agents, a formal, versioned contract is the only way to allow independent evolution.
  • Never deploy a breaking change to a tool. Always introduce a `v2`. The cost of maintaining the old contract is almost always lower than the cost of a cascading failure and the loss of trust in your platform.
JC
Juan Cardena
Enterprise Architect, Data & AI

Enterprise architect with 25 years across web, software, data, and AI. MIT CDAO ’25. Writing on agentic AI in production.