Command Palette

Search for a command to run...

Hectal
PHASE 2Beginner ~22 min· topic 5 of 9

Topic 2.5

SDKs: What They Add

In one line

An SDK is a library that wraps the HTTP request for you: it builds the body, retries safe failures, parses the reply into typed objects and adds streaming helpers. Most providers copy the OpenAI shape, Anthropic uses its own, and frameworks add a common layer on top.

Think of it like this

A travel agent. You could book flights yourself by calling each airline and filling in each airline's forms. The agent knows the forms, retries when a line is busy, and hands you one tidy ticket. But you still pay the airline, and if the agent is wrong or slow you need to know what they did. An SDK is the agent: convenient, and worth understanding.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

SDK
Software development kit: a library that wraps an API so you call functions instead of building raw requests.
OpenAI-compatible API
A server that accepts the OpenAI chat-completions request shape, so OpenAI's SDKs work with it by changing the base URL.
Messages API (Anthropic)
Anthropic's request shape: top-level system, required max_tokens, reply content as a list of blocks.
Base URL
The start of the API address, for example https://api.groq.com/openai/v1. Changing it points the same code at another server.
Adapter
A small piece of code that converts one provider's shape into your own common shape.
Framework
A larger library (Vercel AI SDK, Spring AI, LangChain4j) with one interface over many providers and extra helpers.
Retry
Sending a failed request again. SDKs do it automatically for safe errors.

Step by step

01Step 1: write the call by hand twice

For two providers you would write two request builders and two reply parsers. The example's build_body has one branch per style, and parse returns the same four values for both: text, stop reason, input tokens and output tokens.

02Step 2: compare the two request bodies

Run the example and read the two request lines. The OpenAI style puts the system text in the messages list; the Anthropic style has a top-level system and requires max_tokens. Same question, different JSON.

Step 2: compare the two request bodiesdiagram
Rendering diagram…

03Step 3: add retries

The fake OpenAI-style server answers 503 (overloaded) on the first attempt. The client sees a retryable status, tries again and succeeds, and retries=1 shows it happened. A real SDK waits between attempts and honours Retry-After; Topic 6.8 builds that properly.

04Step 4: normalise the stop reason

end_turn and stop mean the same thing; max_tokens and length mean the same thing. Mapping them to one vocabulary once, in the adapter, keeps the rest of the code free of provider names.

05Step 5: meet the real SDKs

The blocks after the example show the official openai SDK (with a Groq base URL), LangChain4j for Java, the Anthropic SDK, and the Vercel AI SDK and Spring AI. Read each and find the parts you built: model, messages, limit, reply text, usage.

06Step 6: decide, then isolate

Choose an SDK, a framework or plain HTTP by your needs, then hide the choice behind a small interface of your own (Topic 2.8). Replacing a library then touches one file.

Try it yourself

  1. 1

    Predict the retry

    Before running, predict the retries value in each of the two reply lines. Then set max_retries to 0 for the OpenAI-style client. What happens, and which exception type do you see?

  2. 2

    Add a third provider

    Add a style "mini" whose reply is {"text":"Hello!","done":true}. Extend fake_send and parse so the client prints the same two lines for it. Notice how few places change.

  3. 3

    Map the SDK to the example

    Take one of the SDK blocks and label each line with the part of the example it replaces: body building, headers, retries, parsing.

Code & diagrams

What an SDK does: bodies, retries and one reply shape New tab

A hand-built mini SDK over two fake providers. Real SDKs do the same jobs with more care.

Sign in to run this example in your browser.

Expected output

openai request: {"model":"some-model","messages":[{"role":"system","content":"Be brief."},{"role":"user","content":"Hi"}],"max_tokens":20}
openai reply:   text=Hello! stop=stop in=12 out=3 retries=1
anthropic request: {"model":"some-model","max_tokens":20,"system":"Be brief.","messages":[{"role":"user","content":"Hi"}]}
anthropic reply:   text=Hello! stop=stop in=11 out=3 retries=0
OpenAI SDK, with any compatible providerpython

Not run here. Python and JavaScript use the official openai package; Java shows LangChain4j. Check each library's documentation for the current version.

# pip install openai      (the official OpenAI SDK; it also talks to any OpenAI-compatible server)
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://api.groq.com/openai/v1",  # leave out for OpenAI itself
    api_key=os.environ["GROQ_API_KEY"],         # from the environment (Topic 2.4)
    timeout=30,                                  # seconds
    max_retries=2,                               # the SDK retries connection errors, 408, 409, 429 and 5xx for you
)
response = client.chat.completions.create(
    model="openai/gpt-oss-20b",
    messages=[{"role": "system", "content": "Be brief."}, {"role": "user", "content": "Hi"}],
    max_tokens=300,  # OpenAI's own newer models expect max_completion_tokens instead (max_tokens is deprecated there)
)
print(response.choices[0].message.content)
print(response.choices[0].finish_reason, response.usage.total_tokens)
Anthropic Messages APIpython

Not run here. Use a model name from Anthropic's current model list. The Java tab uses plain HTTP.

# pip install anthropic      (the official Anthropic SDK)
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment
message = client.messages.create(
    model="<a model name from Anthropic's model list>",
    max_tokens=300,                       # required in this API
    system="Be brief.",                   # a top-level field, not a message
    messages=[{"role": "user", "content": "Hi"}],
)
print(message.content[0].text)            # content is a list of blocks (text, tool_use, ...)
print(message.stop_reason, message.usage.input_tokens, message.usage.output_tokens)
Framework SDKs: Vercel AI SDK and Spring AIpython

Not run here. The Vercel AI SDK is for JavaScript and TypeScript, Spring AI for Java.

# These two framework SDKs exist for JavaScript (Vercel AI SDK) and Java (Spring AI).
# In Python the openai package (first block above) or the provider's own SDK is the usual choice.
# Python framework libraries (for example LangChain) wrap the same HTTP calls and are covered with agents in the coming course.

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Retry a request that can never succeed

In the Python example change the set RETRYABLE to include 400, and make fake_send always return 400 for the OpenAI style (replace its body with return 400, compact({"error": {"message": "bad request"}})). Add a try: / except ApiError as e: around the call that prints "failed after " + str(client.retries) + " retries: " + str(e) and then does continue.

terminal
$ Run
── what you'll see ──
failed after 2 retries: HTTP 400
anthropic request: {"model":"some-model","max_tokens":20,"system":"Be brief.","messages":[{"role":"user","content":"Hi"}]}
anthropic reply: text=Hello! stop=stop in=11 out=3 retries=0

Myth vs fact

Myth

You must use an SDK to use a model.

Fact

An SDK is a convenience over a plain HTTP call. Small services are often better off without one.

Myth

All providers use the OpenAI request shape.

Fact

Many do, but Anthropic, Google and others have their own, with different field names and rules (system text, required fields, reply blocks).

Myth

A framework removes the need to understand the API.

Fact

When something fails you debug the HTTP request underneath. Knowing the raw shape is what makes that possible.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    SDK defaults are generous (long timeouts, silent retries). Set your own timeout and retry count, and log each retry so extra latency and cost are visible.

  • ▸

    Pin SDK versions and read changelogs: field names, default models and helper APIs change faster than the underlying HTTP APIs. A thin adapter over the HTTP shape survives longer than code written against a framework's types.

  • ▸

    Parameter names drift even inside one provider: OpenAI deprecated max_tokens for max_completion_tokens, and its reasoning models reject the old name. The same request body can work on one model and fail with a 400 on the next, so read the error body (Topic 2.6).

  • ▸

    "OpenAI-compatible" often means the common subset. Features such as strict structured output, reasoning options, caching controls and tool details can differ per server, so test the exact feature you rely on.

Remember this

  1. 1

    Why this exists. Topic 2.1 showed the raw call. Doing that in every project means rewriting the same things: building the JSON body, setting headers, retrying a 503, waiting on a 429, parsing choices[0].message.content, handling streams (Phase 5). Writing it once in a library saves time and bugs. That library is the SDK (software development kit).

  2. 2

    What an SDK adds. (1) Types: replies arrive as objects with named fields, so your editor autocompletes response.usage.total_tokens. (2) Retries: the official OpenAI and Anthropic SDKs retry connection errors, 408, 409, 429 and 5xx twice with a short wait by default. (3) Timeouts: a default (often long: minutes), which you should lower. (4) Streaming helpers that turn server-sent events into an iterator. (5) Auth from an environment variable. (6) Newer helpers for tools and structured output.

  3. 3

    One shape, many providers. The OpenAI chat-completions shape became a de facto standard. The official openai packages for Python and JavaScript accept a base_url / baseURL, so the same code can call Groq, a local server or another compatible provider by changing the URL, key and model. The first example builds a mini client that does this switching for two shapes.

  4. 4

    A different shape: Anthropic Messages. Anthropic's API uses POST /v1/messages with an x-api-key header and an anthropic-version header. max_tokens is required, the system text is a top-level system field, messages holds only user and assistant turns, the reply content is a list of blocks (text, tool use) and the stop reason is stop_reason (end_turn, stop_sequence, max_tokens, tool_use and a few newer ones) with usage.input_tokens and output_tokens. The example's client maps these names onto one reply shape, which is exactly the job of an adapter or SDK.

  5. 5

    Framework SDKs. Frameworks sit above provider SDKs and give one interface over many providers, plus helpers for prompts, tools and agents: the Vercel AI SDK (JavaScript and TypeScript), Spring AI and LangChain4j (Java), and in Python libraries such as LangChain. They help when you switch providers often or need their ready-made pieces. The cost is another layer to learn and to debug. This course builds the pieces by hand first (so you know what they do), and the blocks show each framework's call, not run.

  6. 6

    When to skip the SDK. For one or two calls in a small service, plain HTTP is a few lines and has no dependency that can break, change names or lag behind new API features. Use an SDK when you need streaming, many endpoints or types. Whatever you pick, put it behind your own small interface (Topic 2.8) so the rest of your code does not depend on it.

Explain it without notes

01

What does an SDK add over a plain HTTP call?

02

Name three differences between the OpenAI chat-completions shape and Anthropic's Messages shape.

03

When would you choose plain HTTP over an SDK or framework?

Practice

01

Write to_anthropic_body(openai_body) that converts an OpenAI-style body (with a system message first) into an Anthropic-style body: top-level system, the remaining messages, and max_tokens defaulting to 256.

02

Write normalise_stop(stop_reason) that maps end_turn to stop, max_tokens to length, tool_use to tool_calls, and returns anything else unchanged.

Trade-offs

  • ↔

    An SDK saves boilerplate and handles retries and streaming, at the cost of a dependency, hidden defaults and slower access to new API features.

  • ↔

    A framework gives one interface over many providers but hides details that matter when debugging, and its abstractions change.

  • ↔

    Plain HTTP is portable and stable, but you write and test retries, streaming and types yourself.

Done when you can

  • Done when you can list what an SDK adds to a raw HTTP call.

  • Done when you can switch an OpenAI-compatible client between providers by changing URL, key and model.

  • Done when you can name the main differences of Anthropic's Messages API.

  • Done when you can set an explicit timeout and retry count on any SDK you use.