Whatever message this page gives is out now! Go check it out!
ChatModel() + agent() pattern. Only the configuration struct changes. For a conceptual overview, see guardrails in the ColdFusion AI framework.chatModel = ChatModel({
PROVIDER: "anthropic",
APIKEY: application.anthropicKey,
MODELNAME: application.anthropicModelName
});
aiService = agent({ CHATMODEL: chatModel });chatModel = ChatModel({
PROVIDER: application.provider,
APIKEY: application.openAikey,
MODELNAME: application.modelName,
temperature: 0
});
aiService = agent({ CHATMODEL: chatModel });temperature: 0 for OpenAI, Azure OpenAI, and Mistral when using schema guardrails. Deterministic output is more reliable with structured schemas.chatModel = ChatModel({
PROVIDER: "azureopenAi",
APIKEY: application.azureopenaikey,
BASEURL: application.azureopenaiEndpoint,
MODELNAME: application.azureModelName,
temperature: 0
});
aiService = agent({ CHATMODEL: chatModel });BASEURL of your deployed endpoint (for example, https://my-resource.openai.azure.com/). Without it the call will fail regardless of schema validity.chatModel = ChatModel({
PROVIDER: "gemini",
APIKEY: application.geminiKey,
MODELNAME: application.geminiModelName
});
aiService = agent({ CHATMODEL: chatModel });chatModel = ChatModel({
PROVIDER: "mistral",
APIKEY: application.mistralkey,
MODELNAME: application.mistralModelName,
temperature: 0,
MAXTOKENS: 2048,
LOGRESPONSES: false,
ResponseFormat: "JSON"
});
aiService = agent({ CHATMODEL: chatModel });ResponseFormat: "JSON" is the Mistral-specific flag that enables JSON mode. Without it, Mistral may include markdown fences or prose around the JSON.chatModel = ChatModel({
PROVIDER: "ollama",
BASEURL: application.ollamaurl,
MODELNAME: application.ollamaModelName,
responseFormat: "json"
});
aiService = agent({ CHATMODEL: chatModel });BASEURL points to the Ollama server. Local models vary in their JSON output reliability. Set responseFormat: "json" to improve consistency.SCHEMA key in the aiService.chat() call with a plain ColdFusion struct.response = aiService.chat({
USERMESSAGE: { MESSAGE: "Return person Alice who is 30 years old and active." },
SCHEMA: { "name": "String", "age": "Number", "active": "Boolean" }
});SchemaFactory CFC.component displayname="SchemaFactory" {
public struct function getPersonSchema() {
return {
"firstName": "String",
"lastName": "String",
"age": "Number",
"active": "Boolean?"
};
}
}
factory = new SchemaFactory();
response = aiService.chat({
USERMESSAGE: { MESSAGE: "Return person Jane Doe age 32 active true." },
SCHEMA: factory.getPersonSchema()
});SchemaFactory CFC or in application scope. Do not repeat schema definitions across CFMs — one change should update everywhere.// Application.cfc — onApplicationStart()
application.aiSchemas = {
person: {
"firstName": "String",
"lastName": "String",
"age": "Number",
"email": "String?",
"active": "Boolean"
},
order: {
"orderId": "String",
"customer": "String",
"total": "Number",
"items": [{ "product": "String", "quantity": "Number", "price": "Number" }]
}
};
// Any CFM
response = aiService.chat({
USERMESSAGE: { MESSAGE: "..." },
SCHEMA: application.aiSchemas.person
});aiService.systemMessage() before aiService.chat() to set behavioral constraints on the model.aiService.systemMessage(
"You are a nutrition expert. You MUST provide accurate nutritional data including " &
"calories, protein, and serving information. Always respond with precise numbers."
);
response = aiService.chat({
USERMESSAGE: { MESSAGE: "Give info for Caesar Salad, 4 servings, 350 calories, 15g protein." },
SCHEMA: {
"recipe": "String",
"servings": "Number",
"nutrition": {
"calories": "Number",
"protein": "String"
}
}
});aiService.chat() call in try/catch.try {
response = aiService.chat({
USERMESSAGE: { MESSAGE: "Return data." },
SCHEMA: { "created": "Date" }
});
} catch (any e) {
errType = e.type;
errMsg = e.message;
}
if (len(errMsg)) {
writeLog(file="ai_errors", type="error", text="Schema error: #errMsg#");
}public function onApplicationStart() {
try {
application.schemas = {
person: { "firstName": "String", "lastName": "String", "age": "Number" },
order: { "orderId": "String", "total": "Number", "items": [{ "product": "String", "price": "Number" }] },
company: { "name": "String", "founded": "Number", "active": "Boolean?" }
};
writeLog(file="application", type="info", text="AI schemas initialized.");
} catch (any e) {
writeLog(file="application", type="error", text="Invalid schema at startup: #e.message#");
rethrow;
}
return true;
}isJSON() before calling deserializeJSON().response = aiService.chat({ USERMESSAGE: { MESSAGE: "..." }, SCHEMA: { "name": "String" } });
text = response.message ?: "";
parsed = isJSON(text) ? deserializeJSON(text) : {};
if (structIsEmpty(parsed)) {
writeLog(file="ai_errors", type="warning", text="Non-JSON response: #text#");
}structKeyExists() to check field presence before accessing any field.hasName = structKeyExists(parsed, "name") && len(trim(parsed.name)) > 0;
hasAge = structKeyExists(parsed, "age") && isNumeric(parsed.age);
if (!hasName || !hasAge) {
throw(type="AIResponseError", message="Required fields missing from AI response");
}hasItems = structKeyExists(parsed, "items") &&
isArray(parsed.items) &&
arrayLen(parsed.items) >= 1;
if (hasItems) {
for (var item in parsed.items) {
if (!isStruct(item) || !structKeyExists(item, "product") || !structKeyExists(item, "price")) {
hasItems = false;
break;
}
}
}chatWithFallback function.function chatWithFallback(required struct chatRequest, required array providers) {
var lastError = "";
for (var providerConfig in arguments.providers) {
try {
var model = ChatModel(providerConfig);
var service = agent({ CHATMODEL: model });
return service.chat(arguments.chatRequest);
} catch (any e) {
lastError = e.message;
writeLog(file="ai_fallback", type="warning",
text="Provider #providerConfig.PROVIDER# failed: #e.message#");
}
}
throw(type="AIUnavailable", message="All providers failed. Last error: #lastError#");
}
providers = [
{ PROVIDER: "anthropic", APIKEY: application.anthropicKey, MODELNAME: "claude-3-5-sonnet-20241022" },
{ PROVIDER: "openai", APIKEY: application.openAikey, MODELNAME: "gpt-4o", temperature: 0 },
{ PROVIDER: "mistral", APIKEY: application.mistralkey, MODELNAME: application.mistralModelName, temperature: 0 }
];composeSchema function.function composeSchema(required struct base, struct extension = {}) {
var result = duplicate(arguments.base);
if (!structIsEmpty(arguments.extension)) {
structAppend(result, arguments.extension, true);
}
return result;
}
basePersonSchema = { "firstName": "String", "lastName": "String", "age": "Number" };
adminExtension = { "internalId": "Number", "accessLevel": "String", "lastLogin": "String?" };
schema = isAdminUser ? composeSchema(basePersonSchema, adminExtension) : basePersonSchema;
response = aiService.chat({
USERMESSAGE: { MESSAGE: extractionPrompt },
SCHEMA: schema
});aiService.chat() with a SCHEMA key will return structured JSON that conforms to the defined contract, with schema validation errors thrown before any API quota is consumed.