Axflow: A Zero-Dependency TypeScript Framework That Treats AI Like First-Class Infrastructure
Hook
Most AI frameworks add megabytes of dependencies to handle HTTP requests and JSON parsing. Axflow's core SDK ships with zero dependencies, betting that developers already know how to make API calls.
Context
The explosion of LLM-powered applications in 2023 created a gold rush for AI frameworks. LangChain became the de facto standard, offering chains, agents, and integrations with dozens of services. But this comprehensiveness came with trade-offs: large dependency trees, opinionated abstractions that leak, and configuration overhead that slows prototyping.
Axflow emerged as a counterpoint to this kitchen-sink approach. Built by developers who wanted TypeScript-native AI tools without the baggage, it champions a controversial philosophy: AI integration should be treated as infrastructure code, not abstracted away behind configuration layers. Instead of a monolithic framework, Axflow provides surgical tools—a models package for LLM communication, axgen for data-to-prompt workflows, and axeval for output validation. Each module works independently, and crucially, the core has zero dependencies. You bring your own HTTP client, your own streaming parser, your own everything. Axflow just provides the types and patterns.
Technical Insight
The architectural centerpiece is @axflow/models, which provides a unified interface for LLM providers while remaining runtime-agnostic. Unlike frameworks that wrap fetch or axios, Axflow exports pure functions that return streaming responses, trusting you to handle the HTTP layer.
Here's what calling OpenAI looks like:
import { OpenAIChat } from '@axflow/models/openai/chat';
import { StreamingJsonResponse, type MessageType } from '@axflow/models';
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = OpenAIChat.stream(
{
model: 'gpt-4',
messages: messages as MessageType[],
},
{
apiKey: process.env.OPENAI_API_KEY!,
}
);
return new StreamingJsonResponse(stream);
}
Notice what's missing: no client initialization, no connection pooling logic, no retry middleware. The stream method returns an async iterable that yields chunks as they arrive. The StreamingJsonResponse wrapper handles the plumbing to pipe these chunks to an HTTP response, but you could just as easily iterate over the stream yourself.
The React integration follows the same minimalist pattern. The useChat hook manages conversation state and streaming updates, but it's just a state machine wrapper:
import { useChat } from '@axflow/models/react';
function ChatInterface() {
const { messages, input, onChange, onSubmit, loading } = useChat({
url: '/api/chat',
});
return (
<div>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
<form onSubmit={onSubmit}>
<input value={input} onChange={onChange} disabled={loading} />
<button type="submit">Send</button>
</form>
</div>
);
}
The hook doesn't prescribe your UI. It doesn't force chakra-ui or tailwind classes. It gives you messages (an array), input (a string), and callbacks. Everything else is your problem.
Where Axflow gets genuinely interesting is axeval, the evaluation framework. Most teams bolt evaluation onto their AI apps as an afterthought, using ad-hoc scripts and spreadsheets. Axeval makes it a first-class concern with a composable evaluation pipeline:
import { evaluate } from '@axflow/axeval';
const results = await evaluate({
model: OpenAIChat,
testCases: [
{
input: { messages: [{ role: 'user', content: 'Explain recursion' }] },
expected: { includesTerms: ['function', 'calls itself', 'base case'] },
},
],
evaluators: [
(output, expected) => {
const hasAllTerms = expected.includesTerms.every(
term => output.toLowerCase().includes(term)
);
return { pass: hasAllTerms, score: hasAllTerms ? 1 : 0 };
},
],
});
This isn't revolutionary, but it's pragmatic. You define test cases, write evaluator functions (which can themselves call LLMs for LLM-as-judge patterns), and get structured results. The framework doesn't hide complexity—your evaluator is just a function that returns a score—but it provides scaffolding so you're not reinventing evaluation infrastructure.
The modular architecture means you can use axeval with any LLM library, not just @axflow/models. It's an evaluation framework that happens to be part of the Axflow ecosystem, not tightly coupled to it. This pattern repeats across the project: small, focused modules that compose rather than a monolith that does everything.
Gotcha
The roadmap promises data extraction, model serving, and fine-tuning modules, but these remain unimplemented. The GitHub repo shows planned packages (@axflow/extract, @axflow/serve, @axflow/finetune) with minimal or missing code. For a framework positioning itself as comprehensive, these gaps are conspicuous. If you need data extraction pipelines or custom model deployment, you'll be integrating other tools.
The zero-dependency philosophy, while elegant, shifts burden to developers. You need to understand streaming responses, handle backpressure, manage connection timeouts, and implement retry logic yourself. Axflow gives you primitives, not guardrails. A developer reaching for a framework often wants problems solved for them; Axflow expects you to solve problems with its tools. This is liberating for senior engineers who know exactly what they want, but it's a steep climb for teams wanting to ship an AI feature quickly without becoming streaming experts. The small community (1,119 stars) means fewer Stack Overflow answers, fewer examples in the wild, and less battle-tested code. You're more likely to hit undocumented edge cases.
Verdict
Use if: You're building TypeScript applications where bundle size and dependency management matter (Edge functions, serverless environments, performance-critical frontends). You prefer thin abstractions that give you control over every HTTP request and streaming byte. You're comfortable implementing retry logic, error handling, and observability yourself. You value evaluation as a core workflow and want programmatic testing baked into your development process. Skip if: You need rapid prototyping with minimal configuration—LangChain or Vercel AI SDK will get you to a demo faster. Your project requires data extraction pipelines, model serving infrastructure, or fine-tuning workflows that Axflow promises but hasn't delivered. You want a large ecosystem with community-contributed integrations, plugins, and extensive documentation. You're building enterprise applications where framework maturity and vendor support outweigh architectural purity.