Skip to content
Workflow Automation

BNP Paribas Starts Its Agentic Programme With Credit Memos. Here Is The Workflow Architecture For A Credit Memo Agent: Deterministic Ratios, Cited Drafts And A Reviewer Who Signs

On 24 September BNP Paribas and Google Cloud announced a five-year agentic AI partnership whose first deployments, in Corporate & Institutional Banking, help teams prepare corporate credit memos - before extending to sales, trading, research and structuring - with Gemini integrated into LLM@CIB, the assistant more than 65,000 employees already use, inside the bank's existing governance. The choice of first workflow is instructive: a document-heavy task where a credit officer already reviews every output. This is the engineering version of that decision - the workflow architecture we use for credit memo agents, with code: a durable pipeline, financial spreading and ratios computed deterministically, section drafting constrained to cited evidence, a validator that refuses any number it cannot trace, and a review step that records exactly what the human changed.

AlchmAI Engineering16 min read

5 years

BNP Paribas - Google Cloud agentic AI partnership, announced 24 September, starting with corporate credit memos

65,000+

Employees already using LLM@CIB, the bank's assistant, which will integrate Gemini models

100%

Of figures in the draft that must trace to a source document or a deterministic calculation - the validator's rule

1

Accountable credit officer who signs every memo; the agent drafts, it does not decide

BNP Paribas' announcement with Google Cloud is specific in a way most bank AI announcements are not. The partnership gives the bank Gemini models, Gemini Enterprise and Google's AI infrastructure; the first agentic use cases are in Corporate & Institutional Banking, helping teams prepare corporate credit memos, with sales, trading, research and structuring to follow; Gemini will be integrated into LLM@CIB, which more than 65,000 employees already use; and it all runs within the bank's multi-cloud, multi-model strategy and established security and data governance.

The credit memo is a near-perfect first agent for any lender. It assembles financial statements, covenant analysis, industry context, relationship history and a recommendation into a standard structure. It is laborious and repetitive, and a credit officer reviews every one before anything is decided. What follows is the architecture we use for credit memo agents at smaller lenders - the same shape scales up - with the parts that make it survive credit committee and audit.

The Pipeline

  1. 01Gather: pull financial statements, management accounts, existing facility terms, KYC file and relationship notes into a case folder with document IDs and hashes.
  2. 02Extract: parse statements into a canonical chart of accounts, with the page and cell each figure came from.
  3. 03Spread and compute: deterministic code produces the spread, ratios, covenant headroom and trend tables.
  4. 04Draft: the model writes narrative sections using only the computed tables and cited source extracts.
  5. 05Validate: every number in the draft is matched to the computed tables or a cited span; unsupported claims fail the run.
  6. 06Review: the credit officer edits and signs; the system stores the draft, the final and the diff.

Run it on a durable workflow engine so a failure at step five resumes at step five, not from scratch - and so each step's inputs and outputs are persisted as evidence. The sketch below uses Temporal's Python SDK; the same shape works with any durable executor.

pythonmemo/workflow.py
from datetime import timedelta
from temporalio import workflow

with workflow.unsafe.imports_passed_through():
    from memo import activities as act

@workflow.defn
class CreditMemoWorkflow:
    @workflow.run
    async def run(self, case_id: str) -> str:
        opts = dict(start_to_close_timeout=timedelta(minutes=10))
        folder = await workflow.execute_activity(act.gather_documents, case_id, **opts)
        extracted = await workflow.execute_activity(act.extract_financials, folder, **opts)
        spread = await workflow.execute_activity(act.compute_spread_and_ratios, extracted, **opts)
        draft = await workflow.execute_activity(act.draft_sections, {"folder": folder, "spread": spread},
                                                start_to_close_timeout=timedelta(minutes=20))
        report = await workflow.execute_activity(act.validate_draft, {"draft": draft, "spread": spread}, **opts)
        if not report["ok"]:
            # Route back with the failures; never pass an unvalidated draft to a human.
            draft = await workflow.execute_activity(act.redraft_with_failures,
                                                    {"draft": draft, "failures": report["failures"]}, **opts)
            report = await workflow.execute_activity(act.validate_draft, {"draft": draft, "spread": spread}, **opts)
            if not report["ok"]:
                return await workflow.execute_activity(act.escalate_to_analyst, case_id, **opts)
        return await workflow.execute_activity(act.open_review_task, {"case": case_id, "draft": draft}, **opts)

Numbers Are Computed, Not Generated

pythonmemo/ratios.py
from decimal import Decimal, ROUND_HALF_UP
from dataclasses import dataclass

@dataclass(frozen=True)
class Figure:
    key: str; value: Decimal; source: str   # "doc:FS2025#p4:r12" or "calc:ratios.leverage"

def q(x: Decimal, places="0.01") -> Decimal:
    return x.quantize(Decimal(places), rounding=ROUND_HALF_UP)

def compute(fs: dict) -> dict:
    ebitda = fs["operating_profit"].value + fs["depreciation"].value + fs["amortisation"].value
    net_debt = fs["total_borrowings"].value - fs["cash"].value
    out = {
        "ebitda": Figure("ebitda", q(ebitda), "calc:ratios.ebitda"),
        "net_debt": Figure("net_debt", q(net_debt), "calc:ratios.net_debt"),
        "leverage": Figure("leverage", q(net_debt / ebitda), "calc:ratios.leverage"),
        "interest_cover": Figure("interest_cover",
                                 q(fs["operating_profit"].value / fs["interest_expense"].value),
                                 "calc:ratios.interest_cover"),
    }
    covenant = fs["covenant_max_leverage"].value
    out["leverage_headroom"] = Figure("leverage_headroom", q(covenant - out["leverage"].value),
                                      "calc:ratios.leverage_headroom")
    return out

Drafts That Cite, And A Validator That Refuses

The drafting prompt gives the model the computed figures as a table with keys, and the source extracts with span IDs, and asks for narrative that references them by key - for example writing 'leverage of {leverage}x' rather than a number. The renderer substitutes the values. Anything the model states as a number outside that mechanism is, by definition, unsupported, and the validator catches it.

pythonmemo/validate.py
import re

PLACEHOLDER = re.compile(r"[{]([a-z_]+)[}]")
CITATION = re.compile(r"[[](doc:[^]]+)[]]")
NUMBER = re.compile(r"(?<![{A-Za-z_])[-]?[0-9][0-9,]*[.]?[0-9]*(?:x|%|m|bn)?")

def validate(sections: dict, figures: dict, spans: set) -> dict:
    failures = []
    for name, text in sections.items():
        for key in PLACEHOLDER.findall(text):
            if key not in figures:
                failures.append((name, "unknown figure key: " + key))
        for ref in CITATION.findall(text):
            if ref not in spans:
                failures.append((name, "citation to unknown span: " + ref))
        stripped = CITATION.sub("", PLACEHOLDER.sub("", text))
        for raw in NUMBER.findall(stripped):
            if raw.strip() and not raw.isdigit() or (raw.isdigit() and len(raw) > 4):
                failures.append((name, "free-text number not traced to a figure: " + raw))
    return {"ok": not failures, "failures": failures}

The validator is deliberately strict - it allows short integers such as years and section numbers, and nothing else in free text. Credit officers quickly prefer a draft that says less but is always traceable to one that says more and must be checked line by line.

Review That Leaves Evidence

  • Show the officer the draft with every figure and citation clickable back to the source page or the calculation.
  • Store the draft, the final text and a structured diff; report the edit rate per section over time - it is your quality metric.
  • Require the officer's sign-off as a separate authenticated action; the agent's identity has no permission to mark a memo final.
  • Keep the model and prompt version, the document hashes and the calculation code version with the memo, so it can be reproduced for audit or a model-risk review.

“The agent's job is to get a credit officer to a defensible first draft in minutes. The officer's job is unchanged. That division is why credit memos are the right first agent.”


Where To Go Next - The BNP Paribas Sequence

BNP Paribas plans to extend from credit memos to sales, trading, research and structuring. The same architecture carries over: deterministic calculation for anything numeric, cited drafting for narrative, a validator between the model and the human, and an evidence trail of every change. Research notes and structuring term sheets are natural next steps; anything that moves money or quotes a client price needs the stronger controls - propose-only credentials and pre-trade checks - that we describe for trading agents.

The Bottom Line

BNP Paribas starting its five-year agentic programme with Google Cloud on corporate credit memos is a signal every lender should read: begin with document-heavy work that an accountable expert already reviews. The architecture that makes a credit memo agent production-grade is a durable pipeline from gathering to review, spreads and ratios computed in deterministic code, narrative drafted only from keyed figures and cited spans, a validator that rejects any untraceable number, and a sign-off step that records the human's diff alongside model, prompt and document versions. That is the workflow automation architecture we build for lenders and banks in London, and it is how an agentic pilot becomes something credit committee will actually rely on.

References & Further Reading

Workflow Automation Agency architectureWorkflow automation code samplesAgentic AI finance codecredit memo automationAI Agency fintechWorkflow Automation LondonBNP Paribas
Share Email
AI

AlchmAI Engineering

Engineering, London

Written by the AlchmAI engineering team in Mayfair, London. We build trading platforms, real-time charts, market data pipelines and AI features for brokers, prop firms and fintech teams. The Playbook is where we explain how we approach these systems, with code you can run and sources you can check.

Code in this guide is illustrative and supplied without warranty. Review and test it before production use. Nothing here is investment advice. Important information