dev-tools 5 min read

RΞASON - TypeScript Framework for LLM Apps

RΞASON is a minimalistic TypeScript framework for building LLM apps with structured outputs, function-based agents, streaming, and zero-config OpenTelemetry observability.

By
Share: X in
RΞASON TypeScript framework for LLM apps

TL;DR

TL;DR: RΞASON is a minimalistic TypeScript framework that uses TypeScript interfaces at runtime to get structured output from LLMs, with built-in function-based agents, streaming, and OpenTelemetry support.

Source and Accuracy Notes

⚠️ This section is MANDATORY. All links must be verified from actual source, not guessed.

What Is RΞASON?

RΞASON (pronounced “reason”) is an open-source TypeScript framework for building LLM-powered backend applications. It was created by Inacio (HN: inacio17m) as a first-principles approach to LLM framework design.

The core philosophy: LLMs are a new programming primitive — like databases in the 1970s or the web in the 2000s — and they need the right abstractions. RΞASON tries to provide those abstractions without bloating your codebase.

Five Core Principles

  1. Structured output is key, but not at all cost — RΞASON uses TypeScript’s interface and JSDoc comments at runtime to guide the LLM toward typed output
  2. Prompting is the developer’s job — no pre-made prompts or agents; you control your prompts entirely
  3. Agents should be functional — agents and actions are plain JavaScript functions, not classes
  4. Streaming, but structured — streams both text and structured data, not just raw tokens
  5. Zero setup observability — ships with OpenTelemetry compatibility out of the box, no extra packages needed

Setup Workflow

Step 1: Install

npx use-reason@latest

Step 2: Create your first entrypoint

// src/entrypoints/joke.ts
import { reason } from 'tryreason'

interface Joke {
  /** The joke text */
  joke: string
  /** Age rating from 1 to 18 */
  rating: number
  explanation: string
}

const result = await reason<Joke>('tell me a really spicy joke')
console.log(result.joke)      // "I'd tell you a chemistry joke..."
console.log(result.rating)    // 18
console.log(result.explanation) // structured explanation

Step 3: Run

npm run dev

Deeper Analysis

Structured Output via TypeScript Interfaces

The standout feature is using TypeScript interfaces directly at runtime. Most LLM frameworks require you to learn a new schema system or DSL. RΞASON works with what you already know:

interface UserProfile {
  name: string
  email: string
  preferences: string[]
  accountTier: 'free' | 'pro' | 'enterprise'
}

RΞASON serializes the interface and JSDoc comments and sends them to the LLM as part of the prompt, producing a correctly-typed response without a separate schema definition step.

Function-Based Agents

Unlike LangChain-style OOP agents that require extending base classes and learning framework-specific patterns, RΞASON agents are just async functions:

import { useAgent } from 'tryreason'

export const actions = [searchWeb, generateImage, sendEmail]

export default async function MyAgent(userMessage: string) {
  const agent = await useAgent()
  return agent.run(userMessage)
}

Each action is a plain async function. The LLM decides which action to call, RΞASON calls it with the generated parameters, and returns the output to the LLM. No agent base classes, no framework-specific inheritance.

OpenTelemetry Out of the Box

Every RΞASON app automatically emits OpenTelemetry traces. You get spans for:

  • LLM calls (model, input tokens, output tokens, latency)
  • Agent reasoning steps (action selection, parameter generation)
  • Action executions (function calls, return values)

No @decorators, no extra packages, no configuration. Import and it works.

Practical Evaluation Checklist

  • Open source? Yes — github.com/try-reason/reason
  • npm package? Yes — tryreason on npm
  • TypeScript-native? Yes — built in TypeScript, uses TypeScript interfaces at runtime
  • Streaming support? Yes — streams both text and structured partial results
  • Observability built in? Yes — OpenTelemetry with zero config
  • Multi-agent support? Yes — function-based action pool pattern
  • Framework lock-in? No — uses standard fetch for LLM calls, supports any OpenAI-compatible API
  • Active development? Last push November 2025 (verify via GitHub)
  • Documentation? Yes — docs.tryreason.dev

Security Notes

  • RΞASON calls LLMs via standard HTTP — ensure your API keys are stored in environment variables, never hardcoded
  • The framework does not impose output sanitization — treat LLM outputs as untrusted user input in downstream code
  • No built-in rate limiting or quota enforcement — implement at the application layer if needed

FAQ

Q: How is RΞASON different from LangChain or LlamaIndex? A: RΞASON uses plain TypeScript functions for agents instead of class-based inheritance chains. It also skips pre-made prompts and retrieval strategies entirely — prompting is always the developer’s responsibility. The result is a smaller, more predictable framework.

Q: Does it support OpenAI, Anthropic, and local models? A: It works with any OpenAI-compatible API endpoint (OpenAI, Anthropic, local Ollama instances, etc.). Custom provider configuration is done at the application level.

Q: Is it production-ready? A: The README notes it is “experimental” — the author explicitly recommends thinking carefully before using in production. It has 49 stars on GitHub and is actively maintained as of late 2025.

Q: What is the license? A: The repository does not contain an explicit LICENSE file. The GitHub API returns no license field. Treat it accordingly.

Conclusion

RΞASON is a thoughtful, minimal take on LLM backend framework design. Its use of TypeScript interfaces as a runtime schema mechanism is genuinely novel — no other framework uses the language’s type system quite this way. The function-based agent pattern sidesteps OOP boilerplate, and zero-config OpenTelemetry is exactly what production LLM apps need.

If you’re building LLM-powered services in TypeScript and want a framework that stays out of your way, RΞASON is worth a closer look. Start with npx use-reason@latest and read the docs at docs.tryreason.dev.