Artificial IntelligenceArtificial Intelligence · 4 Jul 2026
How to choose an AI SDK: why the fear of lock-in is a mistake and how to decide based on your app's format
The fear of being locked into an AI provider is a common mistake. Learn how to choose the best SDK based on your project's format and productivity.
For a long time, I did the math wrong in my head. When I was about to start an app with AI, I would discard the Claude Agent SDK and the Vercel AI SDK almost out of reflex — “those must be tied to their provider,” I thought. Then I would go with Genkit, thinking it was the only “free” option. Until the day the Ollama launcher showed me, right to my face, that I was wrong the whole time.
What you take away from this article
No agent SDK locks you into a vendor — they all run Claude, GPT, Gemini, or local models.
The agnostic layer is the same in all of them: pointing to a URL (base-URL / gateway / plugins) + normalization.
The real choice is based on the APP FORMAT, not the brand: code agent, content+RAG, typed logic, or UI.
Batteries-included is worth more than theoretical agnosticism — what comes ready-made saves weeks.
The premise that cost me dearly
The question that stalled everything was: “what if one day I want to switch models? Will I be held hostage by Anthropic / Vercel?”. With that fear, the selection criteria became the vendor — and not the problem I was solving. It is a silent error, because it looks like prudence.
Choosing an SDK out of fear of provider lock-in. You might end up with the right tool for the wrong reason — or the wrong tool because of a fear that doesn't even exist. Provider lock-in is not a real criterion: no modern agent SDK locks you into a single model.
Ollama toppled the premise
I ran the ollama launch and the menu offered me, among other things, “Launch Claude Code (minimax-m3:cloud)” and “Launch OpenCode”. Notice the detail: it was about to run Claude Code — which uses the Claude Agent SDK under the hood — with a minimax-m3 model, which is not from Anthropic. How? It just swaps the base URL pointer.
# É só isto que o launcher do Ollama faz por baixo dos panos:
export ANTHROPIC_BASE_URL=http://localhost:11434 # endpoint Anthropic-compat do Ollama
export ANTHROPIC_MODEL=minimax-m3:cloud
claude # Claude Code rodando um modelo NÃO-Claude, com subagentes e tudoZero code. A third-party model running under the Claude Code harness, just because Ollama exposes an endpoint compatible with the Anthropic protocol. If this applies to Claude Code, it applies to any app built on the same SDK.
The agnostic layer exists in all of them
After that realization, I went to look at the others. They all have the same fundamental mechanism: pointing to an endpoint + a normalization layer. Only the name changes:
SDK | How it points to another provider | Normalizes to |
|---|---|---|
claude-agent-sdk | ANTHROPIC_BASE_URL (endpoint that speaks the Anthropic protocol); Bedrock/Vertex backends | shape Anthropic Messages |
Vercel AI SDK | gateway() / createGateway({baseURL}) / createOpenAICompatible({baseURL}) | neutral contract (text/tool-call/reasoning) |
Genkit | provider plugins (googleAI, openai-compat…) | Genkit model abstraction |
Pointing the URL is free. But the model on the other side receives a harness molded for whoever normalizes. An OpenAI-native model running under the Anthropic shape works, but whether it behaves well there is a matter of model quality — not architecture. Claude in Bedrock/Vertex is native; non-Claude model via Anthropic-compat runs, but test the behavior.
O vendor não é critério. A escolha real é qual batteries-included bate com o formato do app.
The four SDKs and what each one already brings ready-made
They are not at the same level of abstraction — and that is exactly what decides the choice. It is not “which one is freer” (all are), but rather “which one already solves the type of app I am building”.
claude-agent-sdk — “Claude Code as a library”
It is a complete agent harness. It gives you the five most annoying primitives to build for free: tool hooks (deterministic guard), human-in-the-loop approval, AskUserQuestion as a protocol, subagents via native tool, and in-process MCP. Fits: autonomous code agent with security and approval.
Genkit — GenAI app framework
Strong in first-class RAG (retriever/indexer/embedder), orchestration flows, and OpenTelemetry observability with dev UI. Fits: content generation, RAG, pipelines, tracing. It was the right choice for my editorial — just for the wrong reason at the time.
pydantic-ai — typed agents in Python
Typed agents and tools, structured output validated by Pydantic, multi-agent. Lightweight, no ready-made RAG/flows/observability. Fits: typed agent logic. I tested it for the editorial and it didn't fit — it is a battery for another format.
Vercel AI SDK — model + tools + provider (+ UI)
streamTextAI SDK CoregenerateText with neutral parts, ToolLoopAgentthe best agnostic provider story, and UI hooks (useChat). Fits: truly provider-neutral (first-class OpenAI-native) + React UI integration.
The five primitives of the claude-agent-sdk (guard, approval, AskUserQuestion, subagents, MCP) do not exist ready-made in the Vercel AI SDK or Genkit — rewriting them in an agent app is weeks of work. Conversely, they are irrelevant in a content app, which doesn't edit a repo nor needs approval.
Capability (comes ready?) | claude-agent-sdk | Vercel AI SDK | Genkit | pydantic-ai |
|---|---|---|---|---|
Agent loop | ✓ | ✓ | ✓ | ✓ |
Guard / tool hooks | ✓ native | — | — | — |
Human approval | ✓ | — | — | — |
Native subagents | ✓ | — | — | ~ |
First-class RAG | — | — | ✓✓ | — |
Observability / tracing | basic | basic | ✓ OTel | basic |
UI hooks (useChat) | — | ✓ | — | — |
Provider agnostic | via base-URL | ✓ neutral | ✓ plugins | ✓ |
The decision ruler
After all this, the question I ask today, before any line of code, is just one: what is the app format?
❌ How I used to decide
“Which SDK locks me in the least to the vendor?”
Result: I chose out of fear, not because of the problem.
✅ How I decide now
“Which batteries-included matches the app format?”
Result: the tool that already solves the right type of problem.
Autonomous code agent (security, approval, subagents) → claude-agent-sdk
Content + RAG + flows + observability → Genkit
Typed agent logic (Python) → pydantic-ai
Truly provider-neutral + UI → Vercel AI SDK
Bonus: the settingSources trap
A technical surprise worth keeping in mind, if you use claude-agent-sdk: your agent inherits the Claude Code environment (hooks, plugins, CLAUDE.md, permission rules) even if it is not Claude Code. And it is not because of the API key — it is the default of settingSourcessettingSources
// sdk.d.ts: "When omitted, all sources are loaded (matches CLI defaults).
// Pass [] to disable filesystem settings (SDK isolation mode)."
buildAgentOptions({
// settingSources OMITIDO -> carrega ~/.claude inteiro (hooks/CLAUDE.md/perms)
settingSources: [], // <- modo ISOLAMENTO: só as regras do teu app
})Auth (which API key) is orthogonal to settings loading. If your agent inherits behavior you didn't ask for, the lever is settingSourcessettingSources
, not the key. Make it explicit — accidental inheritance is debt.
What I take to every new projectVendor is not a criterion. Every agent SDK is agnostic via base-URL / gateway / plugins.
Decide by the app format, not by the brand or fear of lock-in.
Batteries-included > theoretical agnosticism. What comes ready-made saves weeks.Testing and migrating without guilt is correct selection, not an error (that's how I went from pydantic-ai to Genkit in a content app).
What is reusable is UI/infra, not the engine: extract chat, streaming, and retriever into a common package.
The good part about discovering you were wrong is that the remaining ruler is simple and reusable.Not “which SDK is the best” — but rather
which SDK is the best for this app. app.