Verified DSL Code Generation for Regulated Workflows

Agentic AI Systems advanced Building with AI ~34 min read

Overview

Regulated software teams often need to turn large, ambiguous policy documents into executable business logic under severe deadlines. Tax, healthcare, insurance, lending, and government systems all share the same shape: the source material is prose, the implementation target is a specialized internal language or rules engine, and the acceptable error rate is near zero. A general coding agent can accelerate analysis, but it cannot be the trust boundary.

The pattern in Intuit’s tax-code workflow is to split the work into three layers. General-purpose LLMs summarize and reconcile long documents. Domain-aware generation tooling translates only the relevant provisions into a proprietary domain-specific language. Deterministic validation, custom test tooling, and human subject-matter review decide whether the generated artifact is shippable.

This is not ordinary prompt-to-code automation. The model is used where probabilistic language understanding is valuable, then boxed into narrow generation tasks whose outputs can be checked by deterministic systems. The training objective for engineers is to design the scaffold around the model: anchors, dependency maps, DSL constraints, test harnesses, failure localization, and approval gates.

Core Concepts

Document Reconciliation Before Generation

Regulatory source material frequently arrives in multiple forms: draft bills, amended versions, agency guidance, forms, examples, and legacy references. Before code generation starts, the system must identify stable anchors such as statute sections, policy identifiers, line items, form fields, or rule IDs. The model can summarize each source, but the scaffold should preserve citations and anchor mappings so later stages know exactly which provision drove each generated rule.

Domain-Specific Language Boundary

A DSL narrows the generation target. Instead of asking a model to modify arbitrary application code, the workflow asks for constrained rule artifacts: eligibility predicates, calculation formulas, field mappings, validation clauses, or state transitions. This reduces the output space and gives deterministic tools something concrete to parse, lint, execute, and diff.

Verification as the Shipping Gate

LLM-based evaluation can help triage generated output, but it is not the final authority in regulated workflows. The final gate should be deterministic where possible: parser checks, type checks, golden test cases, property tests, simulation runs, trace comparisons, and expert review. The important design rule is that generation is probabilistic, while release approval must be evidence-driven and reproducible.

Key Concept: The Model Drafts, the Harness Decides

Use LLMs to compress reading time and draft candidate rules, but place the release decision in a domain-specific harness that can explain failures, reproduce results, and map every generated artifact back to source evidence.

How It Works

Stage 1: Extract and Reconcile Policy Anchors

The first stage converts unstructured policy text into a structured change set. The model reads the source documents, identifies provisions relevant to the product, maps each provision to a stable anchor, and reconciles differences between versions. This stage should produce artifacts that humans can inspect before generation begins.

type ProvisionChange struct {
    AnchorID       string   `json:"anchor_id"`
    SourceURL      string   `json:"source_url"`
    AppliesTo      []string `json:"applies_to"`
    EffectiveDate  string   `json:"effective_date"`
    PriorRuleRefs  []string `json:"prior_rule_refs"`
    ChangeSummary  string   `json:"change_summary"`
    EvidenceSpans  []Span   `json:"evidence_spans"`
}

func reconcileVersions(houseDoc, senateDoc Document) []ProvisionChange {
    house := extractAnchoredChanges(houseDoc)
    senate := extractAnchoredChanges(senateDoc)
    return mergeByAnchor(house, senate)
}

The key engineering choice is to carry the source anchor forward. If the generation later fails a test, reviewers need to trace the failing rule back to the exact policy span rather than reverse-engineering why the model wrote it.

Stage 2: Generate a Narrow DSL Artifact

The generation prompt should not ask for arbitrary code. It should provide the DSL grammar, allowed symbols, existing rule references, examples of valid rules, and explicit output schema. A constrained target makes automatic validation meaningful.

# Generated rule artifact
rule child_credit.phaseout_2026 {
  source_anchor = "SEC-110201"
  effective_on = "2026-01-01"

  when taxpayer.filing_status in ["single", "head_of_household"] {
    threshold = money(200000)
  }

  when taxpayer.filing_status == "married_joint" {
    threshold = money(400000)
  }

  reduce credit_amount by phaseout(taxpayer.modified_agi, threshold)
}

The artifact is intentionally boring. It has no network calls, no hidden side effects, and no access to application internals beyond approved symbols. That restriction is what lets downstream validation catch malformed or unsupported logic before it enters production code.

Stage 3: Localize Failures and Repair in Context

A strong harness reports more than pass or fail. It identifies the failing rule segment, the source anchor, the fixture that failed, and the expected versus actual result. The repair loop can then ask the model to revise only the narrow rule segment while preserving test intent and source mappings.

Practical Applications

Tax and Benefits Calculation Engines

Tax preparation, benefit eligibility, and subsidy systems often encode statutory text as calculation rules. LLMs can accelerate provision extraction and dependency mapping, while deterministic fixtures check known household profiles, income ranges, phaseouts, dates, and edge cases. Human reviewers remain essential because the law may contain ambiguity that no model should silently resolve.

Healthcare and Insurance Policy Automation

Clinical prior authorization, claims adjudication, and insurance coverage rules are well suited to a constrained DSL boundary. The source material is long and domain-heavy, but the runtime artifact can be a limited set of predicates, exclusions, codes, and calculation rules. The harness should include synthetic cases, historical cases, and denial/approval explanations.

Enterprise Workflow Compilation

Compiled AI systems use LLMs during a build phase to produce executable workflow artifacts that later run without model calls. This is valuable when runtime inference would be expensive, non-deterministic, or exposed to prompt injection. The same pattern applies to document processing, routing policies, compliance checklists, and back-office decision workflows.

Implementation Patterns

Separate Analysis, Generation, and Validation Queues

Keep each phase explicit. Analysis creates structured changes. Generation creates candidate DSL artifacts. Validation produces signed evidence bundles. Mixing these phases in one chat transcript makes audit difficult and lets unverified assumptions slip into code.

type PipelineState string

const (
    StateAnalyzed   PipelineState = "analyzed"
    StateGenerated  PipelineState = "generated"
    StateValidated  PipelineState = "validated"
    StateApproved   PipelineState = "approved"
)

type RuleBundle struct {
    ID             string
    State          PipelineState
    Changes        []ProvisionChange
    GeneratedRules []string
    TestReport     *ValidationReport
    ExpertApproval *Approval
}

Make the Test Harness Domain-Specific

Generic pass/fail tests are too weak for regulated code generation. The harness should understand domain objects, fixture provenance, explanation fields, tolerances, and invariant classes. For a calculation engine, failures should identify the specific formula branch and input profile; for a claims engine, they should identify the predicate that changed the decision.

type RuleFailure struct {
    RuleID        string
    AnchorID      string
    FixtureID     string
    Segment       string
    Expected      Decimal
    Actual        Decimal
    Explanation   string
}

func ValidateBundle(bundle RuleBundle, fixtures []Fixture) ValidationReport {
    report := ValidationReport{}
    for _, rule := range bundle.GeneratedRules {
        parsed := parseAndTypecheck(rule)
        report.AddStaticChecks(parsed.Checks)
        report.AddScenarioResults(runFixtures(parsed.Program, fixtures))
    }
    return report
}

Preserve Human Review as a First-Class Step

Subject-matter experts should review source mappings, edge cases, and validation failures inside the same workflow, not in a disconnected document. Their approval should reference bundle IDs, source anchors, fixture sets, and validation report versions so the final artifact is auditable.

Performance Considerations

Common Pitfalls

Further Reading