Render a one-screen inline visual summary of a commercial borrower's credit package — facility exposure, financial KPIs from latest Boom spread, loan tiles, covenant compliance, collateral coverage, and guarantor. **TRIGGER aggressively** on ANY of these phrasings when a commercial borrower is named or referenced: "summarize the deal", "summarize [borrower]", "deal summary", "summary of the [borrower] deal", "deal at a glance", "quick summary", "credit snapshot", "deal overview", "show me the credit package", "give me a snapshot", "give me an overview", "what's the deal with [borrower]", "tell me about [borrower]'s credit", **"tell me about [borrower]"**, **"tell me what you know about [borrower]"**, **"what do we know about [borrower]"**, **"research [borrower]"**, **"look up [borrower]"**, **"what's our exposure to [borrower]"**, **"what's the status of the [borrower] deal"**, **"pull up [borrower]"**, **"show me [borrower]"**. Whenever a banker mentions a company or business name in the context of credit, lending, or relationship inquiry, this is almost certainly the right skill — render the widget rather than answering from general knowledge. Prefer this skill over `commercial-credit-memo` whenever the user asks for a SUMMARY or OVERVIEW (anything that suggests a quick read), and only use `commercial-credit-memo` when the user explicitly asks to "draft", "write", "generate", or "refresh" the full credit memo. NOT for drafting the full credit memo.
How this skill is triggered — by the user, by Claude, or both
Slash command
/truist-credit-memo-agent:deal-summary-widgetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Render a single-screen inline widget showing the key facts of a commercial credit deal. Output via Cowork's `show_widget` (transient, one-shot, lives inline in the chat message).
Render a single-screen inline widget showing the key facts of a commercial credit deal. Output via Cowork's show_widget (transient, one-shot, lives inline in the chat message).
| This skill (deal-summary-widget) | commercial-credit-memo | |
|---|---|---|
| Output | Inline show_widget HTML | Live Cowork artifact (persistent, re-openable) |
| Persistence | Lives in the chat message it was generated in | Persists across sessions; re-opens with fresh data |
| Data refresh | Static snapshot of the moment | Re-queries on every artifact open |
| Purpose | Single-screen at-a-glance reference | The actual underwriting workspace where the memo gets drafted |
| Trigger phrases | "Quick look", "deal snapshot", "at a glance", "summary", "credit package overview" | "Draft the memo", "underwriting workspace", "annual review" |
Mental model: widget = boarding pass (compact, glance at it); memo = the flight (where the work happens). The widget is a natural prelude — after rendering it, offer "Want me to open the full credit memo workspace next?"
User asks for:
Do not use for:
commercial-credit-memoxlsx-author (if available)One of:
Account.Id (e.g., 001bb00001DLtRMAA1)find first)Optional: a specific LLC_BI__Product_Package__c Id if scoping to a non-latest package.
This is a speed-critical skill. Execute the steps below mechanically. Do not deliberate between steps. Do not read other skill references. Do not verify Salesforce schema before running queries — the field names below are correct. Do not run exploratory queries.
If the user gave a name, run ONE SOSL find: FIND {borrowerName} IN NAME FIELDS RETURNING Account(Id, Name) LIMIT 1. Skip if Account Id was provided.
Anthropic's tool-use protocol executes multiple tool_use blocks in a single assistant message in parallel. Pack everything below into one message — DO NOT send them as separate assistant turns.
Always include a ToolSearch call in this batch to prewarm the Salesforce schemas. The Salesforce MCP tools are deferred in Cowork sessions with many connectors — the first SOQL call would otherwise fail with InputValidationError. Fire ToolSearch alongside the queries; the harness loads schemas before the dependent calls execute:
query: "select:<soqlQuery_tool_name>,<find_tool_name>" with max_results: 2 — skip ONLY if you've already loaded these earlier in the conversation. The Bash schema is built-in and does not need preloading. The exact tool names are visible in the deferred-tool list at session start (search "salesforce" or look for the mcp__<server-id>__soqlQuery / mcp__<server-id>__find pair).Then in the SAME message, fire the queries that DO NOT depend on the Product Package Id:
LLC_BI__Account__c, no package needed)curl -s -H "Authorization: Bearer bk_fdccfeca75a30f34_9611b2e8f5467b4403d678dc1795d14206e2e8b542342fe6" "https://api.boom.build/companies/external-id/$ACCOUNT_ID" — fetches the Boom Company; gives you fileIds[0] as a side-channel to SOQL #4Primary path: Boom REST API. Financial line items come from api.boom.build (the bearer token is hardcoded in CLAUDE.md). The Salesforce Boom shadow objects (Boom_Line_Item__c, etc.) are a fallback only — see Step 3.
Do NOT attempt a nested-relationship subquery to pull Loans inside the Product Package query. The child-relationship name on LLC_BI__Product_Package__c varies across nCino installs. Guessing wrong forces a retry that costs more time than the round trip you saved. Always batch the Loans/Collateral/Guarantor queries separately in Step 2b.
In ONE follow-up assistant message, fire in parallel:
packageId from SOQL #2)packageId)packageId)status = completed): curl -s -H "Authorization: Bearer bk_fdccfeca75a30f34_9611b2e8f5467b4403d678dc1795d14206e2e8b542342fe6" "https://api.boom.build/files/<BOOM_FILE_ID>" — fold into this batchPrimary path (Boom REST): parse the JSON returned by GET /files/<fileId> from batch 2. The response has a financialStatements array with lineItems (each with accountCode, name, hierarchy, periodValues). Map line items by accountCode:
sales_revenue (income_statement)cost_of_salessales_revenue − cost_of_sales − general_and_admin_expenses + depreciation_amortizationtotal_debt if present, else long_term_debt + short_term_debtinterest_expense (may be negative — take abs)Compute: Leverage = Total Debt / Adj. EBITDA. DSC = Adj. EBITDA / (Interest + scheduled principal). EBITDA margin = Adj. EBITDA / Revenue. YoY = (current − prior) / prior.
Fallback path (Salesforce Boom shadow) — use ONLY if the REST call fails (timeout, 5xx, malformed response). Fire these four SOQL queries in parallel:
-- Boom file
SELECT Id, Boom_File_Id__c, Status__c, CreatedDate FROM Boom_File__c
WHERE Account__c = :accountId AND Status__c = 'completed'
ORDER BY CreatedDate DESC LIMIT 1
-- Statements
SELECT Id, Boom_File__c, Statement_Type__c, End_Date__c, Validation_Status__c, CreatedDate
FROM Boom_Financial_Statement__c
WHERE Boom_File__r.Account__c = :accountId
ORDER BY End_Date__c DESC, CreatedDate DESC
-- Period UUID → date map
SELECT Id, Boom_Financial_Statement__c, Boom_Period_Id__c, End_Date__c, Period_Type__c
FROM Boom_Financial_Period__c
WHERE Boom_Financial_Statement__r.Boom_File__r.Account__c = :accountId
-- Line items (values in Period_Values_Json__c as JSON dict keyed by period UUID)
SELECT Boom_Financial_Statement__r.Statement_Type__c,
Boom_Financial_Statement__r.End_Date__c,
Account_Code__c, Name, Hierarchy__c, Period_Values_Json__c
FROM Boom_Line_Item__c
WHERE Boom_Financial_Statement__r.Boom_File__r.Account__c = :accountId
AND Account_Code__c IN ('sales_revenue','cost_of_sales','general_and_admin_expenses','interest_expense','depreciation_amortization','total_debt','long_term_debt','short_term_debt','cash_and_equivalents','total_assets','total_equity','net_income')
Parse: build {periodUuid → endDate} map; dedupe by (Statement_Type__c, End_Date__c) keeping most recent CreatedDate; JSON.parse(Period_Values_Json__c) to get values; apply units sanity check (BankingGPT has mixed thousands/dollars — multiply 4-5 digit values for a $10M+ borrower by 1000). Same accountCode → KPI mapping as the REST path.
If BOTH paths fail (REST errors AND no Boom_Line_Item__c rows), render — placeholders and surface "Spread unavailable" in the Spread Status KPI cell.
Read('truist-credit-memo-agent/skills/deal-summary-widget/templates/deal-summary-widget.html')
Only this file. Do not read brand-tokens.css, truist-wordmark.svg, boom-logo.svg, or any reference file. The template is fully self-contained.
Substitute every {{placeholder}} with the values you parsed in steps 2 and 3. Construct the Salesforce URLs inline using https://{instance}.lightning.force.com/lightning/r/{ObjectName}/{Id}/view. Render via show_widget in a single call.
Return a 1-2 sentence summary line ABOVE the widget. Example: Atlas Industrial Supply — $120MM total commitment, 4/9 risk rating, all six covenants compliant. Currently in annual review.
DESCRIBE / getObjectSchema) — field names below are correct, run queries directlybrand-tokens.css, the standalone SVG files, or skill referencescompletedLLC_BI__DocType__c records — not needed for the widget (it's only used in Capability D — DocMan save)The Financial KPIs section head contains exactly THREE elements in this order:
<h3 class="dw-section-title">Financial KPIs</h3><span class="dw-section-meta">{{financials.asOfDate}}</span> — the as-of date (e.g., "FYE 12/31/2025")<span class="dw-boom-attribution">Powered by [Boom logo]</span> — Boom attribution chipABSOLUTE RULE — DO NOT INSERT STATUS BADGES IN THIS SECTION HEAD. No "SPREAD COMPLETE", no "SPREAD PENDING", no "SPREAD PROCESSING", no green pills, no amber pills, no red pills, no status chips of any kind. The user has flagged this multiple times — every time you add a status pill here, it clutters the Boom attribution and takes attention away from the "Powered by Boom" branding. Stop doing it.
If you have spread status information to convey, it goes in exactly one place: the "Spread Status" value within the KPI cell at the bottom row of this section (the fifth KPI cell). Nowhere else.
Reason: the section head should read cleanly as Financial KPIs · 12/31/2025 · Powered by [Boom]. Three elements. No more. The Boom attribution chip is the visual anchor for partner integration credit — it needs visual breathing room, not a competing status pill.
If you have ever added a "SPREAD COMPLETE" or similar badge to the section head in a prior render: don't do it again. Render exactly the three elements listed above. Period.
The widget includes a "Sources" section at the bottom with two compact cards (Account + Product Package). These are always rendered — never omit them. Every Account, Product Package, AND Loan must have a hyperlink. The user has explicitly stated: "the widget for high level summary needs ALWAYS share the related links (Account, Product Package, and both loans)."
Hardcoded Salesforce base URL for this demo (per CLAUDE.md):
https://accenture-d8--bankinggpt.sandbox.lightning.force.com
Construct every record URL as:
https://accenture-d8--bankinggpt.sandbox.lightning.force.com/lightning/r/{ObjectApiName}/{RecordId}/view
Required placeholders the agent MUST populate every render:
{{borrower.salesforceUrl}} — Account URL, e.g. https://accenture-d8--bankinggpt.sandbox.lightning.force.com/lightning/r/Account/001bb00001DLtRMAA1/view{{borrower.name}}, {{borrower.industry}}, {{borrower.naics}}, {{borrower.customerSinceYear}} — Account card body{{exposure.salesforceUrl}} — Product Package URL, e.g. .../lightning/r/LLC_BI__Product_Package__c/a0Xbb00000WXYZ/view{{exposure.packageName}}, {{exposure.stage}}, {{exposure.totalCommitment}} — Product Package card body{{loans.count}} — total loan count, shown in the Product Package card meta line{{loans.compactListHtml}} — concatenated loan lines, one per loan, each wrapped in an <a> hyperlink to its Loan recordThe compact loan list inside the Product Package card uses this per-loan pattern — the <a> wrapper is MANDATORY, not optional:
<a href="https://accenture-d8--bankinggpt.sandbox.lightning.force.com/lightning/r/LLC_BI__Loan__c/{loanId}/view"
class="dw-source-loan-line" target="_blank" rel="noopener">
<span class="ln">Working Capital Line</span>
<span class="amt">$7.5M</span>
</a>
Concatenate the per-loan <a> blocks into a single HTML string for {{loans.compactListHtml}}. Never render a loan line as a non-clickable <div> — it must be an <a> pointing at the Loan record. Each loan's data shape includes a salesforceUrl field (see "Widget data shape" below).
If a record ID is genuinely missing, fall back to href="#" only as a last resort. Never skip the Sources section and never skip the loan hyperlinks.
-- Account info
SELECT Id, Name, Industry, NAICS_Code__c, LLC_BI__NaicsDesc__c,
Customer_Since_Date__c, LLC_BI__Highest_Risk_Grade__c
FROM Account WHERE Id = :accountId
-- Latest Product Package
SELECT Id, Name, LLC_BI__Stage__c, LLC_BI__Status__c, LLC_BI__Risk_Rating__c,
LLC_BI__TBE__c, LLC_BI__TOE__c, LLC_BI__Outstanding__c,
LLC_BI__Unused__c, LLC_BI__New_Money__c, LLC_BI__TCE__c
FROM LLC_BI__Product_Package__c
WHERE LLC_BI__Account__c = :accountId
ORDER BY CreatedDate DESC LIMIT 1
-- Loans under the package
SELECT Id, Name, LLC_BI__Product__c, LLC_BI__Loan_Class__c, LLC_BI__Stage__c,
LLC_BI__Approved_Loan_Amount__c, LLC_BI__Principal_Balance__c,
LLC_BI__Funding_at_Close__c, LLC_BI__InterestRate__c, LLC_BI__Spread__c,
LLC_BI__Term_Months__c, LLC_BI__Maturity_Date__c, LLC_BI__Risk_Grade__c
FROM LLC_BI__Loan__c
WHERE LLC_BI__Product_Package__c = :packageId
ORDER BY LLC_BI__Approved_Loan_Amount__c DESC
-- Covenants (via Account Covenant junction)
SELECT LLC_BI__Covenant2__r.LLC_BI__Covenant_Type__r.Name,
LLC_BI__Covenant2__r.LLC_BI__Detail__c,
LLC_BI__Covenant2__r.LLC_BI__Covenant_Status__c,
LLC_BI__Covenant2__r.LLC_BI__Financial_Indicator_Value__c,
LLC_BI__Covenant2__r.LLC_BI__Last_Evaluation_Value__c,
LLC_BI__Covenant2__r.LLC_BI__Frequency__c,
LLC_BI__Covenant2__r.Financial_Indicator_Operator__c
FROM LLC_BI__Account_Covenant__c
WHERE LLC_BI__Account__c = :accountId
-- Loan collateral pledges (aggregate per loan in app code)
SELECT LLC_BI__Loan__c, LLC_BI__Loan__r.Name, LLC_BI__Loan__r.LLC_BI__Product__c,
LLC_BI__Amount_Pledged__c, LLC_BI__Collateral__r.LLC_BI__Collateral_Name__c
FROM LLC_BI__Loan_Collateral2__c
WHERE LLC_BI__Loan__r.LLC_BI__Product_Package__c = :packageId
AND LLC_BI__Active__c = true
-- Personal guarantors (junction)
SELECT LLC_BI__Account__r.Name, LLC_BI__Account__r.PersonEmail,
LLC_BI__Guarantee_Limit__c, LLC_BI__Guaranty_Amount__c,
LLC_BI__Contingent_Type__c, LLC_BI__Entity_Type__c
FROM LLC_BI__Legal_Entities__c
WHERE LLC_BI__Loan__r.LLC_BI__Product_Package__c = :packageId
AND LLC_BI__Borrower_Type__c = 'Guarantor'
-- Boom file shadow record (cross-reference only — for the file ID + status)
-- Financial line items come from the Boom REST API. The Salesforce Boom shadow
-- objects (Boom_Line_Item__c et al.) exist in this org but are used only as a
-- fallback if the REST call fails — see "Financial line items" section below.
SELECT Id, Boom_File_Id__c, Status__c, File_Name__c, CreatedDate
FROM Boom_File__c
WHERE Account__c = :accountId
ORDER BY CreatedDate DESC LIMIT 1
Field/object names above are verified against the BankingGPT sandbox (May 2026).
Primary path: Boom REST API at https://api.boom.build. The bearer token is hardcoded in CLAUDE.md.
Fallback path: Salesforce Boom shadow (Boom_File__c → Boom_Financial_Statement__c → Boom_Line_Item__c + Boom_Financial_Period__c). Use only when the REST call fails.
Boom_File__c shadow query above (or from GET /companies/external-id/{accountId} on Boom — both should agree).Status__c is anything other than completed, render the widget with — placeholders and put the actual status in the "Spread Status" KPI cell.GET https://api.boom.build/files/{fileId} with the hardcoded bearer header. Parse the response's financialStatements array.accountCode:
sales_revenuecost_of_salessales_revenue − cost_of_sales − general_and_admin_expenses + depreciation_amortizationtotal_debt (else long_term_debt + short_term_debt)interest_expenseperiodValuesSee ../boom-spreading/references/api-workflows.md for full request/response shapes.
If GET /files/{fileId} returns a non-2xx status, times out, or returns a malformed body, fall back to Salesforce. Fire these four SOQL queries in parallel:
-- Statements (one row per Statement_Type__c per file)
SELECT Id, Boom_File__c, Statement_Type__c, End_Date__c, Validation_Status__c, CreatedDate
FROM Boom_Financial_Statement__c
WHERE Boom_File__r.Account__c = :accountId
ORDER BY End_Date__c DESC, CreatedDate DESC
-- Period UUID → date map (needed to interpret line-item JSON)
SELECT Id, Boom_Financial_Statement__c, Boom_Period_Id__c, End_Date__c, Period_Type__c
FROM Boom_Financial_Period__c
WHERE Boom_Financial_Statement__r.Boom_File__r.Account__c = :accountId
-- Line items (values in Period_Values_Json__c as JSON dict keyed by period UUID)
SELECT Boom_Financial_Statement__r.Statement_Type__c,
Boom_Financial_Statement__r.End_Date__c,
Account_Code__c, Name, Hierarchy__c, Period_Values_Json__c
FROM Boom_Line_Item__c
WHERE Boom_Financial_Statement__r.Boom_File__r.Account__c = :accountId
AND Account_Code__c IN ('sales_revenue','cost_of_sales','general_and_admin_expenses','interest_expense','depreciation_amortization','total_debt','long_term_debt','short_term_debt','cash_and_equivalents','total_assets','total_equity','net_income')
Parse: build {periodUuid → endDate} map from periods; dedupe statements by (Statement_Type__c, End_Date__c) keeping most recent CreatedDate; JSON.parse(Period_Values_Json__c) per line item; apply units sanity check (BankingGPT has mixed thousands/dollars — multiply 4-5 digit revenue values by 1000 for a $10M+ borrower). Same accountCode → KPI mapping as the REST path.
If BOTH paths fail (REST errors AND no shadow rows), render — placeholders and surface "Spread unavailable" in the Spread Status KPI cell.
After parsing, assemble:
{
borrower: { name, industry, naics, naicsDesc, customerSinceYear, riskGrade, stage,
salesforceUrl }, // NEW: link to Account record
exposure: { totalCommitment, outstanding, utilizationPct, unused, newMoney,
packageName, stage, salesforceUrl }, // NEW: package name + stage + link to Product Package record
financials: {
asOfDate, // e.g., "FYE 12/31/2025"
revenue, revenueYoYPct,
ebitda, ebitdaMarginPct,
leverage, leverageCovenant, // Funded Debt / EBITDA
dsc, dscCovenant,
boomStatus, // 'completed' | 'processing' | 'failed' | 'pending'
},
loans: [{
name, product, loanClass,
shortName, // brief form (e.g. "Working Capital RCF") for compact source card
salesforceUrl, // MANDATORY: link to the Loan record in Salesforce
facility, outstanding, fundingAtClose,
interestRate, spread,
maturity, termMonths,
action, // derived label, e.g. "Renewal — Senior Secured RCF"
}],
loansCount, // count of loans (for the source card meta line)
covenants: [{
typeName, detail,
threshold, latestValue,
formattedThreshold, formattedLatestValue,
status, // 'compliant' | 'exception' | 'breached' | 'waived'
frequency,
}],
collateralCoverage: [{ loanName, totalSupportPledged, coveragePct, descriptionShort }],
guarantor: { name, title, ownershipPct, totalGuaranty, description } | null,
// Note: NO `branding` field needed — logos are inlined directly in the template
}
$X.XM or $X.XXM for millions; $X,XXX,XXX for amounts under $1MX.XXx (e.g., 2.64x)X.X%MMM D, YYYY (e.g., Mar 31, 2026)Covenant status pill colors (use the brand tokens from ../../assets/brand-tokens.css):
| Status | Background | Text |
|---|---|---|
compliant | rgba(31, 122, 58, 0.12) | #1F7A3A |
exception | rgba(180, 83, 9, 0.12) | #B45309 |
breached | rgba(168, 33, 27, 0.12) | #A8211B |
waived | rgba(92, 90, 96, 0.12) | #5C5A60 |
status ≠ completed): render the Financial KPIs section with — placeholders for the financial metrics. Always keep the "Powered by [Boom]" attribution chip visible in the section head — the Boom logo is part of the attribution chain and stays present regardless of spread status. The actual spread status is communicated via the "Spread Status" KPI cell (which can read Pending, Processing, Failed, or — when completed — the period end date).Failed — see Boom UI.[Short 1-2 sentence summary line]
[show_widget call with rendered HTML]
Example summary line: "Atlas Industrial Supply — $120MM total commitment, 4/9 risk rating, all six covenants compliant. Currently in annual review."
After rendering, offer: "Want me to open the full credit memo workspace next?"
Truist branding (primary, headers, accents) uses the tokens already defined in ../../assets/brand-tokens.css:
#2D1A47 (primary, header band)#1B2D5B#1A1A1A#D6D3D1#1F7A3A / #B45309 / #A8211BThe Truist wordmark logo at ../../assets/truist-wordmark.svg is inlined into the header band (white version on dark purple — apply fill="#FFFFFF" to the SVG when rendering in the header context).
Boom branding (for the "Powered by Boom" attribution near the Financial KPIs section):
#D85A30 (accent)#FFF4EDassets/boom-logo.svg (placeholder typographic mark until the real Boom logo is supplied)The widget is transient — it lives in the chat message. After the user reviews it, the natural next step is the full credit memo workspace via the commercial-credit-memo skill. Offer this proactively as a one-line follow-up.
npx claudepluginhub kwaw-danflo/test-plugin --plugin truist-credit-memo-agentProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.