Skip to content

Gabriel AI Orchestrator

Gabriel is FOTOhub's intelligent platform orchestrator — a proprietary AI layer that classifies user intent, routes requests to optimal features, selects the best available model, builds prompts, and orchestrates multi-step workflows.

Gabriel AI is free to use for authenticated users and provides real-time suggestions, streaming responses, and proactive recommendations.

All authenticated Gabriel endpoints accept your standard API key (fh_live_* / fh_test_*) via the Authorization: Bearer header — the same key you use for every other endpoint. A Supabase session JWT is also accepted (used by the web dashboard), but no separate credential is required for API integrations.

Endpoints

MethodPathAuthDescription
POST/v1/ai/gabrielAPI key or JWTClassify intent and route (single-shot)
POST/v1/ai/gabriel/streamAPI key or JWTStreaming orchestration (SSE)
POST/v1/ai/gabriel/suggestNoneLightweight autocomplete suggestions
POST/v1/ai/gabriel/recommendNoneProactive context-aware recommendations
POST/v1/ai/translateAPI key or JWTTranslate text

POST /v1/ai/gabriel

Classify user intent and return a routing decision with optimal model selection, credit estimation, and contextual tips.

Rate limit: 30 requests/minute per user

Authentication: API key (fh_live_* / fh_test_*) or Supabase session JWT

Request Body

FieldTypeRequiredDescription
promptstringYesUser's natural language request (max 1000 chars)
languagestringNoLanguage code (default: "pl")
contextobjectNoAdditional context for better classification
enhance_promptbooleanNoWhen true, Gabriel enriches the prompt using model-specific architecture knowledge

Context Object

FieldTypeDescription
user_tierstringUser's subscription tier ("free", "pro", "business")
wallet_balance_usdfloatCurrent prepaid USD wallet balance
recent_toolsstring[]Last 5 features the user used
brand_idstringActive brand kit ID (for brand-aware suggestions)

Response

FieldTypeDescription
actionstring"route" | "answer" | "workflow" | "error"
targetstringFeature path to navigate to (e.g., /generate/image)
paramsobjectPre-configured parameters for the target feature
model_selectedstringOptimal available model for the request
suggested_actionsarrayAlternative actions the user might want
confidencefloatClassification confidence (0.0 - 1.0)
credits_estimatedintegerEstimated credit cost
tipsstring[]Contextual prompt engineering tips

Actions

ActionDescription
routeNavigate user to a FOTOhub feature with pre-filled parameters
answerDirect text response (FAQ, help, platform guidance)
workflowMulti-step task requiring sequential operations
errorClassification failed or timed out

Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="your-api-key")

result = client.gabriel.classify(
    prompt="Generate a cinematic photo of a sunset over mountains",
    language="en",
    enhance_prompt=True
)

print(result)
# {
#   "action": "route",
#   "target": "/generate/image",
#   "params": {
#     "model": "seedream-5-0-260128",
#     "prompt": "a sunset over mountains, cinematic color grading, golden hour, dramatic volumetric clouds, 8K, ultra detailed, shallow depth of field"
#   },
#   "model_selected": "seedream-5-0-260128",
#   "confidence": 0.95,
#   "credits_estimated": 1,
#   "tips": ["Seedream excels at photorealism — add '8K, sharp detail' for best results"]
# }
typescript
import { FotoHub } from 'fotohub';

const client = new FotoHub({ apiKey: 'your-api-key' });

const result = await client.gabriel.classify({
  prompt: 'Make a 5-second video of a cat walking through a garden',
  language: 'en',
  context: { wallet_balance_usd: 50 }
});

// {
//   "action": "route",
//   "target": "/generate/video",
//   "params": { "model": "seedance-2-0-pro", "duration": 5, "prompt": "..." },
//   "model_selected": "seedance-2-0-pro",
//   "confidence": 0.92,
//   "credits_estimated": 10,
//   "tips": ["Seedance: describe camera movement for dynamic videos"]
// }
bash
curl -X POST https://apis.fotohub.app/v1/ai/gabriel \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer fh_live_YOUR_API_KEY" \
  -d '{
    "prompt": "Create a brand identity for my coffee shop",
    "language": "en",
    "enhance_prompt": true,
    "context": {
      "user_tier": "pro",
      "wallet_balance_usd": 100
    }
  }'

POST /v1/ai/gabriel/stream

Streaming orchestration via Server-Sent Events (SSE). Provides progressive feedback as Gabriel processes the request — reduces perceived latency and enables real-time UX.

Rate limit: 30 requests/minute per user

Authentication: API key (fh_live_* / fh_test_*) or Supabase session JWT

Request Body

Same as /v1/ai/gabriel (prompt, language, context).

SSE Event Types

Events are sent as data: {json}\n\n lines. The stream ends with data: [DONE]\n\n.

Event TypeDescriptionFields
thinkingGabriel is processingcontent: status message
routingIntent classified, routing in progresstool: tool being called, content: description
resultFinal routing decisionSame fields as single-shot response
errorProcessing failedmessage: error description

Example

typescript
const response = await fetch('https://apis.fotohub.app/v1/ai/gabriel/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  },
  body: JSON.stringify({
    prompt: 'Generate a portrait photo with dramatic lighting',
    language: 'en'
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const text = decoder.decode(value);
  for (const line of text.split('\n')) {
    if (line.startsWith('data: ')) {
      const data = line.slice(6);
      if (data === '[DONE]') break;

      const event = JSON.parse(data);
      switch (event.type) {
        case 'thinking':
          console.log('Processing:', event.content);
          break;
        case 'routing':
          console.log('Using tool:', event.tool);
          break;
        case 'result':
          console.log('Route:', event.target, event.model_selected);
          console.log('Tips:', event.tips);
          break;
      }
    }
  }
}

Stream Timeline

Client                    Gabriel
  |--- POST /stream ------->|
  |<-- thinking: "..." ------|  (immediate, <100ms)
  |<-- routing: {...} -------|  (after intent classification)
  |<-- result: {...} --------|  (final decision + tips)
  |<-- data: [DONE] ---------|

POST /v1/ai/gabriel/suggest

Lightweight autocomplete suggestions. No LLM call — pure in-memory fuzzy matching for sub-50ms response times. Use this for keystroke-speed suggestions as the user types.

Rate limit: 60 requests/minute per IP

Authentication: None required

Request Body

FieldTypeRequiredDescription
partialstringYesPartial user input (min 2 chars, max 200)
tabstringNoCurrent tab context: "all", "image", "video", "audio"
pagestringNoCurrent page path (e.g., /generate/new)

Response

FieldTypeDescription
suggestionsarrayUp to 5 ranked suggestions

Suggestion Object

FieldTypeDescription
textstringSuggestion text
categorystring"prompt" | "tip" | "model" | "feature"
targetstringOptional navigation target
iconstringOptional icon identifier

Example

typescript
// Debounce to 300ms for optimal UX
const suggestions = await fetch('https://apis.fotohub.app/v1/ai/gabriel/suggest', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    partial: 'portrait photo',
    tab: 'image',
    page: '/generate/new'
  })
}).then(r => r.json());

// {
//   "suggestions": [
//     { "text": "portrait photo, studio lighting, shallow depth of field, 8K", "category": "prompt", "icon": "camera" },
//     { "text": "Try Seedream for best portrait quality (1 credit)", "category": "tip", "icon": "sparkles" },
//     { "text": "Use face enhancement for portrait shots", "category": "feature", "target": "/tools/enhance", "icon": "wand" }
//   ]
// }
bash
curl -X POST https://apis.fotohub.app/v1/ai/gabriel/suggest \
  -H "Content-Type: application/json" \
  -d '{"partial": "sunset", "tab": "image"}'

Integration Pattern

typescript
// Recommended: debounced suggestions with local fallback
let debounceTimer: number;

function onInputChange(value: string) {
  // Show local suggestions immediately
  showLocalSuggestions(value);

  // Fetch API suggestions after 300ms pause
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(async () => {
    if (value.length >= 2) {
      const { suggestions } = await fetchSuggestions(value);
      if (suggestions.length > 0) {
        replaceSuggestions(suggestions); // API results take priority
      }
    }
  }, 300);
}

POST /v1/ai/gabriel/recommend

Proactive context-aware recommendations. Returns 1-3 relevant tips based on the user's current state. Template-based (no LLM call), responds in <100ms.

Rate limit: 30 requests/minute per IP

Authentication: None required

Request Body

FieldTypeRequiredDescription
pagestringNoCurrent page path
recent_actionsstring[]NoLast few actions taken
wallet_balance_usdfloatNoUser's prepaid USD wallet balance
has_brandbooleanNoWhether user has a brand kit

Response

FieldTypeDescription
recommendationsarrayUp to 3 contextual recommendations

Recommendation Object

FieldTypeDescription
textstringRecommendation text
targetstringNavigation target
iconstringIcon identifier

Example

bash
curl -X POST https://apis.fotohub.app/v1/ai/gabriel/recommend \
  -H "Content-Type: application/json" \
  -d '{
    "page": "/generate/new",
    "wallet_balance_usd": 5,
    "has_brand": false
  }'

# Response:
# {
#   "recommendations": [
#     { "text": "Low credits — Seedream gives best quality at 1 credit", "target": "/generate/new", "icon": "coins" },
#     { "text": "Create a Brand Kit for consistent style across generations", "target": "/brand", "icon": "palette" }
#   ]
# }

POST /v1/ai/translate

Translate text between languages using FOTOhub's built-in translation engine.

Rate limit: 30 requests/minute per user

Authentication: API key (fh_live_* / fh_test_*) or Supabase session JWT

Request Body

FieldTypeRequiredDescription
textstringYesText to translate (max 10,000 chars)
target_languagestringYesTarget language code (e.g., "en", "pl", "de")
source_languagestringNoSource language (auto-detected if omitted)

Response

FieldTypeDescription
translated_textstringThe translation
source_languagestringDetected/specified source language
target_languagestringTarget language
character_countintegerCharacter count of translated text

Examples

python
from fotohub import FotoHub

client = FotoHub(api_key="your-api-key")

result = client.translate(
    text="The quick brown fox jumps over the lazy dog",
    target_language="pl"
)
# { "translated_text": "Szybki brązowy lis przeskakuje nad leniwym psem", ... }
typescript
const response = await fetch('https://apis.fotohub.app/v1/ai/translate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    text: 'Bonjour le monde',
    target_language: 'en',
    source_language: 'fr'
  })
});

const { translated_text } = await response.json();
// "Hello world"
bash
curl -X POST https://apis.fotohub.app/v1/ai/translate \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hallo Welt",
    "target_language": "en"
  }'

Orchestrator Capabilities

Gabriel provides 10 function-calling tools for intelligent platform routing:

ToolDescription
route_to_image_generationRoute to image generation with optimal model + params
route_to_video_generationRoute to video generation with model + duration
route_to_chatRoute to LLM chat with selected model
route_to_music_generationRoute to music/audio generation
route_to_image_editingRoute to image editing tools (upscale, bg remove, etc.)
route_to_3d_generationRoute to 3D model generation
answer_questionDirect text answer for FAQ/help
route_to_brandRoute to brand kit management
route_to_toolsRoute to platform tools (face swap, lip sync, etc.)
create_workflowMulti-step workflow for complex tasks

Dynamic Model Awareness

Gabriel only recommends models that are currently available. Model availability is checked against the platform's model status database (refreshed every 60 seconds). If a model is disabled or experiencing issues, Gabriel automatically selects the next best alternative.

Prompt Enhancement

When enhance_prompt: true is set, Gabriel applies model-specific prompt engineering:

Model FamilyEnhancement Strategy
SeedreamAdds photorealistic quality terms, resolution hints, optimized structure
SeedanceAdds camera movement, temporal progression, cinematic terms
FLUXAdds detailed composition, style-specific tokens
ImagenAdds quality terms, structured scene description
WanAdds motion description, scene progression
Grok ImagineAdds studio lighting terms, product photography markers, commercial quality

Multi-Step Workflows

When a request requires multiple operations, Gabriel returns action: "workflow" with a steps array:

json
{
  "action": "workflow",
  "params": {
    "steps": [
      { "action": "route_to_image_generation", "target": "/generate/new", "params": {"model": "seedream-5-0-260128", "prompt": "..."} },
      { "action": "route_to_image_editing", "target": "/tools/remove-bg", "params": {"tool": "background_removal"} },
      { "action": "route_to_brand", "target": "/brand", "params": {"action": "save_asset"} }
    ],
    "description": "Generate logo, remove background, save to brand kit"
  }
}

Credit Estimation

Gabriel estimates costs for 50+ models across image, video, and chat:

Image Models

ModelCredits/image
flux-2-klein-4b1.0
minimax-image-011.0
grok-imagine-image1.0
seedream-5-0-2601282.0
seedream-4-5-2511282.0
flux-1.1-pro2.0
flux-kontext-pro2.0
flux-2-pro2.0
imagen-4-standard3.0
grok-imagine-image-pro3.0
imagen-4-ultra5.0

Video Models

Most models bill per second (see the full catalog); MiniMax Hailuo bills a flat per-video amount.

ModelCredits/s
wan2.2-t2v-plus1.2
hailuo-o2— (6 flat)
kling-v35
seedance-2-0-pro9.4
sora-28
gemini-omni-flash6
veo-3.1-generate-00112
grok-imagine-video-1.59

Chat / LLM Models

ModelCredits/message
gemini-flash1.0
gemini-pro2.0
gpt-4o2.0
claude-sonnet2.0

Best Value

seedream-5-0-260128 offers the best quality-to-credit ratio for image generation, and wan2.2-t2v-plus / hailuo-o2 are the most cost-effective for video. For chat, gemini-flash (1 cr) is the cheapest option.


Error Handling

All endpoints gracefully degrade on failure:

ScenarioBehavior
Timeout (>5s for Gabriel, >10s for Translate)Returns error action / original text
Model errorAuto-failover to backup model (transparent to caller)
Rate limit exceededHTTP 429 with retry-after header
Invalid JWTHTTP 401 (for authenticated endpoints)
Missing promptHTTP 422 with validation details

Model Failover

Gabriel uses a multi-model failover chain. If the primary model is unavailable, it automatically falls back without returning an error:

Primary → Backup 1 → Backup 2

The response always succeeds unless all models in the chain are down.


Integration Patterns

Building a Conversational Assistant

python
from fotohub import FotoHub

client = FotoHub(api_key="your-api-key")

def handle_user_message(message: str, user_context: dict):
    result = client.gabriel.classify(
        prompt=message,
        language="en",
        context=user_context,
        enhance_prompt=True
    )
    
    if result["action"] == "route":
        return {
            "message": f"I'll use {result['model_selected']} (~{result['credits_estimated']} credits)",
            "action": result["target"],
            "params": result["params"],
            "tips": result.get("tips", [])
        }
    elif result["action"] == "workflow":
        steps = result["params"]["steps"]
        return {
            "message": f"This requires {len(steps)} steps: {result['params']['description']}",
            "workflow": steps
        }
    elif result["action"] == "answer":
        return {"message": result["answer"]}
    else:
        return {"message": "I couldn't understand that request."}

Real-time Suggestions with Streaming

typescript
import { FotoHub } from 'fotohub';

const client = new FotoHub({ apiKey: 'your-api-key' });

// 1. Autocomplete as user types (debounced 300ms)
const suggestions = await client.gabriel.suggest('portrait photo', {
  tab: 'image',
  page: '/generate/new'
});

// 2. Stream the final classification
const stream = await client.gabriel.stream({
  prompt: 'Generate a cinematic portrait with dramatic lighting',
  language: 'en'
});

for await (const event of stream) {
  if (event.type === 'thinking') updateUI('Processing...');
  if (event.type === 'routing') updateUI(`Using ${event.tool}...`);
  if (event.type === 'result') navigateTo(event.target, event.params);
}

Proactive Onboarding Tips

typescript
// Show contextual tips when user lands on a page
const { recommendations } = await fetch(
  'https://apis.fotohub.app/v1/ai/gabriel/recommend',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      page: '/generate/new',
      wallet_balance_usd: user.credits,
      has_brand: user.brands.length > 0,
      recent_actions: ['image_generation', 'image_generation']
    })
  }
).then(r => r.json());

// Display as floating chips:
// "Try video generation — Seedance creates 5s clips for 1 credit"
// "Create a Brand Kit for consistent style"

Multi-language App with Auto-translation

typescript
async function translateUI(texts: string[], targetLang: string) {
  const results = await Promise.all(
    texts.map(text =>
      fetch('https://apis.fotohub.app/v1/ai/translate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text, target_language: targetLang })
      }).then(r => r.json())
    )
  );
  return results.map(r => r.translated_text);
}