mrkeyoor.com_
Sat 26 Sept 18:46 UTC
LLM Toolsevaluationupdated 25 Aug 2026

baml review

BAML is a programming language and toolchain for defining typed LLM functions, prompts, provider settings, tests, and generated application clients. It is meant to replace hand-written provider calls and JSON cleanup with one schema that can generate clients for languages including Python, TypeScript, Go, Java, C#, Ruby, and Rust.

+85stars / 7d
Verdict

Our BAML checkout installed 2,528 packages and consumed 3,740 MB, then both build and test failed at the Python language-client task, so source contributors need more patience than the user quickstart suggests. BAML is worth a trial when structured LLM calls have spread across providers and languages, because one typed definition can replace duplicated prompt and parsing code. Keep the pilot behind regression tests if coercion behavior or exact provider request shapes affect correctness.

We ran it

Lab card: what happened when we ran bamlScreenshot of baml (boundaryml.com/explore)
Install✓ · 90s2528 packages · 3740 MB
Build✗ · 26s
Tests✗ · 21sran, no count parsed
Repo10891 files~2,211,842 lines of source · 144.4 MB · 48 CI workflows

Answers from our run

Does baml build from source?

Dependencies installed in 90 seconds (2528 packages), and the build failed. We cloned commit 42117dc into a clean Debian container with 3 CPUs and no project-specific setup.

Do baml's tests pass?

The test command failed in our container, and its output did not report a pass or fail count.

Who should not use baml?

Teams unwilling to add a language and generated-client step to their build: BAML functions live in baml_src, and generated client code is not meant to be edited.

What are the alternatives to baml?

Instructor, Guardrails AI, Pydantic AI. Our BAML checkout installed 2,528 packages and consumed 3,740 MB, then both build and test failed at the Python language-client task, so source contributors need more patience than the user quickstart suggests.

Setup2/5User start is short; the source monorepo failed build and test
Docs4/5Detailed language, provider, testing, and deployment references
Community5/5Pushed Aug 25 with same-day issue and pull-request activity
Maturity3/5Useful toolchain with active 0.17 regressions and nightlies

Discussed on

  1. hnShow HN: BAML - A new programming language to get structured data from LLMs18 points
  2. hnBaml: The Programming Language for Agents8 points
  3. hnBAML is a language that helps you get structured data from LLMs4 points

Who it’s for

Teams whose LLM features return structured objects and need types shared between prompts and application code.
Developers switching among hosted providers or OpenAI-compatible local models.
Product teams that want prompt previews, saved eval cases, retries, fallbacks, and streaming types in one workflow.
Claude Code users who want BAML's installable agent support to edit and run the language with project context.

Who it’s NOT for

Teams unwilling to add a language and generated-client step to their build: BAML functions live in baml_src, and generated client code is not meant to be edited.
Projects that only make one simple free-text model call: a provider SDK has fewer moving pieces than this 10,891-file monorepo.
Systems that must reject every imperfect structured response: BAML's schema-aligned parser intentionally repairs outputs, and issue #4590 reports a case where uncoercible array elements were silently dropped.
Consumers that require request bytes to remain stable across upgrades: issue #4585 reports a 0.15 to 0.17 OpenAI-compatible wire-format change without a migration note.
Contributors with limited disk or time for the full workspace: our install occupied 3,740 MB, and both build and test stopped on the Python language-client build.

Setup reality

Our pnpm install succeeded in 90 seconds, pulling 2,528 packages and using 3,740 MB on disk. The repository itself was 144.4 MB with 10,891 files and roughly 2,211,842 source lines, far beyond the scope implied by the four-command user quickstart.

Using BAML requires a model provider key or an OpenAI-compatible endpoint, a baml_src definition, generated client code, and the matching application package. The IDE workflow adds an editor extension; switching providers may add separate environment variables and model options.

The build failed in 26 seconds and tests failed in 21 seconds. Both stopped at @baml/language-client-python; the log also showed Rust 1.93.0 channel synchronization. The tail names the failed task but not its underlying error, so we cannot attribute it to Rust, Python, networking, or the repository.

Typed LLM functions replace repeated provider glue

BAML puts model functions in their own source files. A function declares input and output types, chooses a client, and contains the prompt. The generator then produces application code and matching types for the selected host language. This arrangement keeps a resume extractor's schema, prompt, provider choice, and result type together instead of copying them between an SDK call, a validator, and handwritten parsing code.

The current README calls BAML a programming language for agents and lists clients for TypeScript, Python, Go, C#, Java, and other languages. The repository is correspondingly large: our clone contained about 2,211,842 lines across 10,891 files. Adopting BAML is an architectural choice, especially in a polyglot team. Generated code belongs in the workflow, and the docs warn developers not to edit the generated baml_client directory.

Schema-aligned parsing accepts messy model output

BAML's distinctive behavior is schema-aligned parsing. It tries to turn imperfect model text into the declared result instead of requiring exact JSON syntax. That can be useful when a model adds commentary, misses quotes, or emits a value in a nearby representation. Types remain available to generated clients, while prompts can insert the output format through ctx.output_format.

Permissive repair needs its own correctness tests. Issue #4590 reports BAML 0.17 dropping array elements it could not coerce and returning success without a warning. Issue #4589 describes a nested optional class value being replaced with null. Those are open reports rather than settled conclusions, but they identify the failure mode to test: a syntactically valid result may still have lost input-derived data.

Provider switching stays inside the function definition

A short client string can select an OpenAI or Anthropic model, while named clients expose base URLs, headers, temperature, API keys, retries, and routing. OpenAI-compatible local endpoints fit the same model. Runtime registries can select another client for a request, which is useful for controlled traffic splits or failover without duplicating the function's output schema.

That portability does not make providers identical. BAML still sends provider-specific requests, and issue #4585 reports that the OpenAI-generic message content shape changed between 0.15 and 0.17. Software that signs, records, or byte-compares outgoing requests needs version-pinned fixtures. The latest GitHub release on August 25, 2026 was a 0.17.1 nightly, another reason to separate experimental upgrades from a production baseline.

Tests cover behavior, including multimodal inputs

Test blocks sit beside BAML functions and can provide text, images, audio, PDFs, or video as file paths, URLs, or base64 data. Checks can record a property without stopping the rest of the test, while assertions halt that case on failure. The command line can run all tests, select a function, list cases, or set parallel execution. The editor playground also previews the rendered prompt and raw request.

These facilities help only when teams write cases that detect semantic loss. The repository's 48 CI workflow files indicate a serious internal validation effort, yet our workspace test still failed before reaching a suite result. For an application, include awkward nested objects, missing optional members, partial arrays, provider fallback responses, and exact request-shape fixtures where compatibility matters. BAML reduces test plumbing; it does not decide which wrong result would hurt the product.

What happened when we ran it

Our sandbox installed 2,528 pnpm packages in 90 seconds and used 3,740 MB on disk at commit 42117dc. The clone itself occupied 144.4 MB. Installation succeeded without secrets in an unprivileged Node 22 container, which proves the dependency graph resolved in that environment. It also shows the source workspace is much heavier than installing a released CLI for ordinary use.

The build failed after 26 seconds. Turbo reported 2 successful tasks out of 14 before @baml/language-client-python exited with code 1. The tail also shows @baml/rpc starting a Rust binding export and Rustup synchronizing channel 1.93.0. It does not include the lower-level error from the Python client, so the honest finding ends at the named task.

Tests failed after 21 seconds at the same @baml/language-client-python build, with 2 cached tasks and 2 successful tasks out of 15. No test count was produced. The summary says the lifecycle test command failed because that prerequisite build failed. On our box, we never reached evidence about BAML's test assertions themselves.

Fast development is offset by language and release risk

For a team already maintaining several structured model functions, BAML can remove real repetition. Prompt previews expose the rendered request, generated types keep host applications honest, and provider configuration has one home. Semantic streaming also models partial output states so a user interface can distinguish an unfinished field from a completed one.

The cost is ownership of another language toolchain. The source tree spans Rust, pnpm workspaces, generated SDKs, editor tooling, and bindings for several host languages. With 328 open issues and pull requests on August 25, activity is high, and same-day work covered the compiler, LSP, runtime schemas, and dependency updates. Teams should adopt one pinned release, exercise their actual schemas, and upgrade only after those cases pass.

Alternatives

ProjectWhat it isPick it when
InstructorA library that adds validated structured outputs and retries to existing model SDK calls.pick this instead when you want typed extraction inside normal Python or TypeScript without adopting a separate prompt language.
Guardrails AIA validation framework for checking and correcting model inputs and outputs.pick this instead when validation policies matter more than generated multi-language clients and provider routing.
Pydantic AI gh↗A Python agent framework built around Pydantic models, tools, and typed dependencies.pick this instead when the application is Python-first and you want agents plus structured results in one native library.

What people are saying

  1. [github-trending] BoundaryML/baml

Sources

  1. BAML README
  2. BAML repository
  3. BAML 0.17.1 nightly release
  4. BAML testing guide
  5. Silent array element loss report #4590
  6. OpenAI-generic request change report #4585

More llm tools reviews

llm-wiki-compiler · claude-skills · Humanizer-zh · agent-beacon · MiMo-Code · pi-claude-bridge · the whole board →