@clawhub-itsmebasil-7b2a562132
Automates jewellery product marketing using Google Vertex AI (Gemini and Imagen) and Google Drive.
---
name: Pattern Jewellery Automation
description: Automates jewellery product marketing using Google Vertex AI (Gemini and Imagen) and Google Drive.
---
# Pattern Jewellery Automation Skill
## Overview
This skill automates the creation of high-end marketing content for Pattern Jewellery products. It orchestrates a sophisticated multi-agent pipeline: securely ingesting raw product photos, generating lifestyle and studio images via Imagen 3, writing SEO-optimized copy via Gemini 1.5 Pro, and systematically organizing the final assets in Google Drive.
---
## 📥 Input Schema
The skill expects a trigger payload with the following fields:
- `product_image` (String): URL or base64 string of the raw product photograph.
- `product_details` (Object):
- `name`: Product title (e.g. "Diamond Blue Sapphire Ring")
- `sku`: Unique identifier (e.g. "R4389")
- `category`: Organization category (e.g. "rings")
- `material`: Composition (e.g. "18K white gold, 0.32ct diamond")
- `price_now`: Current retail price (e.g. 4455)
- `description`: Core design breakdown.
## 📤 Output Schema
- `model_image_url`: Link to the generated lifestyle model image.
- `product_image_url`: Link to the generated product-only image.
- `caption`: Formatted Instagram caption highlighting the luxury aesthetic.
- `hashtags`: Array of 20 optimized tags.
- `drive_link`: Public/Internal Google Drive folder URL hosting all generated assets.
---
## ⚙️ Workflow Execution Steps
### 1. Vision & Prompt Generation (Gemini 1.5 Pro)
The system visually analyzes the `product_image` alongside the `product_details` to determine design intricacy, materials, and aesthetic quality. It then outputs two strictly constrained prompts:
* **Model Prompt (Max 120 Tokens):** A lifestyle photograph prompt targeting the Gulf luxury market. It details an elegant model wearing the piece in an upscale interior (e.g., modern Dubai), with specific studio lighting and bokeh settings.
* **Product Prompt (Max 120 Tokens):** A premium product-only photography prompt placing the piece on luxury backgrounds (e.g., white Carrara marble, deep navy velvet) equipped with three-point studio lighting and macro lens specs.
### 2. Parallel Image Generation (Imagen 3)
Using Google Vertex AI, this step dispatches parallel requests:
* Generates the `model_image` (1 sample, ultra quality, 4:5 aspect ratio, adult generation allowed).
* Generates the `product_image` (1 sample, ultra quality, 1:1 aspect ratio, tack-sharp).
### 3. Parallel Content Generation (Gemini 1.5 Pro)
Concurrently with the image rendering, the LLM drafts an engaging Instagram caption matching Pattern Jewellery's aspirational and traditional-modern fusion tone. It seamlessly integrates the price point and structural details, returning the copy alongside a 20-tag hashtag package.
### 4. Storage & Compilation (Google Drive)
All final image bytes (`.jpg`) and text output (`.txt`) are piped into the Google Drive API. They are systematically uploaded into a structured directory constraint: `/Pattern_Jewellery/{category}/{sku}/`.
---
## 🧠 Memory Rules & State Management
This skill utilizes a persistent, 4-field memory map to iteratively improve generation over time based on user feedback. The core keys are:
- `style`: Default is "editorial"
- `tone`: Default is "aspirational-luxury"
- `background_preference`: Default is "white-marble"
- `top_performing_caption`: Cached high-performing copy for tone-matching.
*These variables dynamically inject into the prompt generation templates (Step 1).*
## ⚡ Caching Protocol
To minimize unnecessary GPU execution costs:
1. Incoming images are hashed (SHA-256 or pHash).
2. Lookups occur against a Redis/Local cache mapping.
3. If the exact same image and metadata payload are received within the TTL window (30 days), the pipeline bypasses Gemini/Imagen entirely and immediately returns the cached Google Drive URL.
## 📂 Bundled Files
- `jewellery_openclaw_skill.json`: The core JSON pipeline graph mapped to OpenCLAW UI.
- `jewellery_openclaw_skill.py`: Background FastAPI worker capable of executing the pipeline outside of OpenCLAW.
- `pattern_jewellery_openclaw_system.html`: Front-end architectural diagram and design blueprint.
FILE:jewellery_openclaw_skill.py
import os
import io
import asyncio
import hashlib
from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel
from tenacity import retry, stop_after_attempt, wait_exponential
import httpx
# AI and Cloud providers
from anthropic import AsyncAnthropic
import vertexai
from vertexai.preview.vision_models import ImageGenerationModel
from googleapiclient.discovery import build
from google.oauth2 import service_account
from googleapiclient.http import MediaIoBaseUpload
import redis.asyncio as redis
app = FastAPI(title="Jewellery Content Engine (OpenCLAW Skill)")
# -------------------------------------------------------------------
# Configuration & Initialization
# -------------------------------------------------------------------
# Environment variables expected:
# ANTHROPIC_API_KEY
# GOOGLE_APPLICATION_CREDENTIALS (path to service account json)
# REDIS_URL (e.g. redis://localhost:6379)
# GCP_PROJECT_ID
# GCP_LOCATION (e.g., us-central1)
aclient = AsyncAnthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
try:
vertexai.init(
project=os.getenv("GCP_PROJECT_ID"),
location=os.getenv("GCP_LOCATION", "us-central1")
)
except Exception as e:
print(f"Vertex AI Init Warning: {e}")
try:
redis_client = redis.from_url(os.getenv("REDIS_URL", "redis://localhost:6379"), decode_responses=True)
except Exception as e:
print(f"Redis Init Warning: {e}")
try:
creds = service_account.Credentials.from_service_account_file(
os.getenv("GOOGLE_APPLICATION_CREDENTIALS", "gcp-service-account.json"),
scopes=['https://www.googleapis.com/auth/drive.file']
)
drive_service = build('drive', 'v3', credentials=creds)
except Exception as e:
print(f"Drive Init Warning: {e}")
# -------------------------------------------------------------------
# Data Models
# -------------------------------------------------------------------
class WebhookPayload(BaseModel):
image_url: str
product_name: str
metadata: Optional[Dict[str, Any]] = {}
# -------------------------------------------------------------------
# Core Functions
# -------------------------------------------------------------------
async def download_image(url: str) -> bytes:
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
return response.content
def get_image_hash(image_bytes: bytes) -> str:
return hashlib.sha256(image_bytes).hexdigest()
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
async def generate_prompts(image_url: str, metadata: dict) -> dict:
prompt = f"Analyze this jewellery piece context: {metadata}. Provide ONLY a JSON with two keys: 'model_prompt' (describing an AI model wearing it naturally) and 'product_prompt' (studio lighting for the product alone)."
response = await aclient.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=500,
system="You are an expert jewellery art director.",
messages=[{
"role": "user",
"content": [
{"type": "image", "source": {"type": "url", "url": image_url}},
{"type": "text", "text": prompt}
]
}]
)
# Simplified JSON extraction
import json
return json.loads(response.content[0].text)
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
async def generate_content(product_name: str, metadata: dict) -> str:
prompt = f"Write a catchy Instagram caption and a short SEO product description for {product_name}. Details: {metadata}"
response = await aclient.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=600,
system="You are a luxury jewellery copywriter.",
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=2, min=4, max=15))
async def generate_imagen_asset(prompt: str) -> bytes:
loop = asyncio.get_event_loop()
model = ImageGenerationModel.from_pretrained("imagen-3.0-generate-001")
def _gen():
return model.generate_images(
prompt=prompt,
number_of_images=1,
aspect_ratio="1:1",
person_generation="ALLOW_ADULT"
)
response = await loop.run_in_executor(None, _gen)
return response.images[0]._image_bytes
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def upload_to_drive(file_bytes_or_text, file_name: str, folder_id: str, mime_type: str):
if isinstance(file_bytes_or_text, str):
file_bytes_or_text = file_bytes_or_text.encode('utf-8')
file_stream = io.BytesIO(file_bytes_or_text)
media = MediaIoBaseUpload(file_stream, mimetype=mime_type, resumable=True)
file_metadata = {'name': file_name, 'parents': [folder_id]}
file = drive_service.files().create(body=file_metadata, media_body=media, fields='id, webViewLink').execute()
return file.get('webViewLink')
def create_drive_folder(folder_name: str, parent_id: str = None) -> str:
file_metadata = {
'name': folder_name,
'mimeType': 'application/vnd.google-apps.folder'
}
if parent_id:
file_metadata['parents'] = [parent_id]
file = drive_service.files().create(body=file_metadata, fields='id').execute()
return file.get('id')
# -------------------------------------------------------------------
# Pipeline Execution Definition
# -------------------------------------------------------------------
async def run_pipeline(payload: WebhookPayload, folder_id_root: str):
try:
# Step 1: Input & Hash Check
image_bytes = await download_image(payload.image_url)
img_hash = get_image_hash(image_bytes)
cahed_result = await redis_client.get(f"jewellery_pipeline:{img_hash}")
if cahed_result:
return {"status": "success", "cached": True, "links": cahed_result}
# Step 2: Prompt Generation
prompts = await generate_prompts(payload.image_url, payload.metadata)
# Step 3: Parallel Generation
model_img_task = asyncio.create_task(generate_imagen_asset(prompts['model_prompt']))
prod_img_task = asyncio.create_task(generate_imagen_asset(prompts['product_prompt']))
content_task = asyncio.create_task(generate_content(payload.product_name, payload.metadata))
model_img_bytes, prod_img_bytes, text_content = await asyncio.gather(
model_img_task, prod_img_task, content_task
)
# Step 4: Storage
loop = asyncio.get_event_loop()
folder_id = await loop.run_in_executor(None, create_drive_folder, payload.product_name, folder_id_root)
links = {}
links['model'] = await loop.run_in_executor(None, upload_to_drive, model_img_bytes, "model_image.jpg", folder_id, "image/jpeg")
links['product'] = await loop.run_in_executor(None, upload_to_drive, prod_img_bytes, "product_image.jpg", folder_id, "image/jpeg")
links['content'] = await loop.run_in_executor(None, upload_to_drive, text_content, "content.txt", folder_id, "text/plain")
# Step 5: Save to Cache
import json
await redis_client.setex(f"jewellery_pipeline:{img_hash}", 2592000, json.dumps(links))
return {"status": "success", "links": links}
except Exception as e:
return {"status": "error", "message": str(e)}
# -------------------------------------------------------------------
# OpenCLAW Webhook Trigger
# -------------------------------------------------------------------
@app.post("/api/v1/jewellery/process")
async def process_jewellery_content(payload: WebhookPayload):
# This acts as the synchronous webhook return, processing in background if needed
# Wait for completion to return real results for integration ease.
import os
parent_folder = os.getenv("DRIVE_FOLDER_ID", "root")
result = await run_pipeline(payload, parent_folder)
if result["status"] == "error":
raise HTTPException(status_code=500, detail=result["message"])
return result
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
FILE:pattern_jewellery_openclaw_system.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pattern Jewellery — OpenClaw Skill System</title>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&family=DM+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<style>
:root {
--gold: #b8963e;
--gold-light: #d4b06a;
--gold-pale: #f5ecd7;
--navy: #0e1628;
--navy-mid: #1a2540;
--slate: #2c3a55;
--ink: #111827;
--mist: #f8f6f2;
--border: rgba(184,150,62,0.25);
--tag-bg: rgba(184,150,62,0.1);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'DM Mono', monospace;
background: var(--navy);
color: #e8e0d4;
min-height: 100vh;
line-height: 1.6;
}
/* ── HEADER ── */
header {
background: linear-gradient(135deg, var(--navy) 0%, var(--navy-mid) 60%, #1c2e50 100%);
border-bottom: 1px solid var(--border);
padding: 3rem 4rem 2.5rem;
position: relative;
overflow: hidden;
}
header::before {
content: '';
position: absolute;
top: -60px; right: -60px;
width: 280px; height: 280px;
border-radius: 50%;
border: 1px solid rgba(184,150,62,0.12);
}
header::after {
content: '';
position: absolute;
top: -30px; right: -30px;
width: 180px; height: 180px;
border-radius: 50%;
border: 1px solid rgba(184,150,62,0.08);
}
.header-eyebrow {
font-family: 'DM Mono', monospace;
font-size: 0.65rem;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--gold);
margin-bottom: 0.75rem;
}
header h1 {
font-family: 'Cormorant Garamond', serif;
font-weight: 300;
font-size: 2.6rem;
letter-spacing: 0.02em;
color: #fff;
line-height: 1.1;
margin-bottom: 0.5rem;
}
header h1 span { color: var(--gold); font-style: italic; }
.header-sub {
font-size: 0.72rem;
color: rgba(232,224,212,0.5);
letter-spacing: 0.1em;
}
.product-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin-top: 1.5rem;
padding: 0.5rem 1rem;
background: var(--tag-bg);
border: 1px solid var(--border);
border-radius: 2px;
font-size: 0.68rem;
color: var(--gold-light);
letter-spacing: 0.12em;
}
.dot { width: 6px; height: 6px; background: var(--gold); border-radius: 50%; }
/* ── LAYOUT ── */
main { max-width: 1200px; margin: 0 auto; padding: 3rem 4rem; }
/* ── SECTION ── */
.component {
margin-bottom: 4rem;
border: 1px solid var(--border);
border-radius: 4px;
overflow: hidden;
}
.component-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem 1.5rem;
background: rgba(184,150,62,0.07);
border-bottom: 1px solid var(--border);
}
.component-num {
font-family: 'Cormorant Garamond', serif;
font-size: 1.4rem;
font-weight: 300;
color: var(--gold);
font-style: italic;
min-width: 2rem;
}
.component-title {
font-size: 0.7rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: #c8bfb0;
}
.component-tag {
margin-left: auto;
padding: 0.2rem 0.6rem;
background: var(--tag-bg);
border: 1px solid var(--border);
border-radius: 2px;
font-size: 0.6rem;
color: var(--gold);
letter-spacing: 0.1em;
}
/* ── CODE BLOCK ── */
.code-wrap { padding: 1.5rem; background: #080e1a; overflow-x: auto; }
pre {
font-family: 'DM Mono', monospace;
font-size: 0.72rem;
line-height: 1.7;
color: #c8d0e0;
white-space: pre;
}
.tok-key { color: #7eb8f7; }
.tok-str { color: #a8d9a0; }
.tok-num { color: #f0c060; }
.tok-bool { color: #e08080; }
.tok-cmt { color: #5a6a8a; font-style: italic; }
.tok-gold { color: var(--gold-light); }
/* ── PROSE SECTION ── */
.prose-wrap { padding: 1.5rem 2rem; }
.prose-wrap p { font-size: 0.78rem; color: #b8b0a4; line-height: 1.8; margin-bottom: 0.8rem; }
/* ── TEMPLATES ── */
.template-block {
padding: 1.5rem 2rem;
border-bottom: 1px solid rgba(184,150,62,0.1);
}
.template-block:last-child { border-bottom: none; }
.template-label {
font-size: 0.6rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--gold);
margin-bottom: 0.75rem;
}
.template-text {
font-family: 'DM Mono', monospace;
font-size: 0.72rem;
line-height: 1.8;
color: #d0c8be;
background: #080e1a;
padding: 1rem 1.25rem;
border-left: 2px solid var(--gold);
white-space: pre-wrap;
}
.token-pill {
display: inline-block;
margin-top: 0.6rem;
padding: 0.2rem 0.7rem;
background: rgba(184,150,62,0.12);
border: 1px solid rgba(184,150,62,0.3);
border-radius: 20px;
font-size: 0.6rem;
color: var(--gold-light);
letter-spacing: 0.1em;
}
.var-pill {
color: #7eb8f7;
font-style: italic;
}
/* ── WORKFLOW DIAGRAM ── */
.workflow-wrap { padding: 2rem; }
.flow-row {
display: flex;
align-items: stretch;
gap: 0;
margin-bottom: 0;
}
.flow-row.parallel { align-items: flex-start; margin-left: 3rem; }
.agent-box {
flex: 1;
border: 1px solid var(--border);
border-radius: 3px;
padding: 1rem 1.25rem;
background: #0d1525;
position: relative;
}
.agent-box .a-label {
font-size: 0.58rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--gold);
margin-bottom: 0.3rem;
}
.agent-box .a-name {
font-family: 'Cormorant Garamond', serif;
font-size: 1rem;
color: #fff;
margin-bottom: 0.5rem;
}
.agent-box .a-io {
font-size: 0.65rem;
color: #7a8aa0;
line-height: 1.6;
}
.arrow {
display: flex;
align-items: center;
padding: 0 0.5rem;
color: var(--gold);
font-size: 1.2rem;
flex-shrink: 0;
}
.arrow-down {
text-align: center;
color: var(--gold);
font-size: 1rem;
padding: 0.4rem 0;
margin-left: 2rem;
}
.parallel-label {
font-size: 0.58rem;
letter-spacing: 0.15em;
text-transform: uppercase;
color: rgba(184,150,62,0.5);
margin-bottom: 0.5rem;
margin-left: 3rem;
}
.flow-join {
margin-left: 3rem;
font-size: 0.65rem;
color: #5a6a8a;
padding: 0.3rem 0;
}
.data-tag {
display: inline-block;
padding: 0.15rem 0.4rem;
background: rgba(126,184,247,0.08);
border: 1px solid rgba(126,184,247,0.2);
border-radius: 2px;
font-size: 0.6rem;
color: #7eb8f7;
margin: 0.1rem 0;
font-style: italic;
}
/* ── MEMORY / CACHE ── */
.rule-list { padding: 1.5rem 2rem; }
.rule-item {
display: flex;
gap: 0.75rem;
margin-bottom: 0.7rem;
align-items: flex-start;
}
.rule-icon { color: var(--gold); flex-shrink: 0; font-size: 0.7rem; padding-top: 0.05rem; }
.rule-text { font-size: 0.73rem; color: #b0a898; line-height: 1.6; }
.rule-text strong { color: #d4ccc4; font-weight: 500; }
/* ── TOKEN BUDGET ── */
.budget-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1px;
background: var(--border);
border: 1px solid var(--border);
margin: 1.5rem 2rem;
}
.budget-cell {
background: #0d1525;
padding: 1rem 1.25rem;
}
.budget-agent { font-size: 0.6rem; letter-spacing: 0.15em; text-transform: uppercase; color: #5a7a9a; margin-bottom: 0.3rem; }
.budget-tokens {
font-family: 'Cormorant Garamond', serif;
font-size: 2rem;
font-weight: 300;
color: var(--gold);
line-height: 1;
}
.budget-label { font-size: 0.6rem; color: #5a6a7a; margin-top: 0.2rem; }
.budget-total { background: rgba(184,150,62,0.08); }
.budget-total .budget-tokens { color: #fff; }
/* ── FOOTER ── */
footer {
text-align: center;
padding: 2rem;
border-top: 1px solid var(--border);
font-size: 0.62rem;
color: #3a4a60;
letter-spacing: 0.12em;
text-transform: uppercase;
}
</style>
</head>
<body>
<header>
<div class="header-eyebrow">OpenClaw Agent System · Production-Ready</div>
<h1>Pattern Jewellery <span>Automation</span></h1>
<div class="header-sub">skill_schema · tool_definitions · prompt_templates · workflow · memory · cache · token_optimization</div>
<div class="product-badge">
<span class="dot"></span>
R4389 · Diamond & Blue Sapphire Ring · 18K White Gold · AED 4,455
</div>
</header>
<main>
<!-- ═══════════════════════════════════════════════════
COMPONENT 1: SKILL SCHEMA
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">01</span>
<span class="component-title">Skill Schema</span>
<span class="component-tag">JSON</span>
</div>
<div class="code-wrap"><pre>{
<span class="tok-key">"skill_name"</span>: <span class="tok-str">"pattern_jewellery_automation"</span>,
<span class="tok-key">"version"</span>: <span class="tok-str">"1.0.0"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Automates jewellery product marketing: enhances images, generates lifestyle and product visuals, creates SEO content, and stores outputs in Google Drive for Pattern Jewellery."</span>,
<span class="tok-key">"pattern_jewellery_specs"</span>: {
<span class="tok-key">"intricate_design_focus"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"high_detail_textures"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"fusion_aesthetic"</span>: <span class="tok-str">"traditional-modern"</span>,
<span class="tok-key">"target_market"</span>: <span class="tok-str">"Gulf luxury"</span>,
<span class="tok-key">"hallmark"</span>: <span class="tok-str">"750"</span>
},
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"product_image"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>,
<span class="tok-key">"format"</span>: <span class="tok-str">"url_or_base64"</span>,
<span class="tok-key">"required"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Raw product photograph from studio shoot"</span>
},
<span class="tok-key">"product_details"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"required"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"properties"</span>: {
<span class="tok-key">"name"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"Diamond Blue Sapphire Ring"</span> },
<span class="tok-key">"sku"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"R4389"</span> },
<span class="tok-key">"category"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"rings"</span> },
<span class="tok-key">"material"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"18K white gold 2.24gm, natural diamond 0.32ct, blue sapphire 0.78ct"</span> },
<span class="tok-key">"price_now"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"number"</span>, <span class="tok-key">"example"</span>: <span class="tok-num">4455</span> },
<span class="tok-key">"price_was"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"number"</span>, <span class="tok-key">"example"</span>: <span class="tok-num">8990</span> },
<span class="tok-key">"description"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"Oval blue sapphire centrepiece with double diamond halo, prong-set in 18K white gold, hallmarked 750"</span> }
}
}
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"model_image_url"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"description"</span>: <span class="tok-str">"URL of generated lifestyle model image"</span> },
<span class="tok-key">"product_image_url"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"description"</span>: <span class="tok-str">"URL of generated premium product-only image"</span> },
<span class="tok-key">"caption"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"description"</span>: <span class="tok-str">"SEO-optimized social media caption"</span> },
<span class="tok-key">"hashtags"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"array"</span>, <span class="tok-key">"items"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span> } },
<span class="tok-key">"drive_link"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"description"</span>: <span class="tok-str">"Google Drive folder URL for all assets"</span> }
},
<span class="tok-key">"steps"</span>: [
{
<span class="tok-key">"step"</span>: <span class="tok-num">1</span>,
<span class="tok-key">"id"</span>: <span class="tok-str">"prompt_generation"</span>,
<span class="tok-key">"agent"</span>: <span class="tok-str">"creative_agent"</span>,
<span class="tok-key">"depends_on"</span>: <span class="tok-str">"vision_agent"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate model and product image prompts from visual analysis and memory"</span>
},
{
<span class="tok-key">"step"</span>: <span class="tok-num">2</span>,
<span class="tok-key">"id"</span>: <span class="tok-str">"image_generation"</span>,
<span class="tok-key">"agent"</span>: <span class="tok-str">"vision_agent"</span>,
<span class="tok-key">"tool"</span>: <span class="tok-str">"imagen_api"</span>,
<span class="tok-key">"parallel"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate model lifestyle image and premium product image concurrently"</span>
},
{
<span class="tok-key">"step"</span>: <span class="tok-num">3</span>,
<span class="tok-key">"id"</span>: <span class="tok-str">"content_generation"</span>,
<span class="tok-key">"agent"</span>: <span class="tok-str">"content_agent"</span>,
<span class="tok-key">"tool"</span>: <span class="tok-str">"claude_llm"</span>,
<span class="tok-key">"parallel"</span>: <span class="tok-bool">true</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate SEO caption and hashtags concurrently with image generation"</span>
},
{
<span class="tok-key">"step"</span>: <span class="tok-num">4</span>,
<span class="tok-key">"id"</span>: <span class="tok-str">"storage"</span>,
<span class="tok-key">"agent"</span>: <span class="tok-str">"storage_agent"</span>,
<span class="tok-key">"tool"</span>: <span class="tok-str">"drive_api"</span>,
<span class="tok-key">"depends_on"</span>: [<span class="tok-str">"image_generation"</span>, <span class="tok-str">"content_generation"</span>],
<span class="tok-key">"description"</span>: <span class="tok-str">"Upload all assets to organized Google Drive folder"</span>
}
]
}</pre></div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 2: TOOL DEFINITIONS
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">02</span>
<span class="component-title">Tool Definitions</span>
<span class="component-tag">JSON</span>
</div>
<div class="code-wrap"><pre>[
{
<span class="tok-key">"tool_name"</span>: <span class="tok-str">"claude_llm"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Anthropic Claude for prompt generation and social content creation"</span>,
<span class="tok-key">"api_endpoint"</span>: <span class="tok-str">"https://api.anthropic.com/v1/messages"</span>,
<span class="tok-key">"auth_method"</span>: <span class="tok-str">"bearer_token"</span>,
<span class="tok-key">"auth_header"</span>: <span class="tok-str">"x-api-key"</span>,
<span class="tok-key">"model"</span>: <span class="tok-str">"claude-3-5-haiku-20241022"</span>,
<span class="tok-key">"functions"</span>: [
{
<span class="tok-key">"name"</span>: <span class="tok-str">"generate_image_prompt"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate optimized Imagen prompts for model and product visuals"</span>,
<span class="tok-key">"max_tokens"</span>: <span class="tok-num">300</span>,
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"image_analysis"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"fields"</span>: [<span class="tok-str">"design_type"</span>, <span class="tok-str">"material_detected"</span>, <span class="tok-str">"quality_score"</span>]
},
<span class="tok-key">"product_details"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"fields"</span>: [<span class="tok-str">"name"</span>, <span class="tok-str">"material"</span>, <span class="tok-str">"description"</span>]
},
<span class="tok-key">"memory"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"fields"</span>: [<span class="tok-str">"style"</span>, <span class="tok-str">"background_preference"</span>]
}
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"model_prompt"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"max_tokens"</span>: <span class="tok-num">120</span> },
<span class="tok-key">"product_prompt"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"max_tokens"</span>: <span class="tok-num">120</span> }
},
<span class="tok-key">"response_format"</span>: <span class="tok-str">"json"</span>
},
{
<span class="tok-key">"name"</span>: <span class="tok-str">"generate_social_content"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate SEO-optimized Instagram caption and hashtag array"</span>,
<span class="tok-key">"max_tokens"</span>: <span class="tok-num">220</span>,
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"product_details"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"fields"</span>: [<span class="tok-str">"name"</span>, <span class="tok-str">"price_now"</span>, <span class="tok-str">"price_was"</span>, <span class="tok-str">"material"</span>, <span class="tok-str">"description"</span>]
},
<span class="tok-key">"memory"</span>: {
<span class="tok-key">"type"</span>: <span class="tok-str">"object"</span>,
<span class="tok-key">"fields"</span>: [<span class="tok-str">"tone"</span>, <span class="tok-str">"top_performing_caption"</span>]
}
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"caption"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"max_chars"</span>: <span class="tok-num">220</span> },
<span class="tok-key">"hashtags"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"array"</span>, <span class="tok-key">"max_items"</span>: <span class="tok-num">20</span> }
},
<span class="tok-key">"response_format"</span>: <span class="tok-str">"json"</span>
}
]
},
{
<span class="tok-key">"tool_name"</span>: <span class="tok-str">"imagen_api"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Google Imagen 3 for high-fidelity jewellery image generation"</span>,
<span class="tok-key">"api_endpoint"</span>: <span class="tok-str">"https://us-central1-aiplatform.googleapis.com/v1/projects/{project_id}/locations/us-central1/publishers/google/models/imagen-3.0-generate-002:predict"</span>,
<span class="tok-key">"auth_method"</span>: <span class="tok-str">"oauth2_service_account"</span>,
<span class="tok-key">"model_version"</span>: <span class="tok-str">"imagen-3.0-generate-002"</span>,
<span class="tok-key">"functions"</span>: [
{
<span class="tok-key">"name"</span>: <span class="tok-str">"generate_model_image"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate lifestyle shot of model wearing jewellery"</span>,
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"prompt"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"required"</span>: <span class="tok-bool">true</span> },
<span class="tok-key">"aspect_ratio"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"default"</span>: <span class="tok-str">"4:5"</span>, <span class="tok-key">"enum"</span>: [<span class="tok-str">"1:1"</span>, <span class="tok-str">"4:5"</span>, <span class="tok-str">"9:16"</span>] },
<span class="tok-key">"quality"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"default"</span>: <span class="tok-str">"ultra"</span> },
<span class="tok-key">"sample_count"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"integer"</span>, <span class="tok-key">"default"</span>: <span class="tok-num">1</span> }
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"image_url"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"format"</span>: <span class="tok-str">"gcs_uri"</span> }
}
},
{
<span class="tok-key">"name"</span>: <span class="tok-str">"generate_product_image"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Generate premium product-only image on luxury background"</span>,
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"prompt"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"required"</span>: <span class="tok-bool">true</span> },
<span class="tok-key">"aspect_ratio"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"default"</span>: <span class="tok-str">"1:1"</span>, <span class="tok-key">"enum"</span>: [<span class="tok-str">"1:1"</span>, <span class="tok-str">"4:5"</span>] },
<span class="tok-key">"quality"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"default"</span>: <span class="tok-str">"ultra"</span> },
<span class="tok-key">"sample_count"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"integer"</span>, <span class="tok-key">"default"</span>: <span class="tok-num">1</span> }
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"image_url"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"format"</span>: <span class="tok-str">"gcs_uri"</span> }
}
}
]
},
{
<span class="tok-key">"tool_name"</span>: <span class="tok-str">"drive_api"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Google Drive for organized asset storage"</span>,
<span class="tok-key">"api_endpoint"</span>: <span class="tok-str">"https://www.googleapis.com/upload/drive/v3/files"</span>,
<span class="tok-key">"auth_method"</span>: <span class="tok-str">"oauth2_service_account"</span>,
<span class="tok-key">"scopes"</span>: [<span class="tok-str">"https://www.googleapis.com/auth/drive.file"</span>],
<span class="tok-key">"folder_structure"</span>: <span class="tok-str">"/Pattern_Jewellery/{product_category}/{YYYY-MM-DD}/{sku}/"</span>,
<span class="tok-key">"functions"</span>: [
{
<span class="tok-key">"name"</span>: <span class="tok-str">"upload_to_drive"</span>,
<span class="tok-key">"description"</span>: <span class="tok-str">"Upload file to structured Drive folder, return shareable link"</span>,
<span class="tok-key">"input_schema"</span>: {
<span class="tok-key">"file_data"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"format"</span>: <span class="tok-str">"binary_or_gcs_uri"</span> },
<span class="tok-key">"folder_path"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"/Pattern_Jewellery/rings/2025-01-15/R4389/"</span> },
<span class="tok-key">"file_name"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"example"</span>: <span class="tok-str">"R4389_model_lifestyle.jpg"</span> },
<span class="tok-key">"mime_type"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"default"</span>: <span class="tok-str">"image/jpeg"</span> }
},
<span class="tok-key">"output_schema"</span>: {
<span class="tok-key">"drive_link"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span>, <span class="tok-key">"format"</span>: <span class="tok-str">"https://drive.google.com/drive/folders/{folder_id}"</span> },
<span class="tok-key">"file_id"</span>: { <span class="tok-key">"type"</span>: <span class="tok-str">"string"</span> }
}
}
]
}
]</pre></div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 3: PROMPT TEMPLATES
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">03</span>
<span class="component-title">Prompt Templates</span>
<span class="component-tag">3 Templates</span>
</div>
<div class="template-block">
<div class="template-label">Template 1 · Model Lifestyle Image Prompt · Max 120 tokens</div>
<div class="template-text">Professional luxury jewellery lifestyle photograph, Gulf market. Elegant Middle Eastern woman, refined pose, manicured hand foregrounded. Wearing <span class="var-pill">{product_name}</span> crafted in <span class="var-pill">{material}</span>. Macro detail: <span class="var-pill">{design_details}</span>. Setting: modern Dubai interior, soft bokeh, neutral silk backdrop. Studio lighting with rim highlight on stone facets and prong setting. Editorial fashion quality. 8K, photorealistic, no text.</div>
<div class="token-pill">≈ 78 tokens · within 120-token limit ✓</div>
</div>
<div class="template-block">
<div class="template-label">Template 2 · Premium Product-Only Image Prompt · Max 120 tokens</div>
<div class="template-text">Luxury jewellery product photography, no model. <span class="var-pill">{product_name}</span> in <span class="var-pill">{material}</span>. Key features: <span class="var-pill">{key_features}</span>. Surface: white Carrara marble with deep navy velvet accent. Macro lens, tack-sharp stone facets and prong detail. Three-point studio lighting: soft key, hard fill catching diamond brilliance, warm backlight. Floating shadow. 8K, photorealistic, commercial retail grade, no text.</div>
<div class="token-pill">≈ 80 tokens · within 120-token limit ✓</div>
</div>
<div class="template-block">
<div class="template-label">Template 3 · Social Media Content Prompt · Max 180 tokens</div>
<div class="template-text">Generate Instagram content for Pattern Jewellery, Dubai. Luxury tone, traditional-modern fusion voice.
Product: <span class="var-pill">{product_name}</span>
Price: AED <span class="var-pill">{price_now}</span> (was AED <span class="var-pill">{price_was}</span>)
USP: <span class="var-pill">{unique_selling_points}</span>
Return JSON only:
{
"caption": "2–3 sentence luxury caption, highlight offer, end with CTA (link in bio / DM to order)",
"hashtags": ["array", "of", "20", "mixed", "broad+niche", "tags", "no", "spaces"]
}
Brand rules: aspirational, never salesy. Reference craftsmanship. Include price drop naturally.</div>
<div class="token-pill">≈ 102 tokens · within 180-token limit ✓</div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 4: MULTI-AGENT WORKFLOW DIAGRAM
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">04</span>
<span class="component-title">Multi-Agent Workflow Design</span>
<span class="component-tag">4 Agents</span>
</div>
<div class="workflow-wrap">
<!-- AGENT 1: VISION -->
<div class="flow-row">
<div class="agent-box" style="max-width:380px;">
<div class="a-label">Step 0 · Sequential</div>
<div class="a-name">Vision Agent</div>
<div class="a-io">
IN → <span class="data-tag">product_image (url)</span><br>
TOOL → Internal vision model<br>
OUT → <span class="data-tag">design_type</span> <span class="data-tag">material_detected</span> <span class="data-tag">quality_score</span>
</div>
</div>
</div>
<div class="arrow-down">↓ image_analysis (3 fields only)</div>
<!-- AGENT 2: CREATIVE -->
<div class="flow-row">
<div class="agent-box" style="max-width:380px;">
<div class="a-label">Step 1 · Sequential</div>
<div class="a-name">Creative Agent</div>
<div class="a-io">
IN → <span class="data-tag">image_analysis</span> <span class="data-tag">product_details</span> <span class="data-tag">memory.style</span> <span class="data-tag">memory.background_preference</span><br>
TOOL → claude_llm :: generate_image_prompt<br>
OUT → <span class="data-tag">model_prompt</span> <span class="data-tag">product_prompt</span>
</div>
</div>
</div>
<div class="arrow-down">↓ prompts dispatched in parallel to Steps 2 & 3</div>
<!-- PARALLEL: AGENTS 3 + CONTENT -->
<div class="parallel-label">⟳ Parallel Execution (Steps 2 & 3)</div>
<div class="flow-row" style="gap:1rem; max-width:820px;">
<div class="agent-box">
<div class="a-label">Step 2 · Parallel</div>
<div class="a-name">Image Agent (Vision)</div>
<div class="a-io">
IN → <span class="data-tag">model_prompt</span> <span class="data-tag">product_prompt</span><br>
TOOL → imagen_api :: generate_model_image<br>
imagen_api :: generate_product_image<br>
OUT → <span class="data-tag">model_image_url</span> <span class="data-tag">product_image_url</span>
</div>
</div>
<div class="arrow" style="color:#3a4a60;">|</div>
<div class="agent-box">
<div class="a-label">Step 3 · Parallel</div>
<div class="a-name">Content Agent</div>
<div class="a-io">
IN → <span class="data-tag">product_details</span> <span class="data-tag">memory.tone</span> <span class="data-tag">memory.top_performing_caption</span><br>
TOOL → claude_llm :: generate_social_content<br>
OUT → <span class="data-tag">caption</span> <span class="data-tag">hashtags[]</span>
</div>
</div>
</div>
<div class="flow-join">→ await both parallel steps complete</div>
<div class="arrow-down">↓ all 4 outputs collected</div>
<!-- AGENT 4: STORAGE -->
<div class="flow-row">
<div class="agent-box" style="max-width:500px;">
<div class="a-label">Step 4 · Sequential</div>
<div class="a-name">Storage Agent</div>
<div class="a-io">
IN → <span class="data-tag">model_image_url</span> <span class="data-tag">product_image_url</span> <span class="data-tag">caption</span> <span class="data-tag">hashtags[]</span> <span class="data-tag">product_details.sku</span> <span class="data-tag">product_details.category</span><br>
TOOL → drive_api :: upload_to_drive (×3: model img, product img, metadata.json)<br>
FOLDER → /Pattern_Jewellery/rings/2025-01-15/R4389/<br>
OUT → <span class="data-tag">drive_link (folder URL)</span>
</div>
</div>
</div>
<div class="arrow-down">↓ final skill output returned to user</div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 5: MEMORY SYSTEM
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">05</span>
<span class="component-title">Memory System Structure</span>
<span class="component-tag">JSON + Rules</span>
</div>
<div class="code-wrap"><pre><span class="tok-cmt">// memory.json — persistent, lightweight, 4 fields max</span>
{
<span class="tok-key">"style"</span>: <span class="tok-str">"editorial"</span>,
<span class="tok-key">"tone"</span>: <span class="tok-str">"aspirational-luxury"</span>,
<span class="tok-key">"background_preference"</span>: <span class="tok-str">"white-marble"</span>,
<span class="tok-key">"top_performing_caption"</span>: <span class="tok-str">"Timeless elegance, crafted for you. Now at AED 4,455 — link in bio."</span>
}
<span class="tok-cmt">// ── UPDATE RULES ──────────────────────────────────────────</span>
<span class="tok-cmt">// WHEN: Only on explicit user correction or positive feedback signal</span>
<span class="tok-cmt">// HOW: Replace field value atomically; no nested objects added</span>
<span class="tok-cmt">// WHERE: /system/memory/pattern_jewellery_memory.json (persistent)</span>
<span class="tok-cmt">// LIMIT: 4 fields hard cap — no expansion permitted</span>
<span class="tok-cmt">// ── INJECTION POINTS ──────────────────────────────────────</span>
<span class="tok-cmt">// Creative Agent receives: style + background_preference</span>
<span class="tok-cmt">// Content Agent receives: tone + top_performing_caption</span>
<span class="tok-cmt">// ── BEFORE / AFTER EXAMPLE ────────────────────────────────</span>
<span class="tok-cmt">// BEFORE (default state):</span>
{
<span class="tok-key">"style"</span>: <span class="tok-str">"editorial"</span>,
<span class="tok-key">"tone"</span>: <span class="tok-str">"aspirational-luxury"</span>,
<span class="tok-key">"background_preference"</span>: <span class="tok-str">"white-marble"</span>,
<span class="tok-key">"top_performing_caption"</span>: <span class="tok-str">""</span>
}
<span class="tok-cmt">// USER FEEDBACK: "I prefer dark navy velvet backgrounds, they performed better last week"</span>
<span class="tok-cmt">// AFTER (single field updated):</span>
{
<span class="tok-key">"style"</span>: <span class="tok-str">"editorial"</span>,
<span class="tok-key">"tone"</span>: <span class="tok-str">"aspirational-luxury"</span>,
<span class="tok-key">"background_preference"</span>: <span class="tok-str">"deep-navy-velvet"</span>,
<span class="tok-key">"top_performing_caption"</span>: <span class="tok-str">""</span>
}
<span class="tok-cmt">// Creative Agent now injects "deep-navy-velvet" into Template 2 at {background_preference}</span></pre></div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 6: CACHING LOGIC
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">06</span>
<span class="component-title">Caching Logic</span>
<span class="component-tag">JSON + Flow</span>
</div>
<div class="code-wrap"><pre><span class="tok-cmt">// cache.json — Redis or local JSON, 30-day TTL</span>
{
<span class="tok-key">"image_hashes"</span>: {
<span class="tok-key">"a3f2c1b9_diamond-blue-sapphire-ring-r4389"</span>: {
<span class="tok-key">"hash"</span>: <span class="tok-str">"a3f2c1b9"</span>,
<span class="tok-key">"created_at"</span>: <span class="tok-str">"2025-01-15T08:30:00Z"</span>,
<span class="tok-key">"expires_at"</span>: <span class="tok-str">"2025-02-14T08:30:00Z"</span>
}
},
<span class="tok-key">"enhanced_prompts"</span>: {
<span class="tok-key">"a3f2c1b9_diamond-blue-sapphire-ring-r4389"</span>: {
<span class="tok-key">"model_prompt"</span>: <span class="tok-str">"Professional luxury jewellery lifestyle photograph..."</span>,
<span class="tok-key">"product_prompt"</span>: <span class="tok-str">"Luxury jewellery product photography, no model..."</span>
}
},
<span class="tok-key">"final_outputs"</span>: {
<span class="tok-key">"a3f2c1b9_diamond-blue-sapphire-ring-r4389"</span>: {
<span class="tok-key">"model_image_url"</span>: <span class="tok-str">"https://drive.google.com/file/d/abc123"</span>,
<span class="tok-key">"product_image_url"</span>: <span class="tok-str">"https://drive.google.com/file/d/def456"</span>,
<span class="tok-key">"caption"</span>: <span class="tok-str">"Timeless elegance, crafted for you..."</span>,
<span class="tok-key">"hashtags"</span>: [<span class="tok-str">"#PatternJewellery"</span>, <span class="tok-str">"#DubaiJewellery"</span>],
<span class="tok-key">"drive_link"</span>: <span class="tok-str">"https://drive.google.com/drive/folders/xyz789"</span>
}
}
}
<span class="tok-cmt">// ── CACHE KEY FORMAT ──────────────────────────────────────</span>
<span class="tok-cmt">// "{pHash_8char}_{product_name_slug}"</span>
<span class="tok-cmt">// Example: "a3f2c1b9_diamond-blue-sapphire-ring-r4389"</span>
<span class="tok-cmt">// ── DETECTION ALGORITHM ───────────────────────────────────</span>
<span class="tok-cmt">// Algorithm: pHash (perceptual hash) — tolerates JPEG compression artifacts</span>
<span class="tok-cmt">// Match threshold: Hamming distance ≤ 10 (identical/near-identical images)</span>
<span class="tok-cmt">// product_details change detection: SHA1 hash of JSON.stringify(product_details)</span>
<span class="tok-cmt">// ── LOGIC FLOW ────────────────────────────────────────────</span>
<span class="tok-cmt">// 1. Receive product_image + product_details</span>
<span class="tok-cmt">// 2. Compute pHash(product_image) → hash_key</span>
<span class="tok-cmt">// 3. Compute SHA1(product_details) → detail_fingerprint</span>
<span class="tok-cmt">// 4. cache_key = hash_key + "_" + slug(product_details.name + product_details.sku)</span>
<span class="tok-cmt">// 5. IF cache_key in final_outputs AND NOT expired AND detail_fingerprint unchanged:</span>
<span class="tok-cmt">// RETURN cached final_outputs[cache_key] ← skip all agents</span>
<span class="tok-cmt">// 6. ELSE IF cache_key in enhanced_prompts (image same, details changed):</span>
<span class="tok-cmt">// SKIP vision_agent + creative_agent</span>
<span class="tok-cmt">// RE-RUN content_agent + storage_agent only</span>
<span class="tok-cmt">// 7. ELSE (full miss):</span>
<span class="tok-cmt">// EXECUTE full 4-step workflow</span>
<span class="tok-cmt">// STORE all layers in cache</span>
<span class="tok-cmt">// 8. Expiration: TTL = 30 days. Manual invalidation: cache.delete(cache_key)</span></pre></div>
</section>
<!-- ═══════════════════════════════════════════════════
COMPONENT 7: TOKEN OPTIMIZATION
═══════════════════════════════════════════════════ -->
<section class="component">
<div class="component-header">
<span class="component-num">07</span>
<span class="component-title">Token Optimization Strategy</span>
<span class="component-tag">Budget + Rules</span>
</div>
<div class="rule-list">
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Short atomic prompts:</strong> Each agent call handles one task only. No multi-instruction prompts. Template variables replace repeated context text.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Cached system prompts:</strong> System prompts for claude_llm are cached server-side using Anthropic prompt caching (cache_control: ephemeral). Not resent per call.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>JSON-only responses:</strong> All LLM outputs use response_format: json. Eliminates preamble, filler, and markdown tokens.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Minimal image_analysis payload:</strong> Vision Agent outputs exactly 3 fields (design_type, material_detected, quality_score). No descriptions, no arrays, no nested objects.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Selective memory injection:</strong> Creative Agent receives only style + background_preference. Content Agent receives only tone + top_performing_caption. No agent receives the full memory object.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Parallel Step 2 + 3:</strong> image_generation and content_generation run concurrently. Eliminates sequential latency and avoids a round-trip token overhead for orchestration.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>max_tokens hard caps:</strong> claude_llm calls capped at 300 tokens (generate_image_prompt) and 220 tokens (generate_social_content). Model is prevented from over-generating.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Cache-first on repeat images:</strong> Full cache hit skips all 4 agents (0 LLM tokens consumed). Partial hit (details changed) skips 2 agents, saving ~170 tokens.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Product details passed as minimal subset:</strong> Each agent receives only the fields it requires — never the full product_details object.</span></div>
<div class="rule-item"><span class="rule-icon">→</span><span class="rule-text"><strong>Memory limited to 4 string fields:</strong> No nested objects, arrays, or metadata stored. Keeps injection payload under 40 tokens per agent call.</span></div>
</div>
<div class="budget-grid">
<div class="budget-cell">
<div class="budget-agent">Vision Agent</div>
<div class="budget-tokens">≤ 50</div>
<div class="budget-label">tokens output (3-field JSON)</div>
</div>
<div class="budget-cell">
<div class="budget-agent">Creative Agent</div>
<div class="budget-tokens">≤ 240</div>
<div class="budget-label">tokens output (120 × 2 prompts)</div>
</div>
<div class="budget-cell">
<div class="budget-agent">Content Agent</div>
<div class="budget-tokens">≤ 180</div>
<div class="budget-label">tokens output (caption + hashtags)</div>
</div>
<div class="budget-cell">
<div class="budget-agent">Storage Agent</div>
<div class="budget-tokens">≤ 30</div>
<div class="budget-label">tokens output (drive_link + file_ids)</div>
</div>
<div class="budget-cell budget-total">
<div class="budget-agent">Total Per Execution</div>
<div class="budget-tokens">≤ 500</div>
<div class="budget-label">tokens (well under 600 budget)</div>
</div>
<div class="budget-cell">
<div class="budget-agent">Cache Hit (full)</div>
<div class="budget-tokens">0</div>
<div class="budget-label">LLM tokens consumed</div>
</div>
</div>
</section>
</main>
<footer>
Pattern Jewellery Automation · OpenClaw Skill System v1.0.0 · SKU R4389 · Diamond & Blue Sapphire Ring · 18K White Gold
</footer>
</body>
</html>
FILE:jewellery_openclaw_skill.json
{
"skill_name": "pattern_jewellery_vertex_automation",
"version": "1.2.0",
"description": "Automates jewellery product marketing using Google Vertex AI (Gemini for text, Imagen for visuals) and stores final assets in Google Drive. Enhances images, generates lifestyle/product visuals, creates SEO content, and organizes returning final unified assets.",
"pattern_jewellery_specs": {
"intricate_design_focus": true,
"high_detail_textures": true,
"fusion_aesthetic": "traditional-modern",
"target_market": "Gulf luxury"
},
"input_schema": {
"product_image": {
"type": "string",
"format": "url_or_base64",
"required": true,
"description": "Raw product photograph from studio shoot"
},
"product_details": {
"type": "object",
"required": true,
"properties": {
"name": { "type": "string", "example": "Diamond Blue Sapphire Ring" },
"sku": { "type": "string", "example": "R4389" },
"category": { "type": "string", "example": "rings" },
"material": { "type": "string", "example": "18K white gold" },
"price_now": { "type": "number", "example": 4455 },
"description": { "type": "string", "example": "Oval blue sapphire centrepiece with double diamond halo" }
}
}
},
"output_schema": {
"model_image_url": { "type": "string", "description": "URL of generated lifestyle model image" },
"product_image_url": { "type": "string", "description": "URL of generated premium product-only image" },
"caption": { "type": "string", "description": "SEO-optimized social media caption from Gemini" },
"hashtags": { "type": "array", "items": { "type": "string" } },
"drive_link": { "type": "string", "description": "Google Drive folder URL containing all generated assets" }
},
"tools": [
{
"tool_name": "gemini_llm",
"description": "Google Vertex AI Gemini 1.5 Pro for prompt generation and social content creation",
"api_endpoint": "https://us-central1-aiplatform.googleapis.com/v1/projects/{project_id}/locations/us-central1/publishers/google/models/gemini-1.5-pro:generateContent",
"auth_method": "bearer_token",
"auth_header": "Authorization",
"model": "gemini-1.5-pro",
"functions": [
{
"name": "generate_image_prompt",
"description": "Generate optimized Imagen prompts for model and product visuals",
"max_tokens": 300,
"input_schema": {
"image_url": {"type": "string"},
"product_details": {
"type": "object",
"fields": ["name", "material", "description"]
}
},
"output_schema": {
"model_prompt": { "type": "string", "max_tokens": 120 },
"product_prompt": { "type": "string", "max_tokens": 120 }
},
"response_format": "json"
},
{
"name": "generate_social_content",
"description": "Generate SEO-optimized Instagram caption and hashtag array",
"max_tokens": 220,
"input_schema": {
"product_details": {
"type": "object",
"fields": ["name", "price_now", "material", "description"]
}
},
"output_schema": {
"caption": { "type": "string", "max_chars": 220 },
"hashtags": { "type": "array", "max_items": 20 }
},
"response_format": "json"
}
]
},
{
"tool_name": "imagen_api",
"description": "Google Vertex AI Imagen 3 for high-fidelity jewellery image generation",
"api_endpoint": "https://us-central1-aiplatform.googleapis.com/v1/projects/{project_id}/locations/us-central1/publishers/google/models/imagen-3.0-generate-002:predict",
"auth_method": "bearer_token",
"auth_header": "Authorization",
"model_version": "imagen-3.0-generate-002",
"functions": [
{
"name": "generate_model_image",
"description": "Generate lifestyle shot of model wearing jewellery",
"input_schema": {
"prompt": { "type": "string", "required": true },
"aspect_ratio": { "type": "string", "default": "4:5", "enum": ["1:1", "4:5", "9:16"] },
"person_generation": { "type": "string", "default": "ALLOW_ADULT" }
},
"output_schema": {
"image_bytes": { "type": "string", "format": "base64" }
}
},
{
"name": "generate_product_image",
"description": "Generate premium product-only image on luxury background",
"input_schema": {
"prompt": { "type": "string", "required": true },
"aspect_ratio": { "type": "string", "default": "1:1", "enum": ["1:1", "4:5"] }
},
"output_schema": {
"image_bytes": { "type": "string", "format": "base64" }
}
}
]
},
{
"tool_name": "drive_api",
"description": "Google Drive for organized asset storage",
"api_endpoint": "https://www.googleapis.com/upload/drive/v3/files",
"auth_method": "oauth2_service_account",
"scopes": ["https://www.googleapis.com/auth/drive.file"],
"folder_structure": "/Pattern_Jewellery/{product_category}/{sku}/",
"functions": [
{
"name": "upload_to_drive",
"description": "Upload file to structured Drive folder, return shareable link",
"input_schema": {
"file_data": { "type": "string", "format": "binary_or_base64" },
"folder_path": { "type": "string", "example": "/Pattern_Jewellery/rings/R4389/" },
"file_name": { "type": "string", "example": "R4389_model_lifestyle.jpg" },
"mime_type": { "type": "string", "default": "image/jpeg" }
},
"output_schema": {
"drive_link": { "type": "string", "format": "https://drive.google.com/drive/folders/{folder_id}" },
"file_id": { "type": "string" }
}
}
]
}
],
"steps": [
{
"step": 1,
"id": "prompt_generation",
"agent": "creative_agent",
"tool": "gemini_llm",
"function": "generate_image_prompt",
"description": "Analyze the product image and details using Gemini 1.5 Pro to generate tailored model and product generation prompts."
},
{
"step": 2,
"id": "image_generation",
"agent": "vision_agent",
"tool": "imagen_api",
"parallel": true,
"description": "Dispatch parallel requests to Imagen 3 to generate the lifestyle model shot and the standalone product shot based on Gemini's prompts."
},
{
"step": 3,
"id": "content_generation",
"agent": "content_agent",
"tool": "gemini_llm",
"function": "generate_social_content",
"parallel": true,
"description": "Use Gemini 1.5 Pro to draft an engaging Instagram caption and SEO hashtag package concurrently with image generation."
},
{
"step": 4,
"id": "storage",
"agent": "storage_agent",
"tool": "drive_api",
"depends_on": ["image_generation", "content_generation"],
"description": "Take outputs from the parallel generation steps and upload all assets (images + text) into a dedicated Google Drive folder."
},
{
"step": 5,
"id": "response_compilation",
"agent": "system_agent",
"depends_on": ["storage"],
"description": "Return the final unified JSON payload containing the Google Drive link and captions."
}
]
}