Materializing is the handoff from design time to run time. A compiled shape is a
draft until you materialize it to a project; once you do, it governs that
project’s graph and the SDK can read and write against it.
Materialize
After a clean compile, materialize the shape to your project.
| Tool | What it does |
|---|
shape_workbench_materialize | Materialize the compiled shape to its project. |
shape_workbench_project_grammar | Inspect the project’s grammar after materializing. |
shape_workbench_materialize defaults to a dry run and requires a
review_note describing the change. Nothing commits until you call it with
apply: true and dry_run: false. Read the dry-run result first, then apply.
The handoff to the SDK
Once a shape is materialized, it is live for the runtime. From the SDK you can:
// The shape you designed in the Workbench is now readable from the runtime.
const schema = await pb.shapes.schema("shp_contract_terms");
// And you can extract source material through it. `source` takes the text
// to extract from — a plain string, or an object with `text` plus metadata.
await pb.extract({
source: { text: contractText, external_id: "contract-2026-001" },
shapeId: "shp_contract_terms",
apply: false,
});
Versioning
Shapes are versioned. When you change a materialized shape, compile and diff the
draft, plan the migration, then materialize the new version. The
shape_workbench_version_graph and plan_migration tools
cover this.
Design the shape, materialize it, then build against it with the SDK. That
cascade, design time then run time, is the whole point of keeping the two
surfaces distinct.