Your agent wires an email service, an AI API, and a payment SDK, the vendor's own ready-made code, straight into feature code, wherever each one is needed. It works, until the vendor changes its prices, you want to switch providers, or the SDK ships a breaking change. Now that one change is scattered across twenty files. This chapter gets each outside service behind one door you control.
3.6.1A vendor threaded everywhere is a rewrite waiting
When feature code calls a vendor's SDK directly, the vendor is glued into your whole app. Every screen that charges a card imports the payment library, pulling that vendor's code into its own file. Every place that emails a user does the same with the mail library. This is vendor lock-in: the outside service is now welded into dozens of files.
The day the vendor raises its price, breaks its SDK, or loses your trust, the swap means editing everywhere it appears. Vendor entanglement is one of the most common rewrite triggers in AI-built apps. Note this is a service you consume, distinct from the API you expose.
3.6.2Put each service behind one adapter
Give each outside service one adapter, a thin file you own that wraps the vendor and stands between it and your code. Your feature code calls your function (charge(...)), and only the adapter file ever imports the vendor. That one file is the whole surface the rest of your app sees. This owned wrapper is sometimes called an anti-corruption layer, because it stops the vendor's shape from leaking into, and corrupting, the rest of your code.
Some vendors also call back. A payment provider takes your charge request, then contacts your app minutes later with the outcome, over a webhook, an address on your app the vendor sends to. That handler belongs beside the adapter and not in a feature file, so everything about that vendor still lives in one place.
3.6.3Now you can swap without a rewrite
To move from one provider to another, or to absorb a breaking SDK change, you rewrite the inside of that one adapter. The charge function keeps the same name and the same shape, so every file that calls it stays untouched.
The rest of your app never notices the vendor changed. That is exactly the "extend without rewrites" this part is built around: a swap that could have touched twenty files now touches one.
3.6.4Wrap what you could swap, not your framework
The rule has an edge, and it is worth knowing before you over-apply it. Wrap the services you could plausibly change one day: payments, email and SMS, an AI model API, a login provider.
Do not wrap your framework, your database library, or your UI toolkit. You committed to those when you picked your stack. Swapping one would be a rewrite either way, so the wrapper buys you nothing and costs every reader a layer to see through.
3.6.5Keep the door thin and in your words
An adapter is only useful if it stays narrow. Expose the handful of operations your app actually needs, named in your own terms (charge, refund, sendEmail), not the vendor's entire API surface.
Do not let the vendor's own types leak back out through the door. If charge returns the vendor's raw response object, every caller is quietly coupled to that vendor again, and you are back where you started. Return a small shape you define, the same narrow-interface idea from the coupling chapter.
This prompt has your agent pull every vendor behind its own door:
Do this now: paste the prompt so your agent finds every direct vendor call and moves each behind one adapter you own, then confirm exactly one file imports each SDK.