← Case Studies
Case 002construction202616 weeksBuilt at Heizen

Weeks of Schedule Setup, Compressed Into a Document Dump

Project setup took schedulers weeks of reading documents before the first credible plan. The system had to turn a document dump into a P6-importable schedule a professional would take seriously.

Stack
LangGraph
Claude / Bedrock
FastAPI
PostgreSQL
Primavera XER
Job queues
Scale
2026
16w
01Context

Construction project setup is not a calendar UI problem. Before a scheduler can put dates on a board, they read contracts, drawings, bills of quantities, method statements, productivity tables, and the half-written assumptions that never made it into one clean brief.

At Heizen I worked on the AI side of a construction scheduling product: turn project documents into a Primavera P6–importable programme. The path is document dump → parse and profile → tool-using schedule agent → typed blueprint → deterministic finalize gates → a schedule a professional can open in P6.

No client names. No public integration surface. The domain does not hide: how you schedule is the job. A pretty Gantt that invents the critical path is worse than a slow plan that is right.

02The Challenge

A skilled scheduler does not "fill in dates." They reconstruct a project: predecessors, calendars, quantities, productivity rates, procurement tails, and constraints buried across files. That work was taking weeks per project — not because people were slow, because truth was scattered and every site restarted the reading marathon.

The naive product pitch is easy: upload docs, get a schedule. It fails the first time a professional opens the output. Invented activities. Missing foundations. Durations that collapse the critical path because nothing was grounded in BoQ or rates. An export that will not import cleanly into P6.

The real ask: take the dump seriously, force evidence and validation before export, and produce a draft worth the first review meeting.

Before — weeks of manual project setup

In construction, how you schedule is the job. A pretty timeline that is wrong is worse than a slow one that is right.

03Documents Become Foundation, Not Background Reading

Ingestion is its own pipeline, not a prompt preamble. Files land in background workers: classify pages, parse PDF ranges with specialized document parsers (and a local fallback when the provider fails), stage tabular and XER inputs, and store parsed text plus original files the agent can still open when it needs structure that plain text loses.

After parse, foundation profiling scores each document for capabilities — BoQ, productivity, resources, key dates, scope — so the agent knows which file to read for what instead of treating every PDF as equal background noise. At generation time, that foundation (and tenant defaults when project docs are thin) feeds productivity lookups and finalize-time checks.

A run only sees documents explicitly staged for that attempt. If something is not in the run’s evidence set, the agent cannot use it. That boundary is deliberate.

04The Schedule Agent and the Shipping Gate

Generation is a LangGraph tool-use loop on Claude (via Bedrock or equivalent), run asynchronously with budgets, cancel, and tracing.

The agent does not emit freeform Gantt prose. It builds a typed schedule blueprint — WBS, activities, predecessors, calendars, resources, verification — using tools to list and read project documents, inspect staged files, look up foundation and org standards, analyse critical path, gap-check scope, pre-validate, and only then finalize.

Finalize is the shipping gate. Before any XER leaves, the blueprint must pass ordered checks: schema validation, proof the agent re-validated after the last edit, coverage checks, WBS overload and underpopulated-leaf rules, floating-branch anchoring, LOE-on-critical-path limits, float-ceiling offenders, calendar coverage, and more. Hard failures block; the agent patches and retries. Soft issues advise. On budget exhaustion, the system can finalize from the best scored snapshot rather than returning nothing.

Export is deterministic: blueprint → calendar-aware CPM → XER for P6. Separate engines then audit existing programmes (industry schedule-quality checks and contract-level rules) without pretending generation and audit are the same model call.

Durations are a design problem of their own. Unlabelled tasks defaulting to a flat number collapses programme span. The system pushes duration basis — template analogue, quantity-scaled, document citation, milestone — so lengths are recomputable and verifiable, not silent guesses. Quantities and rates should come from the project's own documents (and templates), not a hardcoded keyword list.

Generate path — docs in, blueprint gates, XER out
05What We Refused to Ship

One blob prompt to "make a Gantt." Extraction, sequencing, and P6 export fail differently; collapsing them hides the real bug.

Finalize without re-validation. Without a hard link between the last edit and a clean validate pass, the agent learns to bounce off export and patch until something sticks — burning iterations.

Silent duration defaults. A schedule that looks dense but is a fraction of the real span is not faster setup; it is false confidence.

Human out of the loop. The product optimizes for time-to-first-credible-plan and a file that opens in P6 — not for zero scheduler judgment.

06The Result

Schedulers no longer start from a blank board and a stack of PDFs. The system takes the dump, builds foundation-aware structure, runs a tool-using agent against real documents, and only then emits a gated, P6-importable draft — activities with evidence hooks, calendars that had to declare what they serve, failures that return as stages you can debug.

The measure that mattered was not "AI drew a timeline." It was whether a professional could use the output as the first real draft of a critical schedule and continue in Primavera, without redoing the entire reading marathon by hand.

I would surface document conflicts earlier as first-class objects (not only as agent retries), and keep extraction quality scored separately from schedule quality so a beautiful critical path built on bad BoQ extraction is not misdiagnosed as a CPM bug.

When the domain is critical and the inputs are messy, treat documents as evidence and export as a gate — not a prompt that treats PDFs as background reading.