Skip to main content

Text Generation

Text generation covers chat-style completions: summarizing, rewriting, translating, classifying, and generating free text from natural-language instructions. It is the model kind behind the CKEditor AI Assistant in the HTML editor and behind general-purpose chat completions for your own integrations.

Model

Model IDadito-llm
Base modelQwen3.5-35B-A3B-FP8
HostingADITO Cloud infrastructure, Germany
Base URLhttps://ai.adito.cloud
Endpoint/chat/completions
InterfaceOpenAI-compatible Chat Completions API
Context window262,144 tokens (prompt and response combined)
Image inputSupported on every codename, see Image input and OCR
Background and release context

For an overview of why the platform exists and how it is introduced, see AI is Part of ADITO Cloud. For the rollout of enable_thinking, see ADITO-LLM Now Supports Thinking.

info

The API uses the same request and response structure as the OpenAI API. You can use official OpenAI client libraries (such as openai for JavaScript/TypeScript) by changing only the base URL and API key.

Pinned versions

CodenameBase modelQuantizationStatusSunset / retired date
adito-llm-brizoQwen3.6-35B-A3B-NVFP4-FastNVFP4Active (GA)
adito-llm-atheneQwen3.5-35B-A3B-FP8FP8Deprecated2026-08-31

The floating alias adito-llm currently still points to adito-llm-athene. Pin adito-llm-brizo explicitly to start tuning your integration against the new model ahead of time — the bare alias switches over to adito-llm-brizo only when adito-llm-athene retires on 2026-08-31. See Model naming and versioning for how floating aliases and pinned codenames work; the same scheme applies to every model kind in the runtime, not just to text generation.

Default request parameters

Every generation parameter you do not send is filled in by the runtime with the value below. These defaults are part of what a pinned codename freezes, so they never change for an existing codename — a new codename is issued instead.

Defaults, not limits

A value you send in the request body always wins over the default. Only the context window is a hard limit rather than something you can override.

Defaults for adito-llm-brizo
ParameterDefaultDescription
chat_template_kwargs.enable_thinkingfalseThinking mode is off. Send true to enable reasoning before the answer.
temperature0.7Sampling randomness. Lower values produce more deterministic output.
top_p0.8Nucleus sampling cutoff.
top_k20Number of candidate tokens considered per step.
min_p0.0Minimum probability threshold, relative to the most likely token.
presence_penalty1.5Discourages repetition of tokens that already appeared.
max_tokens32768Upper bound for the generated response.
Context window262144Hard limit for prompt and response combined. Not a request parameter.
Defaults for adito-llm-athene (deprecated)
ParameterDefaultDescription
chat_template_kwargs.enable_thinkingfalseThinking mode is off. Send true to enable reasoning before the answer.
temperature0.7Sampling randomness. Lower values produce more deterministic output.
top_p0.8Nucleus sampling cutoff.
top_k20Number of candidate tokens considered per step.
min_p0.0Minimum probability threshold, relative to the most likely token.
presence_penalty1.5Discourages repetition of tokens that already appeared.
max_tokens32768Upper bound for the generated response.
Context window262144Hard limit for prompt and response combined. Not a request parameter.

What you can build

  • Summarization — condense customer interactions, emails, or long notes into a few sentences.
  • Rewriting — adjust tone or clarity of drafted text; this is what powers the CKEditor AI Assistant.
  • Translation — translate free-text fields such as emails, notes, or product descriptions between languages. See the Prompting Guide for examples.
  • Classification — sort emails, notes, or tickets by priority, topic, or team using guided_json to constrain the output to a schema.
  • Structured AI outputs for automation — constrain any response to a defined JSON schema with guided_json so it flows directly into automated workflows or gets imported as a CRM entity, without manual parsing.
  • CRM-aware prompts — include CRM data (accounts, opportunities, activities) in the messages array, for example to summarize a customer's history, suggest next actions, or draft emails from existing records.
  • Natural-language task execution — combine CRM-aware prompts with function calling to let the model trigger CRM actions from plain-language instructions, e.g. "Create a quote based on this customer and their last opportunities."
  • Scheduled record enrichment — call the API from a scheduled server process or ADITO web service to enrich records with summaries, keywords, or classifications on a schedule.
  • OCR and document reading — read the text off a scanned invoice, a photographed delivery note, or a screenshot by sending the image together with your prompt. See Image input and OCR.

Authentication

Every request requires an API key, passed as the apiKey parameter when initializing the client. Managed cloud systems receive a system API key automatically at startup. If you need a personal key, contact the AI team.

warning

Keep your API key confidential. Do not expose it in client-side code or public repositories.

Request parameters

The API follows the OpenAI chat completions format. The table below lists the most commonly used parameters. Any parameter you omit falls back to the server-side value listed under Default request parameters.

ParameterTypeRequiredDescription
modelStringYesName of the model to use, e.g. adito-llm.
messagesArrayYesArray of message objects, each with a role and content field.
temperatureNumberNoControls response creativity. Lower values produce more deterministic output.
max_tokensNumberNoMaximum number of tokens in the response.
guided_jsonObjectNoADITO-specific. JSON schema that constrains the model output. See Guided JSON output.
chat_template_kwargsObjectNoADITO-specific. Extra keyword arguments forwarded to the model's chat template. Currently supports enable_thinking (boolean, default false) to enable thinking mode.
ADITO-specific parameter

guided_json is not the same as the standard OpenAI response_format parameter. It is an ADITO-specific extension that enforces a JSON schema on the model output at the inference level. Do not use response_format — use guided_json instead.

For a full list of supported parameters, refer to the OpenAI API documentation.

First how-to: basic chat completion

note

The code examples on this page are not JDito code. They illustrate general API usage and can be adapted to any language or HTTP client.

curl https://ai.adito.cloud/chat/completions \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "adito-llm",
"messages": [
{ "role": "system", "content": "You are a CRM assistant. Summarize customer interactions in two sentences." },
{ "role": "user", "content": "Customer Acme Corp had 3 calls last week about delayed shipments, followed by a meeting where a 10% discount was offered." }
],
"temperature": 0.3
}'

Advanced usage

Image input and OCR

ADITO-LLM reads images, not only text. The /chat/completions endpoint takes an image as part of the message, so OCR is a normal chat request: send the image with an instruction, get the text back. There is no separate OCR service and no extra API key.

Image input works on the floating alias adito-llm and on every pinned codename, so nothing has to be migrated first.

Instead of a plain string, content becomes an array of parts. Each part is either a text part with your instruction or an image_url part with the image itself:

PartFieldDescription
texttextThe instruction that tells the model what to do with the image.
image_urlimage_url.urlA base64 data URL (data:image/png;base64,...) or an HTTPS URL the runtime can reach.

Use common web image formats such as PNG, JPEG, or WebP. A PDF is not an image: render the pages you need to images first, then send those. You can put several image_url parts into one message, for example for a multi-page scan.

How to run an OCR request

  1. Load the image and base64-encode it, or make it available under an HTTPS URL the runtime can reach.
  2. Build the data URL with the MIME type matching the image, for example data:image/png;base64,<encoded>.
  3. Send one text part with the transcription instruction and one image_url part per page.
  4. Set temperature to 0. The default of 0.7 is meant for creative text, while transcription should reproduce what is on the page instead of paraphrasing it.
# Encode the scan; -w 0 keeps the output on a single line
IMAGE_B64=$(base64 -w 0 invoice-scan.png)

curl https://ai.adito.cloud/chat/completions \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "adito-llm",
"messages": [
{ "role": "system", "content": "You transcribe documents. Return only the text you can read, without commentary." },
{ "role": "user", "content": [
{ "type": "text", "text": "Transcribe all text from this invoice and keep the original line order." },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,'"$IMAGE_B64"'" } }
]}
],
"temperature": 0
}'

From scan to CRM record

Plain transcription is rarely the goal. Combine image input with guided_json and the same request returns the fields you want to write to a record, so no parsing step is needed between the scan and the CRM.

Click to expand structured invoice extraction example
import fs from 'fs';
import OpenAI from 'openai';

const openai = new OpenAI({
baseURL: 'https://ai.adito.cloud',
apiKey: 'your-api-key'
});

async function extractInvoice() {
const base64 = fs.readFileSync('invoice-scan.png').toString('base64');

const response = await openai.chat.completions.create({
model: 'adito-llm',
messages: [
{
role: 'system',
content: 'You extract invoice data. Use null for any field that is not readable on the document.'
},
{
role: 'user',
content: [
{ type: 'text', text: 'Extract the invoice header and all line items from this scan.' },
{ type: 'image_url', image_url: { url: `data:image/png;base64,${base64}` } }
]
}
],
temperature: 0,
// guided_json is ADITO-specific — do not use response_format
guided_json: {
type: 'object',
properties: {
invoice_number: { type: ['string', 'null'] },
invoice_date: { type: ['string', 'null'], description: 'ISO date, YYYY-MM-DD' },
supplier_name: { type: ['string', 'null'] },
currency: { type: ['string', 'null'], description: 'ISO 4217 code, e.g. EUR' },
total_gross: { type: ['number', 'null'] },
line_items: {
type: 'array',
items: {
type: 'object',
properties: {
description: { type: 'string' },
quantity: { type: 'number' },
unit_price: { type: 'number' }
},
required: ['description']
}
}
},
required: ['invoice_number', 'invoice_date', 'supplier_name', 'total_gross'],
additionalProperties: false
}
});
console.log(response.choices[0].message.content);
// → {"invoice_number":"2026-4711","invoice_date":"2026-07-14","supplier_name":"Acme Corp", ...}
}

extractInvoice();
What affects the result

Recognition quality follows the input. A straight, sharp scan at roughly 300 dpi reads much better than a tilted phone photo, and printed text reads better than handwriting. Validate extracted values before they reach a record, above all amounts, dates and identifiers.

Payload size and timeout

Images consume tokens from the same 262,144-token context window as text, and base64 encoding inflates the transferred payload by about a third. The 120-second timeout and the 20 MB limit on the request body apply here as well, see Request limits. Send pages in separate requests rather than putting a large multi-page document into a single one.

Guided JSON output

The API supports guided JSON output, which constrains the model response to match a defined JSON schema. This is useful when the result needs to be processed programmatically — for example, to create or update CRM records.

Click to expand guided JSON example
import OpenAI from 'openai';

const openai = new OpenAI({
baseURL: 'https://ai.adito.cloud',
apiKey: 'your-api-key'
});

async function classifyEmail() {
const response = await openai.chat.completions.create({
model: 'adito-llm',
messages: [
{
role: 'system',
content: 'You are a CRM email classifier. Analyze the email and return structured data.'
},
{
role: 'user',
content: `Classify this email:\n\nSubject: Urgent — production system down\nBody: Our main ERP integration has stopped syncing since this morning. We need immediate help. This is blocking 50+ users.`
}
],
temperature: 0.15,
// guided_json is ADITO-specific — do not use response_format
guided_json: {
type: 'object',
properties: {
subject_summary: { type: 'string' },
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
category: { type: 'string', enum: ['bug', 'feature_request', 'support', 'billing', 'other'] },
suggested_team: { type: 'string' }
},
required: ['subject_summary', 'priority', 'category'],
additionalProperties: false
}
});
console.log(response.choices[0].message.content);
// → {"subject_summary":"ERP integration sync failure","priority":"critical","category":"bug","suggested_team":"Integrations"}
}

classifyEmail();

Function calling and tool use

The API supports OpenAI-style function calling. You define tools as part of the request, and the model decides when to invoke them based on the conversation context.

The example below shows a CRM scenario: the user asks about a contact's recent activity, and the model calls two tools — one to look up activities and another to create a follow-up task.

Click to expand function calling example
import OpenAI from 'openai';

const openai = new OpenAI({
baseURL: 'https://ai.adito.cloud',
apiKey: 'your-api-key'
});

async function handleContactQuery() {
const response = await openai.chat.completions.create({
model: 'adito-llm',
messages: [
{
role: 'system',
content: 'You are a CRM assistant. Use the available tools to look up data and create records.'
},
{
role: 'user',
content: 'Show me the last 5 activities for contact "Maria Hoffmann" and create a follow-up call for next Monday.'
}
],
tools: [
{
type: 'function',
function: {
name: 'get_contact_activities',
description: 'Retrieve recent activities for a CRM contact.',
parameters: {
type: 'object',
properties: {
contact_name: { type: 'string', description: 'Full name of the contact' },
limit: { type: 'number', description: 'Maximum number of activities to return' }
},
required: ['contact_name']
}
}
},
{
type: 'function',
function: {
name: 'create_activity',
description: 'Create a new activity (call, meeting, task) in the CRM.',
parameters: {
type: 'object',
properties: {
contact_name: { type: 'string', description: 'Full name of the contact' },
activity_type: { type: 'string', enum: ['call', 'meeting', 'task'], description: 'Type of activity' },
subject: { type: 'string', description: 'Subject line for the activity' },
due_date: { type: 'string', description: 'Due date in YYYY-MM-DD format' }
},
required: ['contact_name', 'activity_type', 'subject', 'due_date']
}
}
}
],
tool_choice: 'auto',
temperature: 0.15
});

// Process tool calls from the response
const toolCalls = response.choices[0].message.tool_calls;
if (toolCalls) {
toolCalls.forEach(call => {
console.log(`Tool: ${call.function.name}, Args: ${call.function.arguments}`);
});
}
}

handleContactQuery();

Thinking mode

Thinking mode makes the model reason through the problem before responding. Use it when the task requires more than pattern-matching: complex classification, ambiguous inputs, or long documents where the model needs to work out an answer rather than retrieve one.

Enable it by adding chat_template_kwargs: { enable_thinking: true } to your request. The default is false. Existing requests are unaffected.

note

Thinking mode increases response latency and token usage. Enable it only for tasks where reasoning depth outweighs the cost.

Request timeout

Requests to the API time out after 120 seconds. Thinking mode combined with long documents or a high max_tokens value can push complex requests close to this limit. If you hit timeouts, reduce input length, lower max_tokens, or split the task into smaller requests.

curl https://ai.adito.cloud/chat/completions \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "adito-llm",
"chat_template_kwargs": { "enable_thinking": true },
"messages": [
{
"role": "system",
"content": "You are a CRM analyst. Analyse the support case and determine root cause, urgency, and recommended action."
},
{
"role": "user",
"content": "Customer reports intermittent login failures since last Friday. Affects roughly 30% of users. No error message shown — the login form just resets. Backend logs show no authentication errors."
}
],
"temperature": 0.15
}'

Error handling

API requests can fail due to authentication errors, rate limits, or invalid parameters. Wrap your calls in a try/catch block and inspect the error response.

async function safeChatCompletion() {
try {
const response = await openai.chat.completions.create({
model: 'adito-llm',
messages: [
{ role: 'user', content: 'Summarize this account.' }
]
});
return response.choices[0].message.content;
} catch (error) {
// The OpenAI client throws an error with status and message
console.error(`API error: ${error.status}${error.message}`);
// Common status codes:
// 401 — Invalid or missing API key
// 429 — Rate limit exceeded, retry after a delay
// 500 — Server error, retry or contact the AI team
// Timeout after 120 seconds — reduce input/max_tokens or split the request
}
}

See also: Prompting Guide | AI Models