cd /news/ai-agents/how-our-pipeline-orchestrates-lbo-du… · home › topics › ai-agents › article
[ARTICLE · art-169020] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

How our Pipeline orchestrates LBO Due Diligence ?

A developer built a bilateral multi-agent hierarchy, governed by Domain-Driven Design, that orchestrates LBO due diligence across disparate financial statements using a deterministic five-step DAG. A generalist crew manager negotiates with a domain specialist advisor to produce the execution plan, while independent balance sheet extractions run in parallel and cross-table ratios wait on upstream inputs before converging into a final decision policy. The design aims to prevent semantic inversion and hallucination in boardroom-level financial synthesis, following earlier work on response-only masking and rejection circuit breakers for an 8B specialist model.

by read10 min views5 publishedNov 13, 2026

Welcome to the third chapter of our four-part series, Building Sovereign, Hallucination-Free Financial AI. In Part 1: Building a Deterministic Financial Agent with Dual-Persona LoRA, we prohibited probabilistic language models from performing arithmetic. In Part 2: How our Training Recipe led us to "Hallucination", we stepped into the machine room: fine-tuning an 8B model.

Today, we address the ultimate frontier: What happens when the financial question cannot fit into a single prompt or table? How do we orchestrate complex, multi-step workflows like a Cross-Table LBO Due Diligence across disparate financial statements—and how do we ensure the final synthesis sent to the boardroom is 100% immune to semantic inversion and hallucination?

In Part 2, we showed that when an 8B specialist model encounters missing variables in a messy financial filing, standard RLHF conditions it to panic: it grabs loosely related numbers from adjacent rows to satisfy the prompt, falling directly into the Compensation Hallucination Trap.

We fixed this at the micro-level with response-only masking and rejection circuit breakers. But in enterprise finance, you quickly encounter a macro-level barrier:

Imagine handing an autonomous agent an audited annual report (like the official French standalone filing — comptes sociaux — of Renault SAS, Renault Group's main operating subsidiary) and asking:

"Is a leveraged buyout (LBO) of this target financially feasible based on its latest audited accounts?"

Answering this is not a one-shot retrieval problem. It requires navigating across multiple disparate accounting schedules:

CAPACITE D'AUTOFINANCEMENT, a proxy for pre-CapEx operating cash flow in French GAAP) in the Cash Flow Statement (RESULTAT D'EXPLOITATION / CHIFFRE D'AFFAIRES). If you shove all these tables into a single context window and ask an 8B model to reason through all five steps at once, attention anxiety returns with a vengeance. The model conflates standalone operating subsidiary debt with consolidated group figures, divides equity by operating profit, or produces subtle, catastrophic semantic inversions.

To solve this, we must enforce Separation of Concerns at the system architecture level.

Instead of burdening a single specialist model with planning, document navigation, tool invocation, and narrative synthesis, we architected a Bilateral Multi-Agent Hierarchy governed by Domain-Driven Design (DDD).

What is a Multi-Step DAG? A Directed Acyclic Graph (DAG) is a deterministic task pipeline where execution flows strictly forward from prerequisites to dependent outputs (Directed) with zero infinite loops (** Acyclic**). Independent balance sheet extractions run in parallel, while cross-table ratios wait for their exact upstream inputs before converging into the final decision policy.

flowchart TD
    User(["💼 Boardroom Prompt:\n'Is an LBO takeover feasible?'"]) --> CrewMgr["👔 Generalist Crew Manager\n(Hierarchical Task Planner & Arbiter)"]

    subgraph BilateralLoop ["🤝 Bilateral Multi-Agent Negotiation"]
        CrewMgr <-->|"1. Evaluates Balance Sheet Rubrics"| SpecAdv["🧠 Domain Specialist Advisor\n(LboCovenantPolicyVO & Accounting Ontology)"]
        SpecAdv -->|"2. Proposes 5-Pillar Credit Plan"| DAG["⚡ Execution Plan (5-Step DAG)"]
    end

    subgraph ExecutionCore ["⚙️ Deterministic Execution Sandbox"]
        DAG --> T1["Pillar 1: Debt Service (YoY CAF)"]
        DAG --> T2["Pillar 2: Historical Deleveraging (YoY Debt)"]
        DAG --> T3["Pillar 3: Cash Flow Coverage (Debt / CAF)"]
        DAG --> T4["Pillar 4: Balance Sheet Gearing (Debt / Equity)"]
        DAG --> T5["Pillar 5: Operating Margin Cushion"]
        T1 & T2 & T3 & T4 & T5 --> PyDec["🐍 Python Decimal Runtime (IEEE-754)\n+ Physical Same-Row Grounding [p.X]"]
    end

    PyDec --> DraftSynth["📝 Executive Synthesizer\n(Draft Decision Memo)"]

    subgraph AdversarialGate ["🛡️ Adversarial GenRM Gatekeeper"]
        DraftSynth --> GenRM{"⚖️ GenRM Critic\nAdversarial Reward Auditor"}
        GenRM -->|"❌ REJECT (Polarity contradiction / Tol > 0.05%)"| SelfCorrect["Self-Correction Loop"]
        SelfCorrect -.-> DraftSynth
        GenRM -->|"✅ CERTIFIED (100% Grounded & Directionally Verified)"| FinalReport["🏆 Certified ComEx Due Diligence Memo\n(Ready for Boardroom Delivery)"]
    end

The Specialist Advisor does not write paragraphs of text. Its sole responsibility is to evaluate available physical table rubrics against declarative banking covenants:

@dataclass(frozen=True)
class LboCovenantPolicyVO:
    """Invariants of LBO banking feasibility (Domain-Driven Design)."""
    max_repayment_years: float = 3.5       # Standard senior debt covenant (< 3.5x)
    critical_repayment_years: float = 5.0  # Junk debt alert threshold
    max_gearing_pct: float = 100.0         # Max Debt / Equity ratio
    min_operating_margin_pct: float = 3.0  # Operating safety buffer

    def evaluate_deal_feasibility(
        self, repayment_years: float, gearing_pct: float, margin_pct: float
    ) -> tuple[str, str]:
        if repayment_years > self.critical_repayment_years or gearing_pct > self.max_gearing_pct:
            return "UNFAVORABLE", "Debt repayment horizon exceeds banking covenants."
        if repayment_years > self.max_repayment_years:
            return "RESERVED", "Requires mezzanine financing or subordinated vendor loan."
        return "FAVORABLE", "Robust cash flow profile meets senior debt underwriting criteria."

When the Generalist Crew Manager receives the LBO query, it feeds the extracted table headers to the Specialist, which compiles an ExecutionPlanDTO composed of 5 non-negotiable credit pillars:

compute_pct_change. DETTES FINANCIERES Note E.4). Tool: compute_ratio(scale="RAW"). CAPITAUX PROPRES Note E.1). Tool: compute_ratio(scale="PERCENT"). RESULTAT D'EXPLOITATION) / Revenue ( CHIFFRE D'AFFAIRES Note C.1). Tool: Because each task has designated keywords and an explicit formula, the tasks execute sequentially or in parallel against our Physical Grounding Engine.

As established in Part 1, all tool calls are executed in Python using exact Decimal arithmetic.

In our Renault SAS 2024 benchmark test ([LOGS_ECHANGE_GEN_SPEC_LBO_RENAULT.md]), the runtime produces audited outputs anchored to exact physical lines:

{
  "metric_label": "Ratio de couverture Dette / CAF (années)",
  "tool_name": "compute_ratio",
  "operands": {
    "numerateur": 10587000.0,
    "denominateur": 1245000.0
  },
  "resultat_brut": 8.503614457831325,
  "resultat_arrondi": 8.5,
  "unite": "ANNEES",
  "citation": "[p.42, Note E.4 & p.40, TAF]"
}

The arithmetic outcome is definitive: 8.50 years of cash flow are required to extinguish existing debt. According to LboCovenantPolicyVO ($> 5.0\text{ years}$), an LBO without massive capital restructuring is strictly unfeasible.

Now comes the ultimate vulnerability: How do we guarantee the LLM does not distort this finding when writing the final executive briefing?

Most agent frameworks rely on the LLM's own self-critique (e.g., "Review your previous response and fix any errors"). As research has repeatedly demonstrated, this triggers sycophancy and confirmation bias: the model rationalizes its mistakes rather than catching them.

What does GenRM stand for? GenRM stands for Generative Reward Model—an adversarial verifier pattern introduced in Generative Verifiers: Reward Modeling as Next-Token Prediction (arXiv:2408.15240). While frameworks like NVIDIA's post-training pipeline for Nemotron-3.5-Bolt use GenRM at train time (RLHF/RLVR alignment), we apply the same generative verifier pattern at inference time inside a 2-Layer Hybrid Neuro-Symbolic GenRMCritic with absolute veto power before any memo reaches the C-suite.

To achieve true enterprise readiness without relying on fragile regexes alone—and without wasting GPU cycles on obvious arithmetic errors—we architected GenRMCritic as a two-stage neuro-symbolic gatekeeper:

flowchart LR
    Draft["Draft Executive Memo"] --> Layer1["Layer 1: Symbolic Pre-Filter\nExact Metric Tolerance <= 0.05%"]
    Layer1 -->|"Fail"| Rej1["❌ Instant VETO (0 LLM calls):\nUncertified number found"]
    Layer1 -->|"Pass"| Layer2["Layer 2: Generative GenRM-CoT Judge\nPolarity, LBO Verdict & Consistency"]
    Layer2 -->|"VETO"| Rej2["❌ VETO (GenRM-CoT):\nSemantic / Verdict Contradiction!"]
    Layer2 -->|"PASS"| Cert["🏆 CERTIFIED FOR BOARDROOM"]

Every percentage extracted from the draft memo must match a certified result in the FinancialRuntime registry within a $0.05%$ margin. If the model hallucinates "an operating margin of 42.5%" when the certified runtime output was -18.47%, Layer 1 issues an immediate VETO with zero LLM calls.

The most insidious failure in financial AI is directional polarity inversion or strategic verdict contradiction expressed with unexpected phrasing.

Consider these real adversarial cases verified against live Nemotron 3.5 Bolt in our E2E benchmark:

-18.47%."* -> Layer 2 ( GenRM-CoT) issues [VETO] because LboCovenantPolicyVO imposes UNFAVORABLE, a draft claiming Here is our production 2-layer GenRMCritic implementation (with an offline deterministic fallback when no GPU/model backend is injected):

class GenRMCritic(GenRMCriticProtocol):
    """2-Layer Hybrid Neuro-Symbolic Auditor (Symbolic Pre-Filter + GenRM-CoT)."""

    def __init__(self, model_backend: ModelBackendProtocol | None = None) -> None:
        self._model = model_backend

    def audit_synthesis(
        self,
        draft_synthesis: str,
        certified_results: list[CertifiedFinancialResultDTO],
        expected_deal_verdict: str | None = None,
    ) -> tuple[bool, str]:
        if not draft_synthesis or not draft_synthesis.strip():
            return False, "Rejet GenRM : la note de synthèse est vide ou non rédigée."
        if certified_results:
            validation_ok, reason = self._audit_percentages(draft_synthesis, certified_results)
            if not validation_ok:
                return False, reason
        if self._model is not None:
            return self._audit_with_genrm_cot(draft_synthesis, certified_results, expected_deal_verdict)
        return self._audit_deterministic_fallback(draft_synthesis, certified_results, expected_deal_verdict)

When a VETO is issued, the Generalist Crew Manager initiates a single targeted correction turn, injecting the explicit rejection reason into the synthesizer's context.

When all gates clear, the engine outputs an auditable, executive-ready memorandum. Below is the actual verbatim output (synthese_complete) generated end-to-end by our live Nemotron 3.5 Bolt pipeline + Python IEEE-754 runtime + Hybrid Neuro-Symbolic GenRMCritic on Renault SAS's audited 2024 standalone accounts (comptes sociaux, elapsed_s: 104.08s, certified_count: 4, genrm_calls: 2, GenRM verdict: [PASS]):


> **Statut d'Audit** : 🟢 CERTIFIÉ CONFORME | **Réf. Document** : `5f8186cfdca20e93...` | **Date** : 13/11/2026 13:36 UTC

> **Verdict Covenants LBO** : `FAVORABLE` — Profil de génération de cash-flow et levier conformes aux standards de dette senior LBO.

## 1. Objet de la Mission
Est-ce qu'un rachat de Renault SAS par LBO est faisable financièrement ?

## 2. Indicateurs Clés Certifiés (Norme Python IEEE-754)
| Poste Comptable Officiel | Métrique Calculée | Valeur Certifiée | Unité | Interprétation | Ancrage |
| :--- | :--- | :--- | :--- | :--- | :---: |
| **CAPACITE D'AUTOFINANCEMENT** | `compute_pct_change` | **+83.02** | PERCENT | HAUSSE | ✅ Source |
| **DETTES FINANCIERES (Note E.4)** | `compute_pct_change` | **-37.55** | PERCENT | BAISSE | ✅ Source |
| **DETTES FINANCIERES (Note E.4)** | `compute_ratio` | **1.8541** | RATIO | RATIO_POSITIF | ✅ Source |
| **DETTES FINANCIERES (Note E.4)** | `compute_ratio` | **0.552** | RATIO | RATIO_POSITIF | ✅ Source |

## 3. Analyse & Diagnostic Financier
Synthèse financière exécutive établie par le Crew (Chief Financial Officer (Executive Writer)) sur la base exclusive des calculs certifiés par le moteur Python IEEE-754 :

- **CAPACITE D'AUTOFINANCEMENT** (`compute_pct_change`) : **+83.02%** (HAUSSE) [Base certifiée : n1=1,378.00, n=2,522.00].
- **DETTES FINANCIERES (Note E.4)** (`compute_pct_change`) : **-37.55%** (BAISSE) [Base certifiée : n1=7,487.00, n=4,676.00].
- **DETTES FINANCIERES (Note E.4)** (`compute_ratio`) : **1.8541 RATIO** (RATIO_POSITIF) [Base certifiée : numerateur=4,676.00, denominateur=2,522.00].
- **DETTES FINANCIERES (Note E.4)** (`compute_ratio`) : **0.552 RATIO** (RATIO_POSITIF) [Base certifiée : numerateur=4,676.00, denominateur=8,471.00].

Diagnostic ComEx : L'ensemble des indicateurs ci-dessus sont physiquement ancrés dans les états financiers et validés sans écart par le juge contradictoire GenRM.

---
### 🛡️ Fiche de Traçabilité & Conformité Native MoM
- **Modèle Spécialiste** : `NVIDIA-Nemotron-3.5-Bolt-E4B`
- **Adaptateur LoRA Financier** : `BtbAgent/nemotron-3.5-Bolt-E4B-specialiste-financier`
- **Juge GenRM** : `CERTIFIED` (Certification GenRM (Hybride Neuro-Symbolique) : 100% conforme.)
- **Empreinte SHA-256 Source** : `5f8186cfdca20e931a74f002d1508cd239d19b03ca1fc5560976c035acaa1ce7`

(Note on the 2024 figures: On Renault SAS's standalone 2024 accounts, CAF rose +83.02% from €1,378M to €2,522M while Financial Debt fell -37.55% from €7,487M to €4,676M, bringing Debt/CAF down to 1.85x and Gearing to 55.2% — clearing LboCovenantPolicyVO thresholds as FAVORABLE, whereas earlier 2023 standalone debt levels of €10,587M vs. €1,245M CAF yielded 8.50x and UNFAVORABLE.)

Deploying LLMs in regulated, mission-critical environments (finance, medical, legal) requires abandoning several common AI tropes:

Legacy Chatbot Trope Enterprise Production Architecture
Giant single prompts trying to do everything Multi-Agent DAG Orchestration (Generalist Planner $\leftrightarrow$ Specialist Advisor).
Letting models do arithmetic in latent tokens Deterministic Execution Sandboxes (Python Decimal IEEE-754 runtime).
Relying on LLM self-correction Adversarial Gatekeeping (GenRM Critic with strict AST & polarity checks).
Naive similarity search across raw text chunks Neuro-symbolic Chapter Locators (TOC discovery + Concept Fingerprinting).
Unverifiable qualitative summaries Mandatory Same-Row Grounding [p.X] across 100% of claims.

Over the first three parts of this series, we built:

In the final installment of this series, we put our complete sovereign pipeline through the ultimate real-world battle test:

Stay tuned for Part 4!

Thank you for following along with this series! If you found these architectural patterns useful, leave a reaction, share it with your engineering team, and join the discussion in the comments below: What safeguards do you rely on when deploying LLMs to high-stakes workflows?

── more in #ai-agents 4 stories · sorted by recency
── more on @renault sas 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-our-pipeline-orc…] indexed:0 read:10min 2026-11-13 · —