How I Turned One Sentence Into a Deployed, Typed API
By Ergini, Software & AI Developer
TL;DR
OmniAPI, which I built, turns a one-sentence description into a typed, deployed endpoint. The first prototype generated code and ran it, and real descriptions exposed the problems: inconsistent types, calls with no timeout, a function reading an environment variable, an endless loop. The rebuild treats generated code as untrusted: schemas first and confirmed by the developer, typechecking and runtime validation, a sandbox with no secrets and no network unless declared, hard time limits, versioned deploys, and examples turned into tests that must pass before anything ships.
The function I kept writing
Every product I built had the same small functions hiding in its backend. Take a messy address and return a clean one. Turn a pasted invoice line into an object with a quantity, a unit and a price. Call a currency API, convert, round the way accounting wants. None of them is hard. Each one takes an afternoon: the types, the validation, the error handling, the deploy.
So I asked the question that became OmniAPI: what if you could describe the function in one sentence and get back an endpoint? Typed input, typed output, deployed, callable from your code a minute later.
The first version generated code and hoped
The first prototype did the obvious thing. It took the sentence, asked a model to write the function, ran it, and returned the result. In a demo it was magic. "Convert a price between currencies using today's rate" became working code in seconds.
Then I fed it the kind of sentences real developers write, and the magic started to show its seams. A function that returned the price as a string on some inputs and a number on others. One that called an external API with no timeout and hung whenever the API was slow. One that, trying to be helpful, read an environment variable it had no business knowing about. And one that, given an input nobody had imagined, looped until something outside it gave up.
None of that is surprising once you say it plainly: generated code is untrusted code, written by an author who has never seen your system and cannot be asked what they meant. The product was not the generator. The product was everything around it that makes generated code safe to call.
Types first, code second
The biggest change was the order of things. OmniAPI no longer starts by writing code. It starts by writing the contract: from the sentence, a model drafts the input and output schemas, and the developer sees them before anything else happens. "Convert a price between currencies" becomes an input with an amount, a source currency and a target currency as three-letter codes, and an output with the converted amount, the rate used and when that rate was fetched.
That one screen catches most misunderstandings. The developer meant integers in cents, not decimals. They wanted the rate's timestamp back so they could show it. Fixing a schema takes seconds; fixing a deployed function that got the question wrong takes an afternoon and an apology.
Only then is the implementation generated, against those exact types. It is typechecked like any other code, and at runtime every response is validated against the output schema before it leaves. A function that returns the wrong shape does not return a guess. It returns an error, loudly, with the shape it produced. I wrote about the same principle from the model's side in structured outputs with strict JSON schema.
A sandbox that assumes the worst
Every generated function runs in an isolated sandbox with nothing it was not given. No file system. No environment variables, and so no secrets to read by accident. Network access is off by default, and a function that needs an external API gets exactly the domains its description needs, declared up front and visible to the developer. Hard limits on time and memory mean the looping function from the first prototype now simply stops, and the call fails with a reason instead of hanging somebody else's request.
Each function is versioned. A regeneration is a new version, not an overwrite, and every call records which version answered it, how long it took and whether its output passed validation. When something goes wrong in production, the question "what code ran here?" always has an answer.
Examples become tests
The last piece was the one that made the whole thing trustworthy for me. When developers describe a function, they almost always have examples in their head: this input should give that output. OmniAPI asks for a few, and they become tests. A generated implementation is not deployed until it passes them. When it fails, the failure goes back to the model as feedback and it tries again, and the version that finally ships is the one that passed, not the one that sounded most confident.
| Stage | Done by | What it prevents |
|---|---|---|
| A sentence and a few examples | The developer | Guessing what the function is for |
| Input and output schemas | The model drafts, the developer confirms | A correct function that answers the wrong question |
| Implementation | The model | Writing boilerplate by hand |
| Typecheck and example tests | Code | Deploying something that merely looks right |
| Sandboxed, versioned deploy | Code | Generated code reaching what it should not |
| Runtime output validation and call logs | Code | Silent wrong answers in production |
What I would not let it generate
Building OmniAPI made me more conservative about generated code, not less. It is excellent at the boring middle of a backend: parsing, validating, transforming, and calling well-documented APIs with clear contracts. It is the wrong tool for anything irreversible. Moving money, deleting data, sending messages on someone's behalf, handling credentials: those belong in hand-written code behind a human approval, however good the model gets. A function you cannot test with examples is also a function you should not generate.
The same thinking runs through the AI features I build for other companies. The model is one component with a contract, a sandbox and tests around it, and most of the engineering is in those. If you want to try the idea yourself, OmniAPI is here. If you want a model working inside your own product under the same discipline, that is AI integration, and tool calling in production covers the neighbouring problem of models calling your code instead of writing it.
Frequently asked questions
Is it safe to run code that an AI model generated?
Only if you treat it as untrusted code. That means a sandbox with no access to the file system or your secrets, network access off unless a domain is explicitly allowed, hard limits on time and memory, and tests that must pass before anything is deployed. Generated code is often correct. The system has to be built for the times it is not.
How do you get typed output from an AI-generated function?
Fix the contract before generating the code. Derive input and output schemas from the description, have a person confirm them, generate the implementation against those types, typecheck it, and validate every response against the output schema at runtime. A function whose output does not match its schema returns an error, never a best guess.
What should an AI code generator never be allowed to do?
Anything irreversible without a person: moving money, deleting data, sending messages on someone's behalf, or touching credentials. Those belong behind explicit human approval and hand-written code. Generation is at its best for the boring middle of a backend: parsing, validating, transforming and calling well-understood APIs with clear contracts.