From baml
Use when calling BAML from host code, or when BAML needs a host capability it lacks (DBs, sockets, crypto). Today's supported host is Python via `baml generate` -> the `baml_sdk` package (NOT the older `baml_client` name). Covers the `generator target { ... }` block (in a `.baml` file, NOT TOML), the generated `b.<function>` API, and the host-bridge pattern (BAML shells out to a thin Python entrypoint via `baml.sys.shell`). Other host languages exist upstream but should not be assumed in this repo. Prerequisite: baml:core.
How this skill is triggered — by the user, by Claude, or both
Slash command
/baml:bridgesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Load this when the task crosses the BAML / host boundary. Host code calls BAML through the **generated `baml_sdk` Python package**; BAML reaches host capabilities through `baml.sys.shell` + a thin generic bridge.
Load this when the task crosses the BAML / host boundary. Host code calls BAML through the generated baml_sdk Python package; BAML reaches host capabilities through baml.sys.shell + a thin generic bridge.
Today's supported host is Python. TypeScript / Go / Ruby clients exist upstream but do not assume them here until the repo adds generators and examples for them.
generator blockGenerators live in a .baml file (usually baml_src/generators.baml), not in baml.toml. The block syntax is BAML, not TOML.
// baml_src/generators.baml
//
// NOTE: Generator field names and valid output_type values change across BAML
// releases. Treat this block as illustrative; copy from your checked-in
// generators.baml and run `baml generate` after edits.
generator target {
output_type "python/pydantic"
// Relative to baml_src/. Layout must match where `baml_sdk` is imported from.
output_dir "../"
default_client_mode "sync"
}
Run:
baml generate
This emits a baml_sdk Python package (typed entrypoints + types) at the configured output_dir. The package is baml_sdk, not the older baml_client name that appears in old docs.
# Import path matches generated layout — this guide assumes the package name `baml_sdk`.
from baml_sdk.sync_client import b
ticket = b.extract_ticket("refund request text")
print(ticket.title, ticket.priority)
output_type "python/pydantic").baml_sdk.async_client (when default_client_mode "async" or per-call).Use generated clients for product code. Use baml run for local debugging, scripts, demos, and CI checks.
BAML's for / in is sequential. For real concurrency, fan out at the host layer:
import asyncio
from baml_sdk.async_client import b
async def triage_many(emails):
return await asyncio.gather(*(b.classify_email(e) for e in emails))
When parallelism inside BAML is acceptable, write the loop in BAML and let it run sequentially.
Use a host bridge only when the task needs a capability BAML doesn't yet provide well: databases, sockets, crypto, advanced byte processing, browser/server runtimes, vector ops, or a missing stdlib primitive.
The bridge should be thin, generic, and protocol-driven.
// ---------------------------------------------------------------------------
// BRIDGE SKETCH — inline comments go stale fast.
// Path, interpreter (python3 vs uv run vs venv), and argv layout drift from
// what this markdown shows. Read the actual bridge entrypoint + JSON schema in
// the repo before editing a real bridge.
// ---------------------------------------------------------------------------
class BridgeRequest {
op: "query" | "execute" | "sign",
payload: json,
}
class BridgeResponse {
ok: bool,
data: json?,
error: string?,
}
function call_bridge(req: BridgeRequest) -> BridgeResponse {
let payload_json = baml.json.stringify(req.to_json());
let request_path = ".baml_bridge_request.json";
baml.fs.write(request_path, payload_json);
// Same caveat: command line below is illustrative; sync with your bridge script.
let out = baml.sys.shell("python3 bridge.py " + request_path, null);
if (!out.ok()) {
throw "bridge exited " + baml.unstable.string(out.exit_code) + ": " + out.stderr.to_string();
};
baml.json.from_string<BridgeResponse>(out.stdout.to_string())
}
Note: baml.sys.shell(cmd, options?) returns ShellOutput { stdout: uint8array, stderr: uint8array, exit_code: int } plus .ok(). Decode the byte buffer with .to_string() before handing it to baml.json.from_string<T>. baml.json.stringify(req.to_json()) round-trips a typed request to JSON.
Bridge rules:
baml run --output json.Inline comments in bridge sketches go stale. Always cross-check
python3vsuv run, argv shape, env wiring, and the JSON envelope against the real bridge entrypoint and tests in your repo before relying on them.
BAML handles well:
Reach for a bridge when:
baml describe confirms is missingKeep the BAML surface clean even when you bridge. The bridge should be replaceable when the stdlib catches up.
[[generator]] in baml.toml — wrong. Generators are a generator <name> { ... } block in a .baml file.baml_client — that's the old name. Today it's baml_sdk.baml generate after every schema change. Wire it into your dev loop (file watcher, pre-commit, make generate).baml run from product code when baml_sdk is available — slow and brittle. Use generated clients in product paths.baml.sys.shell inside tight loops — repeated shell calls dominate runtime and make tests flaky. Prefer one structured bridge call over many tiny ones.op / payload protocol; keep domain rules in BAML.extern function. BAML reaches host capability via baml.sys.shell + a generic bridge.npx claudepluginhub boundaryml/baml-skill --plugin bamlProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.