The unified software stack for agents

BAML is a language with a vertically integrated toolchain that helps agents in production. Test and trace code, query data, build alerts, and replace 10+ separate tools.

deploy
BeforeIn production
Bring your own

11 separate products

BAML

Used by engineers at

  • Stitch Fix
  • Feather
  • SAP
  • AMD
  • EY
  • Akamai
  • Vetcove

Iteration loops are fast when everything speaks the same language.

We didn't want to build a programming language.

But to make something 100x better, you have to vertically integrate. So we built BAML, with a virtual machine that makes it run anywhere,

one that allows us to profile every function at barely any cost,

a compiler that knows about your errors in production,

and a data lake to query your program data: profiles, spans, logs, traces, and blobs.

Raptor 1, Raptor 2, and Raptor 3 engines side by side, drawn as a blueprint. Each one has fewer external parts than the last.

Build, deploy, observe, and improve with one CLI.

Build

Build with the best parts of TypeScript, Rust, and Go.

BAML is a fully open-source language designed for agents.

1type Label = "billing" | "bug" | "other";
2
3// 'AI function' syntax for easy extraction
4function classify(ticket: string) -> Label {
5 client: "openai/gpt-6-luna"
6 prompt: `
7 Classify this support ticket.
8 ${ticket}
9 `
10}
11
12function route(ticket: string) -> string {
13 let label = classify(ticket);
14 if (label == "bug") {
15 return "engineering";
16 }
17 return "support";
18}
Syntax like TypeScript.
If you can read TypeScript, you can read BAML. With unions, generics, and interfaces.
A type system like Rust.
Types exist at runtime. There's no any. No unchecked casts. Thrown errors are statically analyzed. Pattern matching is exhaustive.
Compiles as fast as Go.
baml check type-checks 60,000 lines in about 1.4 seconds (vs Go’s 1.2 seconds).
Tools for agents.
baml describe finds code by its structure, baml run runs any function from the command line, and a built-in baml test.

Deploy

Turn your program data into a queryable data lake.

The BAML runtime records your program as it runs and sends it to Boundary Cloud. There's no SDK to install and no collector to run.

Your app

triage.baml

function classify

function route

function load_ticket

BAML runtime

boundary cloud

data laketypes, spans, blobs

span_namedurationoutput
classify812msbilling
route4msurgent
classify790msbug

Hosted by us, in your own cloud, or on your machine

Your terminal

$ baml query

SELECT span_name, p95(duration)

FROM spans GROUP BY span_name

classify1.2s

route6ms

gpt-6-luna1,204 tokens$0.0042
claude-sonnet-5-51,388 tokens$0.0061

Trace AI calls automatically.

Every call to an AI function records the provider, the model, the tokens it used, and what it cost, next to its arguments and the parsed result.

  • route, 1100ms, starting at 0ms
  • load_ticket, 220ms, starting at 0ms, called by route
  • classify, 660ms, starting at 231ms, called by route
  • notify, 198ms, starting at 902ms, called by route
  • db_get, 132ms, starting at 6ms, called by load_ticket
  • parse_json, 72ms, starting at 143ms, called by load_ticket
  • render_prompt, 77ms, starting at 242ms, called by classify
  • gpt-6-luna, 462ms, starting at 330ms, called by classify
  • parse, 83ms, starting at 803ms, called by classify
  • send_email, 176ms, starting at 913ms, called by notify
  • query, 110ms, starting at 11ms, called by db_get
  • http, 451ms, starting at 336ms, called by gpt-6-luna
  • coerce, 55ms, starting at 809ms, called by parse
  • smtp, 132ms, starting at 924ms, called by send_email
  • stream, 385ms, starting at 396ms, called by http

Cost to profile$0

Profile everything.

Ordinary functions record how long each call took. It costs so little that Boundary Cloud doesn't charge for it.

ParseError in parse

at classifytriage.baml:14

at routetriage.baml:31

Get traces on errors, without changing code.

When a function throws, the runtime records where the error started and how it moved up the stack.

Observe

Create dashboards and alerts from your data.

Make custom dashboards that are 100% tied to your product by using the SQL-based query API.

Calls per minute

SELECT count(*) FROM spans GROUP BY minute

last 4 hours
Labels

SELECT output_value, count(*) FROM spans WHERE span_name = 'classify' GROUP BY hour, output_value

billingbugother
Latency by function

SELECT span_name, p50(duration), p95(duration) FROM spans GROUP BY span_name

route

p50 1.4s
p95 2.9s

classify

p50 1.3s
p95 2.4s
Share labelled other

SELECT avg(output_value = 'other') FROM spans WHERE span_name = 'classify' GROUP BY hour

alert firing on classify

ImproveComing soon

Roll out experiments 100x faster than your CI/CD runs.

The BAML runtime can track experiments and A/B test functions securely for you, without having to redeploy.

gpt-6-sol's share of classify's traffic, and what it cost

gpt-6-luna3.1% labelled other, $0.03 per 1k calls

gpt-6-sol0.3% labelled other, $0.65 per 1k calls

gpt-6-sol took 10% of classify's traffic on Monday, 50% on Tuesday, and 100% on Wednesday, replacing gpt-6-luna. The three days cost $6.71, $23.25, $51.58.

Adopt BAML incrementally.

Start with the language or with production. You don't have to move everything at once.

Start with the language.

Write one function in BAML and call it from your Python, TypeScript, Go, Rust, Java, Swift, or C++ app through a generated client.

Start with production.

Send OpenTelemetry traces to Boundary to get started, and move code into BAML for richer traces and better DX.

Get access to the BAML stack.

The stack is in private beta. Book a 45-minute call with the founders, and we'll set you up.