Traditional REST APIs: General-Purpose, Fixed Contracts

~10 min read

APIs are general-purpose software-to-software interfaces with a fixed contract. When that contract changes — even adding one new parameter — every integrated client has to be manually updated.

Traditional APIs (Application Programming Interfaces) are general-purpose interfaces for software-to-software communication — they're not designed with AI agents specifically in mind, and their implementations can vary greatly from one API to the next. This generality is exactly APIs' strength for their original purpose: any two pieces of software, AI-related or not, can communicate through a well-defined API contract.

That fixed contract is also exactly APIs' core limitation in an AI-agent context. This course's own worked example makes this concrete: if your weather API initially requires two parameters (location and date), every application integrating with it sends requests with exactly those two parameters, hardcoded into their integration code. If you later decide to add a third required parameter — say, a unit field for Celsius versus Fahrenheit — the API's contract changes. Every single existing user of that API now has to update their own integration code to include the new parameter, or their requests will fail, return errors, or produce incomplete results.

This isn't a flaw specific to poorly-designed APIs — it's a structural property of the fixed-contract model itself: the client and server have to agree on the exact shape of the interaction AHEAD of time, and any change to that shape requires coordinated updates on both sides. For traditional software-to-software integration, this is a well-understood, manageable trade-off — API versioning, deprecation windows, and coordinated release schedules are established practices for managing it.

But this becomes a much bigger problem specifically for AI agents that need to discover and adapt to new capabilities dynamically, without a human manually updating integration code every time a tool's interface changes even slightly. This exact gap — a fixed contract that can't communicate its own changes to clients dynamically — is precisely what MCP was designed to solve, covered in the third subtopic of this topic.

💻 Code example

import requests

def call_weather_api_v1(location: str, date: str) -> dict:
    """Traditional API: the client hardcodes the exact parameters
    the contract requires, agreed on ahead of time."""
    return requests.get(
        "https://weather.example.com/v1/forecast",
        params={"location": location, "date": date},
    ).json()

# The API adds a required 'unit' parameter in v2 — every existing
# client's hardcoded integration now breaks unless manually updated
def call_weather_api_v2(location: str, date: str, unit: str = "celsius") -> dict:
    """Every integrated client must be manually updated to include
    the new required parameter — the API can't communicate this
    change to clients dynamically; it's a coordinated, out-of-band update."""
    return requests.get(
        "https://weather.example.com/v2/forecast",
        params={"location": location, "date": date, "unit": unit},
    ).json()

💬 Deep Dive with AI

Key points

  • APIs are general-purpose software-to-software interfaces with a fixed contract, not designed with AI agents specifically in mind
  • When the contract changes (e.g. adding a required parameter), every integrated client must be manually updated
  • This is a structural property of the fixed-contract model, not a flaw specific to poorly-designed APIs
  • Well-managed for traditional integration via versioning and deprecation practices
  • Becomes a much bigger problem for AI agents needing to discover and adapt to changing capabilities without manual updates — exactly what MCP addresses