ai-service-layer
Rule: Domo App Platform AI (Toolkit-First)
This rule is toolkit-first. Use AIClient from @domoinc/toolkit.
Canonical Client
yarn add @domoinc/toolkit
import { AIClient } from '@domoinc/toolkit';
Critical: AIClient methods are static
Do not instantiate AIClient for these methods.
Wrong:
const ai = new AIClient();
await ai.text_to_sql('...');
Correct:
await AIClient.text_to_sql('...');
Text Generation
const response = await AIClient.generate_text(
'Explain this sales trend in simple terms',
{ template: 'You are a business analyst. ${input}' },
{ tone: 'professional' },
undefined,
{ temperature: 0.7 }
);
const body = response.data || response.body || response;
const text = body.output || body.choices?.[0]?.output;
Additional AI Methods
text_to_sql schema argument must be an array
Wrong:
await AIClient.text_to_sql('Show top vendors by spend', {
dataSourceName: 'vendorPayments',
columns: [{ name: 'amount', type: 'number' }]
});
Correct:
await AIClient.text_to_sql('Show top vendors by spend', [
{
dataSourceName: 'vendorPayments',
description: 'Vendor payment invoices',
columns: [
{ name: 'vendor', type: 'string' },
{ name: 'amount', type: 'number' },
{ name: 'date', type: 'date' }
]
}
]);
Signature reference
(Approximate; check installed toolkit typings for exact current signature.)
AIClient.text_to_sql(
input: string,
dataSourceSchemas?: DataSourceSchema[], // array
promptTemplate?: any,
parameters?: Record<string, string>,
model?: string,
modelConfiguration?: Record<string, Object>
): Promise<Response<TextAIResponse>>;
Why array: this supports multi-table SQL generation (including join-aware SQL) when multiple schemas are provided.
text_to_sql usage note
text_to_sql is great for ad-hoc SQL, but /sql/v1 does not automatically apply dashboard/page filters.
If filter-awareness is required in embedded cards, use Query API (/data/v1 via @domoinc/query) for execution.
const sqlResult = await AIClient.text_to_sql('Show total sales by region', [
{
dataSourceName: 'Sales',
description: 'Sales transactions',
columns: [{ name: 'region', type: 'string' }, { name: 'amount', type: 'number' }]
}
]);
const beastModeResult = await AIClient.text_to_beastmode(
'Calculate year over year growth percentage',
{ dataSourceName: 'Revenue', columns: [{ name: 'revenue', type: 'number' }, { name: 'date', type: 'date' }] }
);
Response Handling Rule
AIClient responses are not always shaped like other toolkit clients:
- often uses
response.data - may include both
outputandchoices
Use defensive parsing plus a strict string guard:
const body = response?.data ?? response?.body ?? response;
const outputCandidate = body?.output ?? body?.choices?.[0]?.output;
const output = typeof outputCandidate === 'string' ? outputCandidate.trim() : '';
if (!output) throw new Error('AI returned no usable output');
Checklist
-
AIClientmethods use snake_case (generate_text,text_to_sql, etc.) -
AIClientmethods are called statically (for exampleAIClient.text_to_sql(...), not instance methods) -
AIClient.text_to_sqlsecond argument isDataSourceSchema[](array), not a single object - Responses parsed from
data/bodyfallback - Output extraction includes string guard and empty-output handling
- Error handling and loading state in UI
More from stahura/domo-ai-vibe-rules
domo-js
Use ryuu.js (domo.js) APIs for env, events, navigation, and data calls.
57appdb
Toolkit-first AppDB document CRUD, query operators, and collection wiring.
56html-deck
Build a professional HTML slide deck from source content and convert it to a pixel-perfect PDF. Covers slide architecture, layout patterns, print-safe CSS, Puppeteer PDF conversion, and quality verification. Use when creating presentation decks, converting documents to slide format, or generating PDF decks from HTML.
56migrate-lovable
Convert SSR-heavy Lovable/v0 apps into client-only Domo apps.
56data-api
High-level entry skill for Domo data access. Routes detailed query work to dataset-query.
55jsapi-filters
Apply runtime filters to embedded Domo dashboards/cards from the host page via the JS API (MessagePort). Covers dynamic filtering, drill events, filter change listeners, iframe resize, pfilter URL params, overrideFilters, and App Studio appData. Use for any client-side Domo embed interaction. Not for server-side programmatic filters (use programmatic-filters).
55