Loading...
Loading...
NetSuite Intelligence skill — teaches AI the correct tool selection order, output formatting, domain knowledge, multi-subsidiary and currency handling, and SuiteQL safety checklist for any AI + NetSuite AI Service Connector session.
npx skill4agent add oracle/netsuite-suitecloud-sdk netsuite-ai-connector-instructionsPRIORITY 1 → ns_listAllReports → ns_runReport
PRIORITY 2 → ns_listSavedSearches → ns_runSavedSearch
PRIORITY 3 → ns_getRecordTypeMetadata → ns_getRecord / ns_createRecord / ns_updateRecord
PRIORITY 4 → ns_getSuiteQLMetadata → ns_runCustomSuiteQL ← LAST RESORTCan a standard report answer this?
YES → ns_listAllReports → ns_runReport → STOP
NO ↓
Is there a saved search for this?
YES → ns_listSavedSearches → ns_runSavedSearch → STOP
NO ↓
Is this a record lookup, create, or update?
YES → ns_getRecordTypeMetadata → ns_getRecord / ns_createRecord / ns_updateRecord → STOP
NO ↓
Has user confirmed a custom SuiteQL query is acceptable?
YES → ns_getSuiteQLMetadata → ns_runCustomSuiteQL (ROWNUM required)
NO → Ask: "I can't find a standard report or saved search for this.
Would you like me to try a custom SuiteQL query?"ns_listAllReportsns_getSubsidiarieshas_subsidiary_filter: truens_getRecordTypeMetadatans_getSuiteQLMetadataexternalIdns_createRecordROWNUM <= 1000ns_createRecord| Raw Value | Formatted Output |
|---|---|
| 2100000 | $2.1M |
| 342500 | $342.5K |
| 0.123 | 12.3% |
| 1.05 | 105.0% |
| 2100000 | $2,100,000 (full) |
$X.XM$X.XKX.X%| Record Type | URL Pattern |
|---|---|
| Invoice | |
| Sales Order | |
| Purchase Order | |
| Vendor Bill | |
| Payment | |
| Journal Entry | |
| Credit Memo | |
| Customer | |
| Vendor | |
| Employee | |
| Report | |
target="_blank"#36677DTransactions
├── Sales: Opportunity → Quote → Sales Order → Invoice → Payment
├── Purchasing: PO → Item Receipt → Vendor Bill → Bill Payment
├── Finance: Journal Entry, Bank Deposit, Bank Transfer, Expense Report
└── Inventory: Transfer Order, Inventory Adjustment, Work Order
Entities
├── Customer / Prospect / Lead → recordtype: custjob
├── Vendor → recordtype: vendor
├── Employee → recordtype: employee
└── Contact → recordtype: contact| Account Type | Normal Balance | Debit Effect | Credit Effect |
|---|---|---|---|
| Asset | Debit | Increases | Decreases |
| Liability | Credit | Decreases | Increases |
| Equity | Credit | Decreases | Increases |
| Revenue | Credit | Decreases | Increases |
| Expense | Debit | Increases | Decreases |
recordtype| Transaction | recordtype value |
|---|---|
| Invoice | |
| Sales Order | |
| Purchase Order | |
| Vendor Bill | |
| Customer Payment | |
| Journal Entry | |
| Credit Memo | |
| Bank Deposit | |
| Bank Transfer | |
| Expense Report | |
| Work Order | |
| Concept | Field Name |
|---|---|
| Transaction date | |
| Document number | |
| Base currency amount | |
| Foreign currency amount | |
| Exchange rate | |
| Transaction type | |
| Approval status (approved=2) | |
| Posting flag (posted=T) | |
| Subsidiary | |
| GL account | |
| Entity | |
| Department | |
| Class | |
| Location | |
ns_listAllReports| Scope | How to Handle |
|---|---|
| Consolidated | Standard reports handle currency conversion automatically |
| Single subsidiary | Pass |
| Multi-subsidiary comparison | Run report once per subsidiary, combine results in artifact |
foreignamountamountSELECT
s.name AS subsidiary,
s.currency AS currency,
NVL(SUM(tl.amount), 0) AS base_amount,
NVL(SUM(tl.foreignamount), 0) AS foreign_amount
FROM transactionline tl
JOIN transaction t ON t.id = tl.transaction
JOIN subsidiary s ON s.id = t.subsidiary
WHERE t.recordtype = '[type]'
AND t.posting = 'T'
AND t.approvalstatus = 2
AND t.trandate >= TO_DATE('[start]', 'MM/DD/YYYY')
AND t.trandate <= TO_DATE('[end]', 'MM/DD/YYYY')
AND ROWNUM <= 1000
GROUP BY s.name, s.currency
ORDER BY base_amount DESC□ Standard reports cannot provide this data — confirmed
□ Saved searches cannot provide this data — confirmed
□ User has confirmed a custom SuiteQL query is acceptable
□ ns_getSuiteQLMetadata called for every table in the query
□ All JOINs verified against metadata
□ ROWNUM <= 1000 in WHERE clause
□ NVL() on all nullable amount/text fields
□ posting = 'T' where GL accuracy required
□ approvalstatus = 2 where approved-only data required
□ Dates use TO_DATE('MM/DD/YYYY') format
□ No WITH/CTE — use inline subqueries
□ No OFFSET/FETCH — use ROWNUM pagination
□ No SELECT * — specify columns explicitlySELECT
t.id,
t.tranid,
t.trandate,
t.recordtype,
NVL(e.companyname, 'Unknown') AS entity_name,
NVL(t.amount, 0) AS amount,
NVL(t.foreignamount, 0) AS foreign_amount,
NVL(t.memo, 'No memo') AS memo
FROM transaction t
LEFT JOIN customer e ON e.id = t.entity
WHERE t.recordtype = '[type]'
AND t.posting = 'T'
AND t.approvalstatus = 2
AND t.trandate >= TO_DATE('[start]', 'MM/DD/YYYY')
AND t.trandate <= TO_DATE('[end]', 'MM/DD/YYYY')
AND ROWNUM <= 1000
ORDER BY t.trandate DESC| Mistake | Correct Approach |
|---|---|
| No ROWNUM limit | Always |
| Always list columns explicitly |
| Missing NVL on amounts | |
| JOIN without metadata check | Always call |
Missing | Add for all GL / financial queries |
Missing | Add for approved-transactions-only |
| Hardcoded subsidiary IDs | Use |
| OFFSET/FETCH pagination | Use ROWNUM-based subquery pagination |
| WITH/CTE syntax | Rewrite as inline subquery |
| Use |
| Use |
| Use |
| Record | Table | Essential Fields |
|---|---|---|
| Transaction | | id, tranid, trandate, recordtype, entity, amount, foreignamount, subsidiary, posting, approvalstatus |
| Transaction Line | | id, transaction, account, amount, foreignamount, department, class, location |
| Account (COA) | | id, acctnumber, fullname, accttype, currency, parent |
| Customer | | id, entityid, companyname, email, subsidiary |
| Vendor | | id, entityid, companyname, email |
| Employee | | id, entityid, email, department, subsidiary |
| Item | | id, itemid, displayname, itemtype, baseprice |
| Subsidiary | | id, name, currency, parent |
| Accounting Period | | id, periodname, startdate, enddate, isquarter, isyear, closed |
| Error | Recovery Action |
|---|---|
| Tool call fails / timeout | Retry once → try alternative tool → inform user with NetSuite navigation path |
| Report not found | Try alternate names → try saved searches → ask user for custom name |
| No data returned | Loosen date range → remove filters → suggest alternative scope |
| Permission denied | Don't show raw error → tell user which role/permission is needed |
| Record create fails | Don't auto-retry → ask user to verify in NetSuite → new UUIDv4 on retry |
| Unexpected outlier | Flag: "This figure looks unusual — please verify in your NetSuite UI" |
| Multi-subsidiary conflict | Ask: "Which subsidiary, or consolidated results?" |
| SuiteQL syntax error | Fix query using metadata, retry once → if still failing, suggest saved search |
| Data Needed | NetSuite UI Path |
|---|---|
| Income Statement | Reports → Financial → Income Statement |
| Balance Sheet | Reports → Financial → Balance Sheet |
| Cash Flow | Reports → Financial → Cash Flow Statement |
| AR Aging | Reports → Receivables → Accounts Receivable Aging |
| AP Aging | Reports → Payables → Accounts Payable Aging |
| Bank Accounts | Lists → Accounts → Accounts → filter: Bank |
| Open Invoices | Transactions → Sales → Invoices → filter: Open |
| Vendor Bills | Transactions → Payables → Enter Bills → filter: Open |
| Budget vs Actual | Reports → Financial → Budget vs. Actual |
TOOLS: 1→Reports 2→SavedSearches 3→Records 4→SuiteQL(confirm first)
NUMBERS: $2.1M | $342.5K | 12.3% | full in tables
LINKS: hyperlink every transaction + entity | color #36677D
ARTIFACT: 3+ metrics OR 10+ rows OR dashboard/report/compare request
REDWOOD: #003764 headers #D64700 alerts #3D7A41 positive #B95C00 warning
CREATES: always externalId=UUIDv4 | never auto-retry on failure
SUITEQL: user must confirm | ROWNUM<=1000 | NVL all amounts