Get an AI Coding Agent to Use Your Internal Library

Agents pattern-match your internal library to the nearest public one and invent functions accordingly. Four fixes, in the order worth doing them, starting with a twenty-minute one.

Steve Jefferson
Steve Jefferson
Developer Advocate
30 August 20261 min read

Your AI coding agent keeps writing code against a library it invented, when the real one is sitting in your repo. It imports createUser from your auth package, which has never existed, because every other auth package it has ever seen has a createUser. The fix is not a better prompt. It is making the library's actual surface available to the agent in a form it will read, and then making it expensive for the agent to guess.

Internal libraries are the single most common place AI coding agents fail on a mature codebase, for a mechanical reason: the model has seen millions of examples of public packages and zero examples of yours. Left to itself it will pattern-match to the public convention every time.

Four things fix this, in increasing order of effort and effectiveness.

1. Put the real signatures where the agent will look

Most agents read a project instructions file before they start. That file is the cheapest intervention available, and most teams waste it on tone-of-voice instructions.

What belongs in it, for each internal library:

markdown
## @acme/auth

Import from '@acme/auth'. Never from '@acme/auth/src/*'.

The only exported functions are:
  registerUser(input: RegisterInput): Promise<Result<User>>
  authenticate(email, password): Promise<Result<Session>>
  requireSession(req): Promise<Session>   // throws AuthError

There is NO createUser, NO login, NO getUser. If you want a user
by id, that is @acme/db, not this package.

All functions return Result<T>, never a bare value and never a
throw except requireSession. Check result.ok before using
result.value.

The negative list is doing most of the work. Telling the agent what does not exist, using the exact names it is likely to hallucinate, is more effective than listing what does, because it interrupts the pattern-match directly. If you look at what your agent actually invents over a week, you will find it reaches for the same three or four wrong names repeatedly. Name them.

Keep this section under about forty lines per library. A long file gets skimmed or falls out of context, which is the failure mode described in keeping an AI coding agent from losing context. If you have not set one of these files up at all, how to write an AGENTS.md file is the starting point.

2. Point it at one canonical usage example

Models are far better at copying a real example than at reading a specification. For each internal library, nominate one file in the codebase that uses it correctly and idiomatically, and name that file in the instructions:

markdown
For a correct end-to-end example of @acme/auth in use, read
src/routes/session.ts before writing any auth code.

Pick a file that is short, current, and exercises the common path. Then keep it correct, because it is now load-bearing documentation. This one line typically does more than a page of prose, and it has the useful property of never going stale silently: if the example file breaks, your build tells you.

3. Make the types unavoidable

If your library is typed, the agent can read the types, but only if it thinks to look. Two things make that reliable.

Export a single entry point with explicit types rather than deep paths, so there is one obvious file to read. And make the illegal states unrepresentable enough that a hallucinated call fails at typecheck rather than at runtime. An agent that runs tsc after editing will self-correct within a turn; an agent whose invented function silently type-checks as any will not.

This is why the highest-leverage change for many teams is not a prompt at all. It is turning on noImplicitAny, or the equivalent in your language, so that guessing has an immediate cost. Pair it with instructions to run the typechecker before declaring a task done, and most invented-API problems disappear without you writing another word of documentation.

4. Serve the library over MCP when the surface is large

For a library with a genuinely big API, or one whose docs live outside the repo, static instructions stop scaling. At that point an MCP server that exposes your internal documentation and lets the agent query it on demand is a better fit: the agent pulls the specific signature it needs at the moment it needs it, rather than carrying the whole surface in context.

This is worth the setup effort at roughly the point where your instruction file for one library exceeds a page, or where more than a handful of people hit the same problem. Below that, the file plus the example is cheaper and works. If you are weighing the approach, MCP versus a REST API for AI agents covers the trade-off, what MCP is covers the basics, and the official MCP documentation covers the protocol itself.

The order to do these in

Start with the negative list. It takes twenty minutes and catches most of it.

Add the canonical example file next. Another twenty minutes.

Then check whether guessing actually costs the agent anything. If a hallucinated call passes your typecheck, fix that before writing more documentation, because documentation is a suggestion and a failing build is not.

Reach for MCP last, and only when the first three are in place and still insufficient. It is a real piece of infrastructure with real maintenance, and most teams do not need it.

What still will not work

Two honest limits.

An agent will still occasionally invent an API in a long session, after your instructions have scrolled out of its working context. Re-anchoring periodically, or splitting the task, is the practical answer, and it is the same underlying issue as an agent stuck in a loop.

And if your internal library is genuinely unusual, in the sense that it does the opposite of the public convention, expect a permanently higher error rate. A function called save that does not save is going to be misused by every model and every new hire. That is worth knowing about your own API design, which is a more useful finding than a prompt fix.

FAQ

Why does the agent invent functions instead of reading the code?

Reading costs context and time; predicting is instant. Models will predict a plausible name unless prediction is made expensive, which is why the negative list and a failing typecheck both work better than asking politely.

Should I paste the whole library source into the prompt?

Rarely. It works for a small library and degrades badly past a few hundred lines, because the relevant signature gets buried. A short interface summary plus one usage example outperforms the full source in most cases.

Does this apply to internal APIs as well as libraries?

Yes, and more so, since there is no type checker to catch a wrong endpoint. The same pattern applies: the exact routes, the exact shapes, a negative list of the endpoints people assume exist, and one real example request.

How often should I update the instructions file?

When the library's public surface changes, in the same commit. If it drifts, the agent follows the stale version confidently, which is worse than having no file at all. This is the same failure covered in why an agent keeps recommending deprecated packages.

How did this land?

About the author

Steve Jefferson
Steve Jefferson

Developer Advocate

Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.

Share

Get the next post in your inbox

One email a month. Product updates, engineering posts, and the best of Built with Swarmz.

I agree to receive emails about AI building tips and Swarmz product news. Unsubscribe any time.

Get an AI Coding Agent to Use Your Internal Library | swarmz.net