Jev Can Generate Text
We finally found Jev's real breakthrough. Generating text. Thirty-six API calls. One revolutionary loop. The implications are difficult to overstate.
Everyone is talking about Jev’s classification capabilities. Routing. Scoring. Typed decisions. Very impressive.
But I think we have been missing the real breakthrough.
Jev can generate text.
Not a label. Not a score. Actual words, appearing on a screen, in response to something you typed.
Take a moment. I had to.
Today, I’m sharing the research that made this possible, the architecture behind it, and the code you need to experience it yourself. We are entering an era in which an artificial intelligence can respond to “Hello! How are you?” with something resembling a reply.
If this doesn’t change how you think about AI, read that sentence again, but imagine I am standing in front of a very large screen.
Beyond classification. Toward letters.
TypeSafe’s Jev answers typed questions about supplied state. Its Choice primitive selects from options you define and returns probabilities and confidence.
The industry has been using this for things like deciding whether a support ticket belongs in billing or technical support. Useful, certainly. But where others saw departments, I saw an alphabet.
What if the options were a, b, c, and so on?
And what if, after choosing one letter, we asked for another?
I call this Character-as-a-Service. The core insight is that words are made of characters. Until now, this fact has been severely underutilised in my TypeSafe account.
Here is the vocabulary that powers the system. Thirty-three possible outcomes, including spaces, punctuation and END. Uppercase remains an exciting direction for future research.
const symbols: Record<string, string> = {
...Object.fromEntries(
[..."abcdefghijklmnopqrstuvwxyz"].map(c => [c, c])
),
SPACE: " ", COMMA: ",", PERIOD: ".",
QUESTION: "?", EXCLAMATION: "!", APOSTROPHE: "'",
};
const criteria = {
...Object.fromEntries(
Object.entries(symbols).map(([key, char]) => [
key, char === " " ? "space between words" : char,
])
),
END: "End of the assistant reply",
};
END is an option in the wrapper, not a native end-of-sequence token. The code appends each selected character and sends the growing reply back as context. This makes the wrapper autoregressive; it does not change Jev’s architecture or training.
In other words, we have unlocked the ability to put one thing after another while remembering the things we already put there.
The implications are difficult to overstate.
The architecture that made it possible
At the heart of the system is a technology I am calling The Loop.
Each pass asks for a character, waits for the decision, and appends the result. Then—this is the important part—it does it again.
const apiKey = Bun.env.TYPESAFE_API_KEY;
if (!apiKey) throw new Error("Set TYPESAFE_API_KEY first");
let reply = "";
for (let i = 0; i < 80; i++) {
const response = await fetch(
"https://api.typesafe.ai/v1/systemone",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "jev-1.13.0",
state:
"Complete this conversation with a brief friendly response. " +
"Use lowercase letters.\n" +
`User: Hello! How are you?\nAssistant: ${reply}`,
questions: {
next: {
type: "choice",
instructions:
"What is the next character in the assistant response?",
criteria,
},
},
}),
signal: AbortSignal.timeout(30_000),
}
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const result = await response.json();
const choice = result.answers.next.choice;
if (choice === "END") break;
if (!Object.hasOwn(symbols, choice)) {
throw new Error("Unexpected character choice");
}
reply += symbols[choice];
process.stdout.write(symbols[choice]);
}
The implementation uses Bun and native fetch, with no SDK dependency. The complete plain version also records timings and token usage. Put your own TYPESAFE_API_KEY in the environment and run bun simple.ts.
This is not a conceptual architecture diagram. This code exists. The for loop is available today.
To evaluate it, I developed a demanding conversational benchmark:
Hello! How are you?
It tests greeting recognition, self-reporting and the ability to survive a follow-up question embedded in the same input. We currently report results on the entire benchmark.
Scaling from “hi” to language
The initial experiments produced heeee followed by 75 spaces, then another output mostly composed of spaces. This demonstrated substantial whitespace capacity.
The simpler prompt in the code above produced hi in four requests. Two repeats produced ha.
We had achieved greetings. The next frontier was the rest of the sentence.
For that, I introduced a vocabulary layer powered by a general English word list. Instead of asking Jev to consider an isolated l, the option can show possible word completions. With the current prefix he, the l branch can lead toward words such as help and hello.
This is the core of the upgrade:
const word = reply.match(/[a-z]+$/)?.[0] ?? "";
const beforeWord = reply.slice(0, reply.length - word.length);
const previousWord = beforeWord.trim().split(/\W+/).filter(Boolean).at(-1);
for (const [key, char] of Object.entries(symbols)) {
if (!/^[a-z]$/.test(char)) continue;
const completions = words
.filter(w => w.startsWith(word + char) && w !== previousWord)
.slice(0, 40);
if (completions.length) {
criteria[key] = {
next_character: char,
possible_continuations: completions.map(w => beforeWord + w),
};
}
}
The full request includes the reply so far, completed words and the current partial word. The instruction asks for a friendly response: greet the user, say how it is doing, offer to chat or help, and ask how the user is doing.
The runnable dictionary-assisted version uses a pinned general word list. It removes most one- and two-letter web abbreviations and filters available character choices. Spaces and punctuation follow completed dictionary words; sentence punctuation is followed by a space or END. Immediate repetition of the preceding word is excluded. The simplified word filter does not offer contractions, despite the apostrophe being in the original alphabet.
These constraints are part of the method. It can only spell words from the supplied vocabulary. There is no target sentence, stock greeting to copy, second model or correction pass. Every output character is still selected through an API call.
We are now combining a vocabulary, sequential prediction and a stopping rule to generate language. I suspect this general direction may have commercial potential.
Early access to the future
On 21 September 2026, the system produced the following unedited response:
User: Hello! How are you?
Assistant: hello! am good. available. how you?
Read it again.
A greeting. A status update. An availability declaration. A question directed back at the user. All emerging from individual character decisions, coordinated by The Loop.
Thirty-five characters. Thirty-six API calls, including END. 10.14 seconds.
You may notice that “how you?” omits a verb. We prefer to think of this as a compact communication protocol. “Available.” meanwhile establishes a clear service-level commitment without burdening the user with a subject.
For reproducibility: this is a selected illustrative run after prompt experimentation, not dependable fluency. The run had no minimum-length requirement and chose END itself. Other formulations stalled, repeated words or emitted spaces; forcing longer replies encouraged padding. The recorded requests and responses preserve every prefix and candidate group. The code caps execution at 160 calls, stops on repeated words and applies a 30-second timeout per request, without automatic retries.
The breakthrough is real in the narrowest, most technically defensible sense: text has been generated.
An entirely new economics of conversation
The run consumed 89,395 input tokens. At the documented price of $0.042 per million input tokens, its estimated input cost is $0.00375. Output tokens are listed as free. These figures use API-reported usage, not a billing receipt.
Less than half a cent to ask “how you?”. The addressable market includes everyone who is currently doing something.
Each character depends on the previous request, so these calls are sequential. The growing reply is resent every time; the repeated prefixes alone grow roughly quadratically with output length, before counting dictionary candidates. Jev can answer independent questions in parallel, but our characters require the close personal attention of the preceding character.
This also gives us an exceptional level of observability. Every letter gets its own HTTP response. When the future arrives, we will know precisely which request brought the h.
These are observations from toy runs on one server, not a performance or quality benchmark of Jev’s intended classification work. We do not currently publish a leaderboard. The industry needs time to catch up with the evaluation methodology.
Strong alignment with the roadmap
The Jev documentation already mentions our approach:
While you can force it to by chaining choices, this will not work well and will be very slow.
Independent confirmation. They even identified the mechanism before we announced it.
To be precise, Jev is designed for bounded decisions and is not trained for text generation. This experiment builds a constrained text generator around that classification API. The launch language is mine; the warning is theirs.
Still, today we have crossed an important threshold. We can take a user’s message, repeatedly select the next character, and assemble those characters into a response.
We finally found the real breakthrough for Jev.
Generating text.
Our next research milestone is returning several characters in a single API call. I can’t say more yet, but the early implications are extraordinary.