# car-builder
Natural-language → validated [`car-workflow`](../car-workflow) manifest builder
for the Common Agent Runtime.
Describe what you want in plain English; the builder prompts a model to emit a
workflow manifest, **validates it with the runtime verifier**
(`car_workflow::verify_workflow`) instead of trusting the model, and feeds the
concrete validation errors back for a bounded number of repair attempts.
## Design: generation is injected
`build_workflow` is generic over an async `generate(prompt) -> text` closure, so
this crate has **no inference dependency**. The CLI / server / FFI wire the real
`car-inference` engine; tests inject a fake generator. The reusable,
deterministic part — prompt → parse → verify → repair-loop — is unit-tested
without a model.
```rust,no_run
use car_builder::{build_workflow, BuildRequest, ToolCatalog};
# async fn ex() {
let req = BuildRequest {
goal: "research a stock, then have a human approve the summary".into(),
catalog: ToolCatalog::default(),
existing: None, // Some(workflow) to edit instead of create
feedback: None, // human revision feedback from an approve/revise loop
max_attempts: 3,
};
let result = build_workflow(|prompt| async move {
// call your model and return its text
your_model.generate(prompt).await
}, &req).await;
if result.valid {
// result.workflow is a verified car_workflow::Workflow — save or run it
}
# }
```
## What it guarantees
- The returned workflow (when `valid`) passes `verify_workflow`: reachable
stages, no dangling edge/compensation references, approval gates with a
non-empty `output_key`, and proposal stages that pass `car-verify`. When a
catalog of tools is supplied, it also references only known tool names.
Semantic findings — edge-condition keys and state dependencies that no stage
produces — are returned as non-blocking `warnings` (and fed back as repair
hints); they don't flip `valid`, since they can false-positive on keys
produced at runtime.
- Output parsing tolerates markdown fences, preamble, and trailing commas via
`car_ir::json_extract`, and surfaces serde's error (e.g. the missing field)
back to the repair loop.
- On failure after `max_attempts`, the last parseable-but-invalid workflow and
the remaining issues are returned for inspection.
## CLI
```bash
car build "research a stock, then have a human approve the summary"
car build --update ~/.car/workflows/foo.json "add a verification stage before approval"
```
The CLI generates, validates, prints a summary, and (unless `--yes`) offers an
approve / revise / no loop before saving to `~/.car/workflows/<id>.json`.