Latent Node Study 02 · Conjure Contents ←

Study 02

Don't Import It. Conjure It.

A dependency-free programming paradigm. Describe a function in a YAML spec, let a model on your own machine write it, and verify by syntax tree that the result has no imports at all.

Result88%, pass@3, 9B local model
PublishedJun 2026
SeriesLatent Node  ·  Paper ↗
Cover

A dependency-free programming paradigm: describe the function you want in a YAML spec, let a local model write it, and verify the result has no imports at all.


Here's a number that should bother you more than it does: the average npm package quietly trusts 79 other packages and 39 maintainers you've never heard of. Python is no better. Run pip install flask and you've signed up for Werkzeug, Jinja2, MarkupSafe, ItsDangerous, Click, and Blinker, each with its own maintainer, its own release schedule, and its own bad day waiting to happen.

We mostly don't think about this. The install works, the tests pass, we move on. Then every so often the bill comes due.

In 2018, someone talked their way into commit access on event-stream, a tiny npm package pulling two million downloads a week, and slipped in code to drain a specific Bitcoin wallet. It sat there for two months. In 2021, an attacker grabbed the ua-parser-js maintainer's account and pushed three poisoned versions in a single afternoon to a package with eight million weekly downloads. And in 2024 we got the scariest one yet: a contributor spent two years being helpful on the xz compression library before planting a backdoor into the SSH login path of nearly every Linux server on the planet. It was caught by luck. One engineer noticed his SSH logins were running half a second slow.

The thing all three have in common: the malware arrived through the front door. The official package registry. The legitimate update channel. Lockfiles, scanners, and signed builds all guard that door, but they can't stop an attack that is the door.

So we tried something different. Instead of guarding the dependency, get rid of it.

The SQLite move

SQLite is one of the most-deployed pieces of software ever written, and it pulled that off with a stubborn idea: don't run a database server, just embed the whole engine inside your program. No network hop, no auth handshake, no separate process to babysit. The trade-offs are real. But for the overwhelming majority of apps they don't matter, and the whole category of "database server problems" just disappears.

Conjure does the same thing to library code. You describe the function you want in a short YAML file. A language model running on your own machine writes a self-contained implementation. That code gets checked, tested, and cached. The package registry, the dependency tree, the supply chain. None of it is in the picture anymore.

Traditional dependency chain versus Conjure's local generation path
Traditional dependency chain versus Conjure's local generation path

Spec in, code out

A spec is about as boring as it sounds, which is the point. You write down the function signature and a couple of examples of what it should do:

A levenshtein.yaml spec on the left, the generated import-free Python on the right
A levenshtein.yaml spec on the left, the generated import-free Python on the right

Call conjure.invoke("levenshtein", s1="kitten", s2="sitting") and a few things happen in order. Conjure checks its cache. On a miss, it builds a prompt from your spec, asks the local model for an implementation, and pulls the function out of the reply. Then it runs two gates. The first parses the code and walks its syntax tree. The second runs every example from your spec inside a locked-down sandbox. If anything fails, the exact error gets handed back to the model ("expected 3, got 4", or "import not allowed: hashlib") and it tries again, up to three times.

That feedback loop matters more than I expected. On the first try the model gets about 70% of specs right. Let it read its own error and try again and that jumps to nearly 88%. Most of the time the model already knows how to fix its mistake; it just needs to be told what broke.

Here's the implementation it produced for that Levenshtein spec, untouched:

def levenshtein(s1, s2):
    m, n = len(s1), len(s2)
    dp = list(range(n + 1))
    for i in range(1, m + 1):
        prev = dp[0]
        dp[0] = i
        for j in range(1, n + 1):
            temp = dp[j]
            if s1[i-1] == s2[j-1]:
                dp[j] = prev
            else:
                dp[j] = 1 + min(prev, dp[j], dp[j-1])
            prev = temp
    return dp[n]

Notice it picked the space-optimized version, one row instead of the full matrix, with no library and no nudging. Once it's verified, that code is cached against a hash of your spec, and the next call returns in about a third of a millisecond. The slow part happens once.

Why "no imports" is a guarantee, not a vibe

Most "secure code generation" stories ask you to trust that the model behaved. Conjure doesn't ask. Before any generated function is cached, its syntax tree gets walked and rejected if it contains an import, a call to eval, exec, compile, or open, or any reach into os, sys, subprocess, or shutil. This isn't pattern-matching on strings that a clever payload could dodge. It's a structural property: a function that passes the check provably cannot reference those things, no matter what the model was thinking.

That single rule closes the door on ten different CWE vulnerability categories: code injection, embedded malicious code, OS command injection, path traversal, unsafe deserialization, and more. Not because Conjure detects the attacks, but because the code physically cannot perform them. No imports means no network, no filesystem, no shell. The worst a compromised model can do is write a function that returns the wrong answer, which your example tests are there to catch.

Here's what that buys you against real incidents. A typosquatted package? There's no package to install. A maintainer account takeover? There's no maintainer in your trust chain. A poisoned update three levels deep in your transitive dependencies? There are no transitive dependencies. We went through roughly 3,800 Python supply-chain incidents from 2023 to 2025. This approach neutralizes about 68% of them, including every single one of the 2,500+ malicious package attacks.

Does it actually work?

On ConjureEval-100, a benchmark of 100 specs across 20 categories mapped to real PyPI functionality, a 9-billion-parameter model running locally hits 70% on the first attempt and 88% with the retry loop. That's a model small enough to sit in about 5 GB of memory on a laptop.

ConjureEval-100 results and attack-surface reduction across five real applications
ConjureEval-100 results and attack-surface reduction across five real applications

The more interesting number is the one on the right side of that image. We took five ordinary Python apps (a Flask blog, a FastAPI service, a CLI tool, a web scraper, a file-sync utility) and measured how much of their dependency code Conjure could replace. The web scraper went from 17 transitive packages to zero. Across the five, the auditable code surface shrank by an average of 13x, up to 20x at the high end.

Where it falls down

I'd rather tell you the limits than have you find them.

The 9B model has a ceiling. Ask it for SHA-256 and it stumbles. That algorithm needs 64 exact round constants and bit-twiddling that's unforgiving of a single typo. Full recursive-descent parsers are shaky too. About 12% of specs land in this "the model just can't reliably do this yet" bucket. Bigger models will move that line, but today it's a real line.

There's also a gap between passing your examples and being correct. When we threw 30 random inputs at functions that passed their example tests, about 60% held up. The failures clustered on edge cases (empty lists, weird strings, type mismatches), not on broken logic. The fix is mundane: add the edge case to your spec as an example and regenerate. The spec becomes the living contract. But it does mean conjured code shouldn't go into a safety-critical path without extra fuzzing first.

And one result I'll admit surprised us: we tried to make the model better at this through fine-tuning: supervised, rejection sampling, DPO, self-distillation, the whole menu. None of it beat the plain base model with the retry loop. The diversity you get from just sampling a general model turned out to be worth more than specializing it.

Try it

It's one line to install and runs entirely on your machine. No API key, no cloud, no network call.

Installing and calling Conjure from a terminal, with the cache hit on the second call
Installing and calling Conjure from a terminal, with the cache hit on the second call
import conjure
conjure.invoke("levenshtein", s1="kitten", s2="sitting")  # -> 3, generated locally and verified

None of this makes your other dependencies disappear. Frameworks, database drivers, anything that needs a real socket or a C extension: those stay, and the usual tools still earn their keep there. Conjure goes after the other half of your dependency tree: the pure-logic utility code that does base64, slugs, edit distance, CSV parsing, a hundred small things you import a whole package for. For that code, the supply chain attack surface drops to zero, because there's nothing left to attack.

The full paper has the threat model, the CWE breakdown, the scaling curves, and every number above with its receipts. You can read it at conjure.pages.dev, and pip install conjure-llm if you want to poke at it yourself.

Source, checkpoints, and data for this study are available to sponsors.

Support the work