Model or dataset
ax-llm/ax avatar
ax-llm/ax

Ax: A TypeScript-First DSPy with Cross-Language Ambitions

The pretty much "official" DSPy framework for Typescript

2,924 stars194 forksTypeScriptApache-2.0

At a glance

What is it?
Ax brings DSPy-style typed generation, agents, flows, and optimizers to TypeScript, then compiles the same core to Python, Java, C++, Go, and Rust. The promise is real, but the cross-language story is where you need to look before adopting.
Who is it for?
Adopt Ax if you are a TypeScript team that wants DSPy-style structured generation without prompt engineering, and you value a thin hot path that stays close to raw provider calls. Do not adopt it if you need a stable multi-language story today: the non-TypeScript packages are generated and the README does not show how mature they are.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Ax Solves and Who It Is For

Ax is a framework for building with large language models using typed signatures instead of hand-written prompts. It is the self-described "official" DSPy framework for TypeScript, and it extends that model to Python, Java, C++, Go, and Rust. The core problem it addresses is the fragility of prompt engineering: you write a string like 'review:string -> sentiment:class "positive, negative, neutral"' and Ax handles the generation, parsing, and validation. This is aimed at developers who want structured outputs from LLMs without writing parsing code or managing retries manually. It is especially relevant for teams that work in TypeScript but may need to port logic to other runtimes later. The README claims the same signatures, agents, flows, and optimizers are compiled into verified libraries for other languages, which is a bold promise that needs verification.

The Signature DSL and Deployment Profiles

At the heart of Ax is the signature DSL. The README shows a simple example: you define a function-like string that maps inputs to outputs, including a class constraint for classification. The framework produces a typed result, such as a literal union for sentiment. You can also use a fluent builder or a Standard Schema validator like Zod, Valibot, or ArkType. This is not just a syntactic convenience; the signature is the contract that drives generation and validation. The deployment profile is a separate concept. You specify a provider by name, like 'openai' or 'anthropic', and that name determines the wire behavior, including the endpoint and reasoning rules. The model ID is resolved inside the profile. This means the same signature works across providers, but the profile selects how the request is actually made. For example, a DeepSeek model hosted by Together uses Together's endpoint, not DeepSeek's native format. This separation is useful for portability, but it also means you must trust the profile definitions for your chosen provider.

Agents, Flows, and Optimizers

The README describes a layered architecture. Signatures feed into AxGen, which is the typed generation core. From there, you can attach provider descriptors or build higher-level abstractions: AxAgent and AxFlow. Agents have runtime execution, context budgets, checkpoints, action-log replay, discovery, memory, skills, and delegation. Flows are typed program graphs with branches, loops, feedback, cache behavior, parallel execution, and a returns projection. Optimizers include GEPA, few-shot bootstrapping, and portable optimizer artifacts. This is a full DSPy-like stack, not just a single function. The exact semantics of agents and flows are not detailed in the README, so you will need to consult the repository's documentation to understand how they behave. The breadth is impressive, but it also means a steep learning curve if you want to use more than the basic generation.

Cross-Language Compilation: The Ambitious Part

The most distinctive claim is that Ax is not just a TypeScript library. The README says the same semantic core is compiled into Python, Java, C++, Go, and Rust packages. The generated source is checked in under packages/<language>, so you can inspect it. The repository includes a compiler that produces these packages from a shared intermediate representation called AxIR. When AxIR changes, you run 'npm run axir:generate-packages'. This is a significant engineering effort. The language matrix shows Python on PyPI, Java on Maven Central, C++ via CMake FetchContent, Go via go get, and Rust on crates.io. However, the README does not show any example of using these non-TypeScript packages beyond the import statement. It does show how to run examples in each language via 'npm run example -- <path>'. This suggests the examples are runnable, but it does not prove the libraries are complete or stable. As a technology editor, I see this as the highest-risk area: cross-language compilation is hard, and the README gives no evidence of how well the generated code works in practice.

Getting Started and Running Examples

To use Ax in TypeScript, you install the npm package '@ax-llm/ax' and import the functions. The README's 30-second example shows a classification task. You create an AI client with 'ai({ name: "openai", apiKey: process.env.OPENAI_APIKEY })', define a signature with 'ax(...)', and call 'classify.forward(llm, { review: "..." })'. The result is a typed object. For streaming, you have 'streamingForward()'. The repository also provides a runner for examples across languages. The command 'npm run example -- list' shows available examples, and you can run specific files for Python, Java, C++, Go, or Rust. This is a nice way to test the cross-language packages without knowing each build system. The README mentions a streaming benchmark you can run with environment variables for provider, model, and run counts. This is a concrete way to measure overhead on your own setup. The commands are specific and you can copy them directly.

Streaming-First Design and Latency Claims

Ax makes streaming the default. The README explains that this allows Ax to parse fields as they arrive, run streaming assertions, fail early, cancel the in-flight stream, and start correction without spending tokens on an invalid output. This is a sensible design for structured output, where you often know early that a generation is wrong. The hot path is described as intentionally thin: render the signature, call the provider, parse the result, and return a typed value. The README includes a streaming benchmark script for checking overhead on your own providers and models. It claims that recent runs on Claude and Gemini models show provider queueing and model generation dominate total latency, and AxGen stays close to the raw 'ai.chat()' path. However, these are the project's own claims, not independent measurements. You should run the benchmark yourself with your providers to see if the overhead is acceptable. The design philosophy is sound, but the proof is in the numbers.

Limitations and Wrong-Tool Cases

Ax is not the right tool if you need fine-grained control over every prompt token or if you prefer to write your own parsing logic. The signature DSL abstracts away the prompt construction, which is a benefit for speed of development but a drawback when you need unusual prompting strategies that the DSL cannot express. Also, the cross-language story is a double-edged sword. If you only need TypeScript, the extra compiler machinery is irrelevant overhead. If you need Python or Java, you must trust that the generated packages are fully functional and stay in sync with the TypeScript core. The README does not provide evidence of that beyond the existence of the packages. Another limitation is the dependency on deployment profiles. If your provider is not in the list, or if a profile is outdated, you may have to modify the framework or wait for an update. The README lists many providers, but not every possible API. Finally, the project is under active development with frequent releases, which means APIs may change. The last push is September 2026, and versions go up to 24.0.18, so there is a rapid release cadence.

Alternatives and Comparison

The obvious alternative is the original DSPy library for Python. DSPy is the source of the programming model that Ax adapts. The key difference is that DSPy is Python-first and has a mature ecosystem of optimizers and integrations. Ax is TypeScript-first and aims to compile the same core to multiple languages. If you are a Python-only team, DSPy may be more battle-tested. Another alternative is to use a provider SDK directly with your own validation layer. This avoids the abstraction overhead but requires you to write parsing and retry logic. Ax's value is in providing that layer for you. If you need a multi-language solution, Ax's compiler is unique, but you should compare it to maintaining separate SDKs per language. The README does not compare itself to any alternative, so this is my own assessment. The choice depends on whether you value the unified model across languages or the maturity of a single-language ecosystem.

Maintenance and Upgrade Cost

Ax is released frequently, with versions like 24.0.18 following 24.0.17 within days. This suggests an active maintenance cycle, but it also means you will need to keep up with changes. The README mentions a release document at docs/RELEASE.md that likely describes the package and release shape. The compiler is a key maintenance point: when AxIR changes, you must run 'npm run axir:generate-packages' to refresh the checked-in packages. This is a manual step that could be a source of drift if you forget it. The license is Apache-2.0, which is permissive and allows commercial use without requiring you to share your changes. However, you should check the license details for any third-party dependencies. The project is not archived, and the last push is recent, so it is actively maintained. The upgrade cost will depend on how often the API changes and how well the release notes communicate breaking changes. You should read the release notes before upgrading.

Editorial conclusion

Adopt Ax if you are a TypeScript team that wants DSPy-style structured generation without prompt engineering, and you value a thin hot path that stays close to raw provider calls. Do not adopt it if you need a stable multi-language story today: the non-TypeScript packages are generated and the README does not show how mature they are. Before committing, verify that your exact provider and model combination works with the deployment profile you plan to use, and run the streaming benchmark on your own hardware to confirm the latency overhead is acceptable. The project is actively released, but the cross-language compiler is the part that needs the most scrutiny.

Official sources

  1. ax-llm/ax on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes