N/llm Module Adds Streamed Text Generation via generateTextStreamed
SuiteScript 2.1 gains llm.generateTextStreamed(options) in the N/llm module, enabling token-by-token streaming of LLM responses in server scripts at 100 governance units per call. Tool-calling support (options.tools and options.toolResults) was added in 2025.2.
What changed
The N/llm module now exposes llm.generateTextStreamed(options) (aliased as llm.chatStreamed(options)), a streaming counterpart to the existing llm.generateText(options). Instead of waiting for the full LLM response, you can iterate over tokens as they arrive and read the partial response at any point via StreamedResponse.text.
Key details
- Governance: 100 units per call.
- Script types: Server scripts only (Scheduled, Map/Reduce, Suitelet, User Event, RESTlet, etc.).
- Default model: Cohere Command A (
cohere.command-a-03-2025) whenoptions.modelFamilyis omitted. Set via thellm.ModelFamilyenum. - Default timeout: 30,000 ms. Configurable with
options.timeout. - Parallelism cap: Maximum 5 concurrent requests to the LLM per script execution; exceeding this throws
MAXIMUM_PARALLEL_REQUESTS_LIMIT_EXCEEDED. - Safety mode: Defaults to
llm.SafetyMode.STRICT. Cohere models only.
Streaming pattern
The returned llm.StreamedResponse object supports the standard SuiteScript iterator protocol:
var response = llm.generateTextStreamed({
prompt: "Summarize open sales orders",
modelFamily: llm.ModelFamily.COHERE_COMMAND,
modelParameters: { maxTokens: 1000, temperature: 0.2 }
});
var iter = response.iterator();
iter.each(function(token) {
log.debug("token: " + token.value);
log.debug("partial: " + response.text);
return true;
});OCI unlimited-usage mode
You can supply your own Oracle Cloud Infrastructure (OCI) Generative AI credentials via options.ociConfig to bypass NetSuite's bundled usage limits. The config accepts userId, tenancyId, compartmentId, fingerprint, and privateKey. The fingerprint and privateKey values must be NetSuite API secrets (created via Setup > Company > API Secrets); raw strings throw ONLY_API_SECRET_IS_ACCEPTED. These can also be set account-wide on the AI Preferences page > SuiteScript subtab; per-call values override the page-level defaults.
Tool calling (2025.2)
Two parameters were added in 2025.2:
options.tools— an array ofllm.Toolobjects describing functions the LLM may request.options.toolResults— an array ofllm.ToolResultobjects returned after your script executes the requested tool calls. WhentoolResultsis provided,options.promptis ignored and the LLM generates a follow-up response based solely on the tool output.
Tool call requests appear in StreamedResponse.toolCalls. This enables an agentic loop: call generateTextStreamed with tools, inspect toolCalls, execute them, then call again with toolResults.
RAG via documents (Cohere only)
The options.documents parameter accepts an array of llm.Document objects (created with llm.createDocument(options)) for retrieval-augmented generation. Document IDs must be unique or DOCUMENT_IDS_MUST_BE_UNIQUE is thrown. This parameter is not supported for non-Cohere model families.
Model parameters
Standard LLM tuning knobs are available under options.modelParameters: maxTokens, temperature, topK, topP, frequencyPenalty, and presencePenalty. Note that for COHERE_COMMAND, you cannot set both frequencyPenalty and presencePenalty above zero simultaneously — doing so throws MUTUALLY_EXCLUSIVE_ARGUMENTS.
What to do
- Choose streaming vs. blocking: Use
generateTextStreamedwhen you need progressive output (e.g., writing partial results to a record or log during long generations). UsegenerateTextwhen you only need the final result. - Budget governance: Each call costs 100 units. In Map/Reduce scripts, plan your usage within the 1,000-unit-per-invocation limit — you get at most 10 LLM calls per map or reduce invocation before needing to yield.
- Store OCI credentials as secrets: If using unlimited-usage mode, create API secrets for your OCI private key and fingerprint before writing any script code. Raw credential strings will be rejected at runtime.
- Adopt tool calling for agentic patterns (2025.2+): If you are on 2025.2 or later, you can define tools and implement the tool-call loop. Verify your account is on 2025.2 before using
options.toolsoroptions.toolResults— these parameters do not exist in 2025.1 and will be silently ignored or throw errors. - Handle content filtering: Wrap calls in try/catch for
INAPPROPRIATE_CONTENT_DETECTED. The default safety mode isSTRICT; if you need less aggressive filtering, explicitly setoptions.safetyMode(Cohere models only). - Respect the 5-request concurrency limit: If you are firing multiple LLM calls in parallel (e.g., via
Promise.allin SuiteScript 2.1), keep concurrent requests at or below 5.
Source: Oracle NetSuite Release Notes