Home > Ajabbi Research > Library > Subscriptions > Quanta Magazine
Home > Handbook >
Last Updated
24/10/2026
The Riemann Hypothesis, Explained
By: Alex Kontorovich
Quanta Magazine: 05/01/2021
Alex Kontorovich:A professor of mathematics at Rutgers University.
...
The Riemann Hypothesis is the most notorious unsolved problem in all of mathematics. Ever since it was first proposed by Bernhard Riemann in 1859, the conjecture has maintained the status of the "Holy Grail" of mathematics. The person who solves it will win a $1 million prize from the Clay Institute of Mathematics. So, what is the Riemann Hypothesis? Why is it so important? What can it tell us about the chaotic universe of prime numbers? And why is its proof so elusive? Alex Kontorovich, professor of mathematics at Rutgers University, breaks it all down in this comprehensive explainer.
Yesterday (Wednesday NZ time), I attended the Google Startups Product Roadmap Seminar: October 2026 via
Google Meet.
"Join Google Cloud and Wiz specialists to explore the
latest in startup security and Gemini, with a deep dive into our
newest models. This session is exclusively tailored for our
strategic Google Cloud startup customers." - Google
These great presentations got me thinking, and this morning I solved
this problem on the big list.
"How to connect any LLM model, starting with Gemini, to a
Pipi workspace so that an Ajabbi customer can use AI tools
without the AI changing the actual workspace code. Everything must run
in CFML on Ortus BoxLang, starting from Pipi 10."
Update 23/10/2026
The AGNTCon + MCPCon North America is on today (5 am to 2 pm NZ time), and I'm watching it live. The unforgettable Demetrios Brinkmann from AAIF is the host. Fantastic coverage of many of the issues in great depth, connected with solving this
problem;
By: Mike Peters and Google Search AI Mode (Gemini)
On a Sandy Beach: 22/10/2026
Mike Peters: Mike invented and designed Pipi and founded
Ajabbi.
Google Search AI Mode (Gemini): GSAM is great.
...
Today, using Google Search AI Mode, I asked some
very dumb questions about using connectors. I did this to find a way
to safely connect any workspace generated by Pipi running in CFML on
BoxLang to Gemini. Originally, MCP was the top
contender.
Here is the raw output, with Grammarly post-editing; I'll rework
the code manually. This is a good place to start.
Boxlang AI Module is free and open-source.
Remember, "Use this code with caution." 😎😎😎😎
Mike: What is a connector for Google Gemini?
Gemini:A Google Gemini connector is a secure
bridge that links Google Gemini with external apps, databases, and
third-party software.
Depending on the context, a "connector" refers to either data-ingestion
tools built into enterprise versions of Gemini or third-party integrations
that let other software platforms use Gemini’s AI model
capabilities.
1. Gemini Enterprise Connectors (Data Ingestion)
In Gemini Enterprise (Business, Standard, and Plus editions), IT
administrators manage connectors to securely bring scattered organisational
data into Gemini. This allows users to search, summarise, and analyse their
company's internal information using natural language.
Google Connectors: Link seamlessly to core Google Workspace apps
such as Gmail, Google Drive, Google Calendar, Chat, and Google
Sites.
Third-Party Connectors: Provide native access to external business
ecosystems. Gemini Enterprise supports over 100 integrations, including
Microsoft 365 (SharePoint, OneDrive),
Atlassian (Jira, Confluence), Salesforce,
ServiceNow, Slack, and Zendesk.
Custom Connectors: If a specific proprietary database or software
isn't in the standard catalogue, companies can build custom connectors
using the Google Cloud Discovery Engine API to fetch, transform,
and sync their data.
2. Outbound Connectors (AI for External Apps)
Conversely, many software developers use "Gemini Connectors" to inject
Gemini's AI capabilities into other software. In this scenario, the
connector acts as an API plugin. Examples include:
Automation Platforms: Tools
like Camunda and Microsoft Power Automate utilise a custom Gemini connector so business processes can
automatically generate text, analyse sentiment, or extract keywords from
files.
App Development Modules: Low-code platforms like Mendix feature
pre-packaged Gemini modules that let developers easily build AI chatbots,
translate languages, or parse large blocks of text directly inside their
applications.
Gemini: Are you looking to connect your enterprise data (like Jira
or SharePoint) to Gemini, or are you trying to build Gemini's AI features
into an external app you are developing? Let me know so I can provide the
exact steps or documentation links!
Mike: I want to find a way to connect an enterprise SaaS I built
to integrate with Gemini, so that Gemini can edit the content stored in
the SaaS, but not the SaaS itself.
Gemini: To connect your enterprise SaaS so Gemini can
manipulate content without threatening your core application codebase or
infrastructure, you should implement Function Calling via the Gemini
Enterprise Agent Platform (formerly Vertex AI) or the native Gemini
developer API.
With Function Calling, Gemini doesn't execute code inside your application and has no direct access to
your codebase. Instead, it acts as a decision-maker: you provide a strict
blueprint of the content-editing APIs it can use, and Gemini replies with
a request containing the specific content edits to make.
How the Security Boundary Works
Because Gemini lives on Google's servers, it can only interact with your
SaaS through the specific API endpoints you choose to expose.
Safe (Content Editing): You expose a
PATCH /api/v1/documents/{id} or
PUT /api/v1/content endpoint.
Gemini can request changes to text or data fields.
Isolated (SaaS Integrity): You never give Gemini endpoints that
can rewrite your code, alter your deployment configurations, drop
database tables, or access server SSH keys. Gemini literally cannot
touch the SaaS itself because no such API actions are made available to
it.
Architecture: The 4-Step Tool Loop
When a user gives Gemini an instruction (e.g., "Fix the typos in the
project brief stored in the SaaS"), the following cycle occurs:
┌──────┐ 1. User Prompt + Function Schema
┌────────┐
You Define the Blueprint: When you start a session using the
Gemini API or the standard Interactions API, you pass a list of
available tools in a JSON schema.
Gemini Decides, It Does Not Execute: Gemini parses the user's
request, notices that it needs to edit content, and spits back a
structured JSON command (a
functionCall) specifying which tool
to use and what arguments to supply (e.g., document_id: "123", new_text:
"...").
Your SaaS Validates and Executes: Your application receives
Gemini's JSON payload. Your server checks user permissions, sanitises
the inputs, executes the actual database write, and generates a success
confirmation.
Closing the Loop: Your backend returns the execution results
(functionResponse) back to Gemini, which then formats a friendly final
confirmation message for the end user.
Code Example: Exposing Content-Only Tools
When configuring the model using a modern environment like
Google AI Studio or your backend application SDK, you restrict
Gemini's access directly in the tools array.
javascript
import { GoogleGenAI } from '@google/genai'; const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY
}); // 1. Define only content-centric functions. // Do NOT include system management or code modification tools here. const updateSaasContentTool = { functionDeclarations: [{ name: 'updateSaasContent', description: 'Updates the text body or content of a
specific resource inside the SaaS database.', parameters: { type: 'OBJECT', properties: { contentId: { type: 'STRING', description:
'The unique ID of the document or record.' }, updatedText: { type: 'STRING', description:
'The newly edited or corrected text content.' } }, required: ['contentId', 'updatedText'] } }] }; // 2. Pass the content tool into the Gemini model instance const chat = ai.chats.create({ model: 'gemini-2.5-flash', // Or your preferred Gemini model config: { tools: [updateSaasContentTool], systemInstruction: "You are an assistant that edits
customer data records within our SaaS system. You only have access to
modify data fields via the provided tools." } });
Best Practices for Absolute Isolation
Least Privilege API Keys: Ensure the API key or OAuth token your
application uses to execute the function calls only has read/write
permissions for user content data—never admin or infrastructure
roles.
Strict Schema Validation: Always treat Gemini’s JSON output as
untrusted user input. Validate the fields on your server side before
writing to your database.
The Model Context Protocol (MCP): If you want an open-source,
standardised framework for securely exposing your SaaS data tools to
Gemini, consider building an MCP Server. Gemini natively supports
connecting to external data ecosystems via MCP server setups.
Gemini: What language or framework is your SaaS backend built in
(e.g., Node.js,
Python,
Go)? I can provide the exact code
block for handling the functionCall feedback loop on your server.
Mike: The SaaS backend is built in
CFML.
Gemini:Implementing Function Calling in a CFML backend (such as Lucee or Adobe
ColdFusion) requires managing the request and response cycle via standard
HTTP calls, as there isn't a native Google-maintained SDK for CFML.
Because Gemini only sends back JSON instructions, your CFML application
retains absolute control. Gemini decides what to edit, but your CFML
components (.cfc) validate the parameters, check user sessions, and
execute the actual SQL or ORM operations to modify the content
database.
The CFML Integration Workflow
The integration is split into two phases inside your CFML
application:
The Request: Sending the user prompt alongside your defined CFML
tool schema to Gemini.
The Execution: Parse Gemini's response, run your internal
CFML logic, and send the results back to complete the loop.
Phase 1: Sending the Tool Definition to Gemini
You will send a POST request to the
Gemini API
(/v1beta/models/gemini-2.5-flash:generateContent). Include your system boundaries and the explicit content-editing
functions in the tools array.
cfml
<!--- Define the tools Gemini is allowed to use ---> <cfset toolsPayload = [ { "functionDeclarations": [ { "name":
"editSaaSContent", "description":
"Edits the text body of a specific record inside the SaaS database. Use
this when the user asks to modify, format, or fix text content.", "parameters":
{
"type": "OBJECT",
"properties": {
"recordID": { "type": "STRING", "description": "The unique
UUID or ID of the content record." },
"newContent": { "type": "STRING", "description": "The
newly edited text content." }
},
"required": ["recordID", "newContent"] } } ] } ]> <!--- Prepare the request body ---> <cfset requestBody = { "contents": [ { "role": "user", "parts": [{ "text": "Fix
the grammatical errors in document ID 98765" }] } ], "systemInstruction": { "parts": [{ "text": "You are a content
assistant. You can only modify data records using the provided tools.
You cannot touch SaaS infrastructure or codebase." }] }, "tools": toolsPayload }> <!--- Make the API call to Gemini ---> <cfhttp url="https://googleapis.com" method="POST"
result="geminiResponse"> <cfhttpparam type="header" name="Content-Type"
value="application/json"> <cfhttpparam type="body"
value="#serializeJSON(requestBody)#"> </cfhttp>
Phase 2: Processing Gemini’s Decision in CFML
Gemini will not return a text answer. Instead, it will return a
functionCall object. Your CFML code must intercept this, verify it, run your
safe database update, and send the result back to Gemini.
Here is how you handle that response securely:
cfml
<cfif geminiResponse.statusCode CONTAINS "200"> <cfset responseData =
deserializeJSON(geminiResponse.fileContent)> <!--- Check if Gemini wants to call your
content-editing tool ---> <cfif structKeyExists(responseData,
"candidates") AND
arrayLen(responseData.candidates) GT 0 AND
structKeyExists(responseData.candidates[1].content.parts[1],
"functionCall")> <cfset functionCall =
responseData.candidates[1].content.parts[1].functionCall> <!--- Ensure Gemini is calling the
expected tool ---> <cfif functionCall.name EQ
"editSaaSContent"> <cfset args =
functionCall.args> <!--- SECURITY: Safely
validate incoming parameters before touching the database ---> <cfif isValid("guid",
args.recordID) OR isValid("integer", args.recordID)> <!---
Execute your native CFML database update --->
<cftry>
<query execute="UPDATE saas_content_table SET body_text = :newText
WHERE id = :id"
params="{ newText: {value=args.newContent,
cfsqltype='cf_sql_clob'}, id: {value=args.recordID,
cfsqltype='cf_sql_varchar'} }">
<cfset executionStatus = "Success: Content has been updated inside
the SaaS database.">
<cfcatch type="any">
<cfset executionStatus = "Error: Failed to write to
database. #cfcatch.message#">
</cfcatch>
</cftry> <cfelse> <cfset
executionStatus = "Error: Invalid record ID format provided by
AI."> </cfif> <!--- Final Step: Send the
execution result back to Gemini so it can reply to the user ---> <cfset followUpBody = { "contents":
[
<!--- You must include the original conversation history here,
followed by: --->
{
"role": "function",
"parts": [{
"functionResponse": {
"name": "editSaaSContent",
"response": { "output":
executionStatus }
}
}]
} ] }> <!--- Post this back to
Gemini to get the final conversational confirmation message ---> </cfif> </cfif> </cfif>
Keeping the Boundary Enforced in CFML
Session Validation: Do not rely solely on Gemini knowing who the
user is. Before running the
<cfquery> update, verify that
the logged-in user session (session.userID) actually has permission to modify
args.recordID.
Input Sanitisation: Use
cfqueryparam (or query params
inside script syntax as shown above) without exception. This completely
stops Gemini from performing SQL Injection if it goes rogue or gets
manipulated by a malicious user prompt (Prompt Injection).
Isolation of Admin CFCs: Keep this integration code inside a
separate, non-administrative Component (e.g.,
aiService.cfc). Never pass any
methods that handle server maps, application reloads (url.init), or file system manipulation (<cffile>) into the tools definition payload.
Gemini: Are you using a specific CFML framework like
ColdBox, Framework One (FW/1), or a legacy/custom legacy
codebase? I can help tailor the controller architecture or routing
settings to match your current setup.
Mike: Custom legacy CFML codebase running on
Boxlang.
Gemini: Running on BoxLang, you have a massive architectural
advantage. Because BoxLang includes a native, unified ecosystem called
BoxLang AI (bx-ai), you do not need to
mess with raw JSON schemas or manual HTTP requests like traditional CFML
setups require.
BoxLang AI acts as a multi-tenant orchestration layer. It allows you to
wrap your legacy .cfm/.cfc functions
as native AI Tools that Gemini can call.
The Security Sandbox Strategy
To ensure Gemini can edit data fields but cannot touch files, code, or the
application framework, wrap your legacy database modification logic in a
dedicated BoxLang AI tool execution loop.
Expose only raw data components: Only register data-centric
components with the BoxLang AI agent.
Context isolation: BoxLang AI isolates system contexts, so
Gemini sees only the specific functions you register via
bx-ai. It has zero visibility into
the underlying BoxLang JVM runtime, application maps, or file
headers.
Step-by-Step Implementation with BoxLang AI
1. Configure the Gemini Provider
In your configuration file (or programmatically at app startup), specify
Google Gemini as your LLM driver.
2. Create the Legacy CFML Tool Component (ContentEditor.cfc)
Write a clean, isolated component that handles the actual content-editing
task. BoxLang uses metadata annotations to communicate tool definitions to
Gemini.
cfml
component hint="Exposes database editing boundaries to Gemini via
BoxLang AI" { /** * Updates the text body of a specific SaaS
record. * @recordID The unique primary key or UUID of the
content row. * @newText The finalized text generated by Gemini
to inject into the row. */ public string function modifyRecordText( required string
recordID, required string newText ) { // 1. SECURITY CRITICAL: Session/Role
authorization check if ( !structKeyExists( session, "userID" )
) { return "Error: Unauthorized
execution block."; } // 2. Perform safe, isolated SQL write try { queryExecute( "UPDATE
saas_user_content SET body_content = :newText WHERE id = :id AND user_id
= :uid", {
newText: { value=arguments.newText, cfsqltype="cf_sql_clob" },
id: { value=arguments.recordID, cfsqltype="cf_sql_varchar" },
uid: { value=session.userID, cfsqltype="cf_sql_varchar" } } ); return "Success: Database
updated successfully."; } catch ( any e ) { return "Database insertion
failure: " & e.message; } } }
3. Execute via the BoxLang AI Agent
In your controller or execution script, register the ContentEditor.cfc as
an active tool inside the BoxLang AI interface. BoxLang automatically
converts your component methods into the function schemas Gemini
expects.
cfml
// 1. Instantiate the BoxLang AI service manager aiService = new bx.ai.models.AIService( application.aiConfig ); // 2. Create an agent and bind our safe legacy tool component agent = aiService.newAgent( systemInstruction = "You are a content assistant. You
format, correct, and edit user content strings. You have NO permission
to manage software infrastructure or access code files." ); // BoxLang registers the component methods natively as tools Gemini can
read agent.addTool( new path.to.components.ContentEditor() ); // 3. Process incoming prompt userPrompt = "Please clean up the grammar inside item ID:
ABC-12345"; aiResponse = agent.chat( userPrompt ); // BoxLang automatically intercepts Gemini's tool requests, matches it
to your // component method, executes the SQL, and handles the chat loop. writeOutput( aiResponse.getText() );
Why BoxLang Safeguards Your Legacy Codebase
Automatic Reflection Parsing: BoxLang reads the doc comments
(@recordID, @newText) of your legacy
components natively. It writes the precise JSON schemas Gemini needs
without exposing your component's internal SQL or actual source
path.
Prompt Injection Defence: Because you execute database updates using standard BoxLang
queryExecute bindings, any attempt by a user to manipulate Gemini into
writing malicious SQL code is stopped via parameter isolation at the JVM
database driver level.
Process Isolation: The model never touches file interpreters or
runtime evaluations (evaluate()). It
is entirely a "data-in, data-out" loop passing string arguments back into
your custom CFML method.
Gemini: Are you using CommandBox to manage this runtime
environment, or are you utilizing the new BoxLang Spring Boot Starter /
MiniServer configurations? Let me know if you want help mapping
environment secrets or handling cross-origin requests securely.
Mike: Is there a need to create a MCP server in this
situation?
Gemini: No, you do not need to create an MCP (Model Context
Protocol) server for this specific situation.
Since you are running your legacy CFML codebase on BoxLang, you can use
the built-in bx-ai module to handle Gemini’s function calling out of the
box. Creating an independent MCP server would add unnecessary
architectural overhead.
The distinction between the two approaches explains why the native BoxLang
AI method is more effective for your current setup:
1. Traditional Native BoxLang AI
(bx-ai) Approach
In the solution detailed above, you use BoxLang's native AI
orchestration.
How it works: Your SaaS application initiates the API call to
Gemini, provides the component tools directly, intercepts the response,
and runs the local CFML code.
Why it's sufficient: The AI loop is fully contained inside your
existing application runtime. There is no middleman.
2. The MCP (Model Context Protocol) Alternative
The Model Context Protocol (introduced by Anthropic) is designed to solve
the "N×M integration problem"—enabling any AI model to talk to any software platform via a universal,
standardised JSON-RPC protocol without custom API adapters.
If you were to build an MCP server for your SaaS, the architecture would
look like this:
Gemini AI Client ⇄ Your Custom BoxLang MCP Server (JSON-RPC) ⇄ Your SaaS
Database
Head-to-Head Comparison
Feature
Native BoxLang AI (bx-ai)
Building a Custom MCP Server
Architectural Overhead
Very Low. Built directly into your existing
app.
Medium. Requires setting up a persistent HTTP/SSE or
STDIO listener.
Security Handling
Easier. Inherits your user's live session
(session.userID) naturally during the web request.
Harder. You must implement a separate token-auth
protocol so the MCP server knows which tenant's data is being
edited.
When to use it
When you control the app interface and want Gemini
to act as an integrated feature inside your SaaS.
When you want external AI clients (like Claude
Desktop, Cursor, or ChatGPT) to connect directly into your SaaS
database.
The Only Exception: BoxLang's Built-In
bx-mcp
The creators of BoxLang (Ortus Solutions) shipped a native module called
bx-mcp. However, this module is
specifically used to expose BoxLang runtime diagnostics and server
monitoring to AI coding assistants (like Cursor or Claude Desktop) so they
can help you debug your server. It is not meant for business-logic data
editing inside a SaaS platform.
Final Recommendation
Stick to the native BoxLang AI tool registration (agent.addTool()) approach. It keeps your security boundaries tied straight to your
legacy CFML session state, eliminates the need to route traffic through
external protocol translators, and requires significantly less code to
maintain.
Gemini: Is this Gemini integration meant to be a user-facing
feature inside your SaaS dashboard, or is it an internal automation tool
for your development team? Knowing the end-user environment helps
determine the best way to handle user authentication.
Mike:
It will be a user-facing feature inside the SaaS dashboard. Drafting
emails, writing reports, etc.
Gemini: Since this is a user-facing feature inside your SaaS
dashboard, security boundaries shift from protecting infrastructure to
protecting tenant data isolation. You must guarantee that User A cannot
trick Gemini into modifying or reading User B's content (a vulnerability
known as Indirect Prompt Injection).
Using the native BoxLang AI Agent framework, your legacy CFML codebase
can safely contain this interaction within the user's active
session.
The 3-Tier Security Architecture
Because Gemini operates statelessly, it doesn't know who is logged into
your application. Your CFML controller acts as the gatekeeper by wrapping
the execution cycle:
[ User Dashboard ]
│ 1. Submits Prompt
▼
[ BoxLang Controller ] ──( 2. Restricts Tool to Session User ID )──► [
Gemini API ]
│
│
│ 4. Executes SQL restricted by User ID
│ 3. Returns Function Call
▼
▼
[ SaaS Content DB ]
◄──────────────────────────────────────────────────────┘
Production-Ready BoxLang Implementation
Here is how you handle the user's dashboard request safely. This ensures
Gemini can draft emails and write reports only within the strict scope of
that specific logged-in user.
1. The Secure Legacy Component (ContentManager.cfc)
To lock Gemini down, the component's internal SQL must strictly filter on
the user's session identifier.
cfml
component hint="Handles user-facing AI content operations securely."
{ /** * Creates a brand new document draft (like an email
or report) for the logged-in user. * @title The descriptive title of the document,
email, or report. * @body The AI-generated text body content. */ public struct function createDraftDocument( required
string title, required string body ) { // 1. HARD SECURITY WALL: Verify user is
actively authenticated if ( !structKeyExists( session, "userID" )
|| !len( session.userID ) ) { return { "success": false,
"message": "Authentication required." }; } try { // 2. TENANT ISOLATION: The
session.userID is hardcoded into the write operation var newID = createUUID(); queryExecute( "INSERT INTO
saas_documents (id, user_id, title, body_content, status,
created_at) VALUES
(:id, :uid, :title, :body, 'draft', NOW())", {
id: { value=newID, cfsqltype="cf_sql_varchar" },
uid: { value=session.userID, cfsqltype="cf_sql_varchar"
},
title: { value=arguments.title, cfsqltype="cf_sql_varchar" },
body: { value=arguments.body, cfsqltype="cf_sql_clob" } } ); return { "success":
true, "message":
"Draft securely created.", "documentID":
newID }; } catch ( any e ) { return { "success": false,
"message": "Failed to save draft system-side." }; } } }
2. The Dashboard Endpoint (/api/generate.cfm)
When the user clicks "Draft Email" or "Write Report" on the UI, your
legacy backend endpoint intercepts the action, provisions the BoxLang AI
agent, and executes the sequence.
cfml
<cfsetting showdebugoutput="false"> <cfcontent type="application/json"> <!--- Basic session protection checklist ---> <cfif !structKeyExists( session, "userID" )> <cfset writeOutput( serializeJSON({ "error":
"Unauthorized session context." }) )> <cfabort> </cfif> <!--- Read incoming AJAX request payload from dashboard front-end
---> <cfset requestBody = toString(
getPageContext().getRequest().getInputStream() )> <cfset payload = isJSON( requestBody ) ? deserializeJSON(
requestBody ) : {}> <cfset userPrompt = structKeyExists( payload, "prompt" ) ?
payload.prompt : ""> <cfif !len( trim( userPrompt ) )> <cfset writeOutput( serializeJSON({ "error": "Prompt
cannot be empty." }) )> <cfabort> </cfif> <!--- Orchestrate the BoxLang AI Agent ---> <cfscript> // Initialize BoxLang AI configuration aiConfig = { "provider": "google", "model": "gemini-2.5-flash", "apiKey":
server.system.environment.GEMINI_API_KEY }; aiService = new bx.ai.models.AIService( aiConfig ); // Inject persona boundaries preventing infrastructure
manipulation agent = aiService.newAgent( systemInstruction = "You are an embedded
text generation feature inside our SaaS dashboard. Your role is strictly
to draft emails, generate reports, or format user notes. Use the
provided creation tool when the text is ready." ); // Register our secure, session-aware component contentTool = new path.to.components.ContentManager(); agent.addTool( contentTool ); try { // Execute the processing loop // BoxLang handles: Prompt -> Gemini
-> Tool Call execution -> Final message aiResponse = agent.chat( userPrompt ); // Return clear status back to your
Javascript dashboard UI writeOutput( serializeJSON({ "status": "success", "message":
aiResponse.getText() })); } catch ( any e ) { writeOutput( serializeJSON({ "status": "error", "message": "An error occurred
processing the AI generation request." })); } </cfscript>
Core Rules for User-Facing UI Security
Never Pass Document IDs blindly from Gemini: If you allow Gemini
to edit existing reports, always add a server-side cross-check inside
your CFC method to ensure that the document's user_id matches the
current session.userID before
running an UPDATE query.
Sanitise Output Rendering: When displaying Gemini's output
inside your web application's email template editor or dashboard UI,
ensure your frontend escapes the returned string or uses text-only
content inputs. This blocks potential
HTML/XSS injection vulnerabilities
if Gemini accidentally reads a malicious script from external text
input.
Keep the UI Asynchronous: Generating comprehensive reports can
take a few seconds. Ensure your dashboard interface triggers a loading
spinner or streaming layout while waiting for this endpoint to
reply.
Gemini: How do you intend to present the output to your users? Will they see
the final report saved quietly in the background to their file list, or
should Gemini stream the text dynamically onto their screen inside a
text editor layout?
Mike: Both options are required.
Gemini: To support both workflows seamlessly, structure your
BoxLang backend to handle them dynamically.
When streaming content directly into a UI editor, you want Gemini to
respond with raw text as fast as possible. When saving files silently in
the background, you want Gemini to process the text and automatically
invoke your secure ContentManager.cfc tool to write to the database.
Here is how you can implement both approaches within your legacy BoxLang
infrastructure.
Architecture Strategy
You can use a simple URL parameter or request payload field (e.g.,
mode=stream or
mode=background) to route the
request:
Stream Mode: Bypasses BoxLang's automated tool system entirely.
It hooks into BoxLang AI's underlying streaming mechanism to push
real-time text chunks straight to the client browser via Server-Sent
Events (SSE) or a flushing response buffer.
Background Mode: Utilises the Function Calling setup we built
previously. It tells the agent to orchestrate the generation, save it
quietly via your secure ContentManager.cfc, and return a simple
"Success" payload.
The Dual-Mode Endpoint (/api/generate.cfm)
This unified legacy endpoint routes incoming dashboard requests based on
the user's intent.
cfml
<cfsetting showdebugoutput="false"> <!--- Session and validation guardrails ---> <cfif !structKeyExists( session, "userID" )> <cfcontent type="application/json"> <cfset writeOutput( serializeJSON({ "error":
"Unauthorized" }) )> <cfabort> </cfif> <cfparam name="url.mode" default="background"> <!--- Options:
'stream' or 'background' ---> <cfset userPrompt = form.prompt ?: ""> <cfscript> // Initialize standard BoxLang AI Configuration aiConfig = { "provider": "google", "model": "gemini-2.5-flash", "apiKey":
server.system.environment.GEMINI_API_KEY }; aiService = new bx.ai.models.AIService( aiConfig ); //
---------------------------------------------------- // OPTION 1: STREAM MODE (Direct to Text Editor UI) //
---------------------------------------------------- if ( url.mode EQ "stream" ) { // Change content type to allow dynamic
browser streaming cfcontent( type="text/event-stream" ); agent = aiService.newAgent( systemInstruction = "You are
an AI text editor assistant. Generate the requested text directly. Do
NOT attempt to run tools or database commands." ); // Request a stream from BoxLang AI // BoxLang stream chunks are iterated
natively agent.chatStream( userPrompt, function(
chunk ) { // Write each text fragment
directly to the dashboard UI writeOutput( "data: " &
chunk.getText() & "#chr(10)##chr(10)#" ); cfflush(); // Force the
server buffer to send the text chunk immediately }); cfabort(); } //
---------------------------------------------------- // OPTION 2: BACKGROUND MODE (Save Silently to DB) //
---------------------------------------------------- if ( url.mode EQ "background" ) { cfcontent( type="application/json" ); agent = aiService.newAgent( systemInstruction = "You are
a background generator. Take the prompt, create the required content,
and immediately use the createDraftDocument tool to save it." ); // Bind the secure tool component we
created earlier contentTool = new
path.to.components.ContentManager(); agent.addTool( contentTool ); try { // Gemini creates content,
triggers tool, BoxLang updates database aiResponse = agent.chat(
userPrompt ); writeOutput(
serializeJSON({ "status":
"success", "message":
"Your request has been generated and filed to your dashboard document
list." })); } catch ( any e ) { writeOutput( serializeJSON({
"status": "error", "message": "Failed background execution loop."
})); } cfabort(); } </cfscript>
Frontend JavaScript Connections
Handling Option 1 (Streaming into a UI Rich Text Editor)
To consume the streaming API on your client dashboard web page, use
JavaScript's EventSource api or a standard fetch body reader:
javascript
async function startStreamingEditor(promptText) { const editorElement =
document.getElementById('my-rich-text-editor'); editorElement.innerHTML = "Generating draft..."; const response = await
fetch('/api/generate.cfm?mode=stream', { method: 'POST', headers: { 'Content-Type':
'application/x-www-form-urlencoded' }, body: new URLSearchParams({ prompt:
promptText }) }); const reader = response.body.getReader(); const decoder = new TextDecoder(); editorElement.innerHTML = ""; // Clear loader while (true) { const { value, done } = await
reader.read(); if (done) break; let chunk = decoder.decode(value); // Clean out SSE data prefix formatting if
necessary let processedText =
chunk.replace(/^data:\s*/gm, ''); // Append raw content directly onto the
editor screen in real-time
editorElement.append(processedText); } }
Handling Option 2 (Background Generation Banner)
For background workflows, a standard asynchronous fetch request alerts
the user when the document safely lands in their dashboard
portfolio.
javascript
function generateBackgroundReport(promptText) { showGlobalToast("Generating your report in the
background..."); fetch('/api/generate.cfm?mode=background', { method: 'POST', headers: { 'Content-Type':
'application/x-www-form-urlencoded' }, body: new URLSearchParams({ prompt:
promptText }) }) .then(res => res.json()) .then(data => { if(data.status === "success") { showGlobalToast("Finished!
Your document is ready in your list."); refreshDocumentTableGrid();
// Reloads legacy dashboard table data } }); }
The industry standard for embedding Gemini into a custom web UI is a
Hybrid API + Frontend Component architecture. Your BoxLang backend acts as
the secure proxy to the Gemini API, and your frontend uses JavaScript to
render a tailored, styled chat or text interface.
Recommended Frontend Integration Paths
Depending on how integrated you want the feature to feel, you have three
primary architectural choices:
1. Pre-built Custom Web Components (Easiest & Cleanest)
Instead of building a text box and message bubbles from scratch, you can
use open-source, framework-agnostic UI component libraries designed
exactly for this.
The Tools: Use libraries like Vercel AI SDK UI components or
Deep Chat Core.
How it works: You drop a custom HTML tag (e.g.,
<deep-chat>) into your legacy
.cfm dashboard page. You point its url property to your
/api/generate.cfm endpoint. The
component handles layout, streaming chunks, loading skeletons, and
markdown formatting natively.
html
<!-- Example using an open-source web component in a standard .cfm
page --> <script type="module" src="https://unpkg.com"></script> <div class="dashboard-panel"> <h3>SaaS AI Copywriter</h3> <!-- The component automatically handles user input
and streams your BoxLang response --> <deep-chat request='{"url":
"/api/generate.cfm?mode=stream", "method": "POST"}' stream="true" initialMessages='[{"text": "Hi! Let me help
you draft your next email or report.", "role": "ai"}]' style='{"borderRadius": "8px", "border":
"1px solid #ccc", "height": "500px"}'> </deep-chat> </div>
2. Native Dynamic Text Injection (For In-Line Editors)
If your goal is to let users click a button (e.g., "Write a summary of
this report"), you shouldn't use a chat window at all. Use inline
JavaScript to inject text directly into your existing editor layout.
The Tools: Standard JavaScript fetch() API combined with your
existing text editors (like TinyMCE, CKEditor, or Quill).
How it works: When the user clicks the "AI Assist" button, your
JavaScript calls your BoxLang stream endpoint and updates the text
editor's content block-by-block using the Reader API shown in the
previous response. This creates a seamless "AI is writing inside my
document" effect.
3. Custom Chat Assistant Widget (For Floating Help Panels)
If you want an expandable, floating AI helper in the bottom corner of
your SaaS dashboard, you can build a small HTML/CSS chat container.
How it works: You manage a message array in JavaScript. When the
user types a prompt and hits send, your code appends a user-message
bubble to the DOM, fires the AJAX request to BoxLang, and streams the
response directly into a newly appended ai-message bubble.
Why This Architecture Keeps Your SaaS Secure
By routing everything through your BoxLang backend and rendering natively
on the client side:
API Key Masking: Your Google Gemini API key stays safe on your
server inside BoxLang (server.system.environment.GEMINI_API_KEY). It never appears in the browser's developer inspector.
Seamless Styling: The AI feature matches your SaaS design
system, fonts, and colours perfectly.
State Control: You maintain full control over the data loop, so
you can save copies of the generated text to your database before it
even touches the user's screen.
Gemini:Which style fits your vision best? A floating conversational chat
assistant, a standalone copywriting page, or contextual buttons embedded
right inside your text input fields? I can give you the exact HTML/CSS
boilerplates to start wiring it up.
... to be continued ... 😎😎😎😎
Live from AGNTCon + MCPCon NA, OpenAI, Anthropic, DeepMind, Entire, Block
& More
Join the Agentic AI Foundation live on YouTube for AGNTCon + MCPCon North
America on October 22, 2026, from 9:00 AM to 6:00 PM California time (PDT /
UTC−7).
Tune in from anywhere for a day focused on the ideas, people, and open
technologies shaping agentic AI and the Model Context Protocol. Drop in for
a keynote or stay with us for the full broadcast.
What to expect
3,500+ attendees from across the agentic AI ecosystem
1,000+ organizations represented
150+ talks across 11 tracks
7 hands-on workshops at no added cost for in-person attendees