ZaronAI Developer Guide

Adding Images to a Model

Version 1.0Published 2026-04-10 eZaron LLC — ed@zaronai.com
Contents
  1. Overview — How Image Display Works
  2. Step 1 — Update the Knowledge Base Tool Data
  3. Step 2 — Update Agent System Prompts
  4. The [[ZAI:IMAGE]] Sentinel Reference
  5. End-to-End Flow
  6. Implementation Checklist
01

Overview — How Image Display Works

The ZaronAI runtime renders images inline in chat using a sentinel system. A sentinel is a structured token the AI emits in plain text. The runtime detects it, resolves it, and renders the appropriate HTML. The AI never emits raw HTML.

The image sentinel used in V1 is:

[[ZAI:IMAGE|url=https://yoursite.com/img/pool.jpg|width=320]]

To enable image display in a model, three things must be in place:

Why sentinels instead of markdown or raw HTML?
Markdown image syntax (![alt](url)) is fragile — models occasionally mangle spacing or punctuation. Raw HTML in model output is a security risk. The [[ZAI:]] double-bracket prefix is rare in natural language, log output, and code, making parser collisions essentially impossible. The model emits intent; the runtime owns rendering.
02

Step 1 — Update the Knowledge Base Tool Data

Each KB record that represents a visual product needs two new flat fields added at the top level alongside id, title, and content.

Fields to add

FieldTypeDescription
imageUrlstringFully qualified https:// URL to the product image. Must be accessible from the browser serving the chat widget.
imageWidthstring (digits)Display width in pixels as a string, e.g. "320". Controls max-width in the rendered <img> tag. Omit or leave empty to use the runtime default of 320px.
Important: Both fields must be flat siblings of id and title. Do not nest them inside content. The AI reads the tool result as a JSON object and must be able to reference imageUrl and imageWidth directly by key name.

Before — KB record without image fields

Before
{ "id": "KB-POOL-001", "name": "Laguna Breeze", "title": "Laguna Breeze Fiberglass Pool", "category": "Sales", "keywords": [ "laguna breeze", "fiberglass pool", "medium pool" ], "content": "The Laguna Breeze is a mid-size fiberglass swimming pool designed for families. It features integrated entry steps, a flat lounging area, and a smooth gel-coat finish. Typical installation time is 7 to 10 days once excavation begins.", "recordActive": true, "updatedUTC": "2025-01-10T14:00:00Z" }

After — KB record with image fields added

After
{ "id": "KB-POOL-001", "name": "Laguna Breeze", "title": "Laguna Breeze Fiberglass Pool", "category": "Sales", "keywords": [ "laguna breeze", "fiberglass pool", "medium pool" ], "content": "The Laguna Breeze is a mid-size fiberglass swimming pool designed for families. It features integrated entry steps, a flat lounging area, and a smooth gel-coat finish. Typical installation time is 7 to 10 days once excavation begins.", "imageUrl": "https://yoursite.com/img/laguna-breeze.jpg", "imageWidth": "320", "recordActive": true, "updatedUTC": "2025-01-10T14:00:00Z" }

Repeat for every KB record that has a product image. Records without imageUrl are unaffected — the Sales agent only emits the sentinel when imageUrl is present and non-empty.

03

Step 2 — Update Agent System Prompts

Three agents in the pipeline need prompt additions. Two are simple one-paragraph preservation rules. Only the Sales agent requires a substantive instruction block.

AgentChange requiredReason
SalesAdd sentinel emission instruction blockSales is the only agent that presents product data from the KB tool. It must be told when and how to emit the image sentinel.
ReviewerAdd sentinel preservation ruleThe Reviewer rewrites messageToUser. Without an explicit instruction it may strip or corrupt the [[ZAI:]] token, treating it as unusual text.
FinalizerAdd sentinel preservation ruleThe Finalizer polishes reply_to_user from Reviewer output. Same risk as the Reviewer — the token must be declared opaque.
RouterNo changeRouter never touches product content or output text.
ServiceNo changeService handles repairs and diagnostics, not product presentation. It does not call the KB product tool.

Sales — Sentinel Emission Block

Where to insert: Immediately before the “Behavior and language:” section of the Sales agent system prompt.

Why the Sales agent only: Sales is the sole agent that calls search_knowledge_base and presents product records to the user. Other agents receive and forward the already-composed messageToUser — they do not generate product descriptions themselves.

Why include a worked example: Giving the model a concrete example of the exact sentinel syntax significantly improves emission reliability. The model anchors to the example pattern rather than inferring the format from the description alone.

Why the conditional on imageUrl: Some KB records may not have images. The conditional prevents the agent from emitting a broken sentinel with an empty URL.

Before — nothing here, section opened directly
Behavior and language: 4. If the user asks for a callback but identity_ok is false: ...
After — insert the green block immediately before that section
ZAI SENTINEL - DISPLAYING PRODUCT IMAGES: When presenting a product or model from a search_knowledge_base result that includes imageUrl and imageWidth fields, emit the image sentinel on its own line immediately after naming the product: [[ZAI:IMAGE|url=URL|width=WIDTH]] where URL is the exact imageUrl value and WIDTH is the exact imageWidth value from the tool result. Rules: - Only emit this sentinel when imageUrl is present and non-empty. - Emit it on its own line, with a blank line before and after. - Do not emit HTML. Do not modify the URL or width value. - Only use the [[ZAI:IMAGE]] sentinel type. Do not invent others. - If imageWidth is missing or empty, omit the |width=WIDTH arg and the runtime will use the default width. Example (Laguna Breeze pool, imageWidth=320): Here is the Laguna Breeze, a popular mid-size family pool: [[ZAI:IMAGE|url=https://yoursite.com/img/laguna-breeze.jpg|width=320]] At 14 feet wide with integrated entry steps... Behavior and language: 4. If the user asks for a callback but identity_ok is false: ...

Reviewer — Sentinel Preservation Rule

Where to insert: Immediately before the “3. Output:” section of the Reviewer prompt.

Why this is necessary: The Reviewer inspects and potentially rewrites messageToUser. Without this instruction the model may paraphrase around the sentinel, relocate it, or silently drop it during a rewrite. The preservation rule makes the token explicitly opaque — the Reviewer must treat it as pass-through, not content.

Before — nothing here, section opened directly
3. Output: - messageToUser: The final (or corrected) message that goes to the user. ...
After — insert the green block immediately before that section
ZAI SENTINEL PRESERVATION: If messageToUser contains [[ZAI:...]] sentinel tags, you MUST preserve them exactly as-is in your output. Do not remove, rewrite, move, or modify sentinel tags in any way. They are UI rendering tokens consumed by the runtime after you - not display text. Treat them as opaque pass-through tokens. 3. Output: - messageToUser: The final (or corrected) message that goes to the user. ...

Finalizer — Sentinel Preservation Rule

Where to insert: Immediately before the “4. Consistency:” section of the Finalizer prompt.

Why this is necessary: The Finalizer produces reply_to_user by polishing the Reviewer output. It is the last agent before the response reaches the user — if it drops or corrupts the sentinel here there is no recovery path. The rule is identical in intent to the Reviewer's but scoped to reply_to_user.

Before — nothing here, section opened directly
4. Consistency: - NEVER set ticket_should_create = true when Reviewer review_ok = false. ...
After — insert the green block immediately before that section
ZAI SENTINEL PRESERVATION: If the Reviewer messageToUser contains [[ZAI:...]] sentinel tags, you MUST preserve them exactly as-is in reply_to_user. Do not remove, rewrite, move, or modify sentinel tags in any way. They are UI rendering tokens consumed by the runtime - not display text. Treat them as opaque pass-through tokens. 4. Consistency: - NEVER set ticket_should_create = true when Reviewer review_ok = false. ...
04

The [[ZAI:IMAGE]] Sentinel Reference

Syntax

[[ZAI:IMAGE|url=URL|width=WIDTH]]   <-- preferred: model-controlled width
[[ZAI:IMAGE|url=URL]]              <-- fallback: runtime defaults to 320px

Parsing rules

Rendered HTML output

<!-- [[ZAI:IMAGE|url=URL|width=320]] renders as: -->
<img src="URL"
     style="max-width:320px;width:100%;display:block;
            margin:6px 0;border-radius:4px;" />

Image sizing

Future sentinel types (V1 roadmap, not yet implemented)

[[ZAI:POOL_CARD|id=KB-POOL-001]]                            <-- full product card
[[ZAI:POOL_COMPARE|name1=Laguna Breeze|name2=Monte Carlo]]  <-- side-by-side
[[ZAI:POOL_LIST|names=Laguna Breeze~Monte Carlo]]           <-- multi-card row
[[ZAI:KB_LINK|id=KB-POOL-001]]                              <-- expandable link
05

End-to-End Flow

KB record has imageUrl + imageWidth fields
User asks about a pool model
Router → Sales agent
Sales calls search_knowledge_base tool
Tool returns full KB record including imageUrl + imageWidth
Sales emits [[ZAI:IMAGE|url=...|width=320]] in messageToUser
Reviewer validates response -- preserves sentinel unchanged
Finalizer produces reply_to_user -- preserves sentinel unchanged
cAI.vb returns reply_to_user as response.text
RenderAiOutput() detects [[ZAI: prefix → runs regex patterns
<img src="..." style="max-width:320px;..." /> rendered inline in chat
Legacy model safety: Models that never emit [[ZAI:]] tokens pass through RenderAiOutput() completely unchanged. The function checks for the [[ZAI: prefix before doing any work — normal responses take the fast path with zero regex overhead.
06

Implementation Checklist

  1. Add imageUrl to each KB record that has a product image. Value must be a fully qualified https:// URL accessible from the browser.
  2. Add imageWidth to each KB record. Recommended starting value: "320". Adjust per product to control display size without touching code.
  3. Update the Sales agent system prompt. Insert the ZAI SENTINEL - DISPLAYING PRODUCT IMAGES block immediately before the Behavior section. Update the example URL and product name to match your vertical.
  4. Update the Reviewer agent system prompt. Insert the ZAI SENTINEL PRESERVATION block immediately before the Output section.
  5. Update the Finalizer agent system prompt. Insert the ZAI SENTINEL PRESERVATION block immediately before the Consistency section.
  6. Confirm the runtime is on Example_aspx.vb v2.3+ (or that cAiFormat.RenderAiOutput() contains the [[ZAI:IMAGE]] regex patterns). Earlier versions used the deprecated [img:url] syntax.
  7. Test with a product query. Ask the chat widget about a product that has imageUrl populated. Confirm the image renders inline at the expected size. Then test a product without imageUrl — confirm clean text with no broken sentinel visible.
  8. Verify past conversation replay. Open a prior conversation via the fillPastConversation path. Images in stored aiExchanges records should render correctly on replay since RenderAiOutput() is applied on that path as well.