Unique design
Here's a quick example of how you'd get structured output in RΞASON:
You create a normal TS interface describing what you want and just pass that as a generic to the reason() function. RΞASON then uses that interface to inform the LLM what object to return.
import { reason } from 'tryreason'
interface Joke {
/** Use this property to indicate the age rating of the joke */
rating: number;
joke: string;
/** Use this property to explain the joke to those who did not understood it */
explanation: string;
}
const joke = await reason<Joke>('tell me a really spicy joke')
// `joke` will be:
{
"joke": "I'd tell you a chemistry joke but I know I wouldn't get a reaction.",
"rating": 18,
"explanation": "This joke is a play on words. The term 'reaction' refers to both a chemical process and a response from someone. The humor comes from the double meaning, implying that the joke might not be funny enough to elicit a response."
}
You may have noticed that there are comments that look a like descriptions above each field to guide the LLM, and that is correct! RΞASON also uses the comments as the description for each field.
Agents
Another example of RΞASON interoping with your code is when creating an agent:
// src/agents/web-agent.ts:
import { useAgent } from 'tryreason'
import sum from '../tools/sum-tool'
import subtract from '../tools/subtract-tool'
import multiply from '../tools/multiply-tool'
import divide from '../tools/divide-tool'
export const tools = [
sum,
subtract,
multiply,
divide,
]
/**
* You are a helpful math assistant.
* You only have access to the four basic math operations (addition, subtraction, multiplication, and division).
*
* You *MUST* follow all math rules when answering the user's question.
* For instance, you cannot divide by zero and you have to follow the order of operations.
*/
export default async function WebAgent(userMessage: string) {
const agent = await useAgent()
return agent.run(userMessage)
}In most frameworks, you define tools twice (function + schema).
In RΞASON, the function is the tool — its signature + JSDoc drive the schema automatically. Reason’s compiler inspects the function signature and JSDoc to generate a JSON Schema definition that is passed to the LLM as the tool schema.
Under the hood, Reason has its own compiler that walks throught TypeScript AST.
At compile time, it:
- walks the AST of your TypeScript files,
- extracts types + JSDoc comments,
- and emits runtime metadata that the LLM runtime uses for structured output and tools.
Outcome
In hindsight I got some things very right and others very wrong:
That said, I'm happy with how RΞASON turned out; as it stands, it is a small experimental programming language that I routinely use for my own LLM usecases.

