Hoody AI Usage
Section titled “Hoody AI Usage”Complete integration examples for accessing Hoody AI from containers, AI clients, and custom applications.
This guide shows you exactly how to configure and use Hoody AI across different tools and scenarios.
Quick Reference
Section titled “Quick Reference”Hoody AI Endpoint:
https://ai.hoody.icu/api/v1API Key Format:
container-{containerName}Compatibility: OpenAI-compatible API
From Containers
Section titled “From Containers”Quick Start: Chat Completion
Section titled “Quick Start: Chat Completion”# Chat completion from your containercurl -X POST "https://ai.hoody.icu/api/v1/chat/completions" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-sonnet-4.5", "messages": [ {"role": "system", "content": "You are a helpful coding assistant."}, {"role": "user", "content": "Write a Python function to calculate fibonacci numbers"} ], "max_tokens": 1024, "temperature": 0.7 }'
# Streaming responsecurl -X POST "https://ai.hoody.icu/api/v1/chat/completions" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4o", "messages": [{"role": "user", "content": "Explain quantum computing"}], "stream": true }'import { HoodyClient } from '@hoody-ai/hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });
// List available AI models via SDKconst models = await client.api.ai.listModels();console.log(models.data);
// Chat completion — call the AI gateway directly from your containerconst response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-dev-env', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [ { role: 'system', content: 'You are a helpful coding assistant.' }, { role: 'user', content: 'Write a Python function to calculate fibonacci numbers' } ], max_tokens: 1024, temperature: 0.7 })});
const data = await response.json();console.log(data.choices[0].message.content);# Chat completion with system promptcurl -X POST "https://ai.hoody.icu/api/v1/chat/completions" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-sonnet-4.5", "messages": [ {"role": "system", "content": "You are a helpful coding assistant."}, {"role": "user", "content": "Write a Python function to calculate fibonacci numbers"} ], "max_tokens": 1024, "temperature": 0.7 }'
# Streaming response (Server-Sent Events)curl -X POST "https://ai.hoody.icu/api/v1/chat/completions" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4o", "messages": [{"role": "user", "content": "Explain quantum computing"}], "stream": true }'
# Image generation (image-capable models return images via chat/completions —# pick a model whose output_modalities include "image"; see /models)curl -X POST "https://ai.hoody.icu/api/v1/chat/completions" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "<image-capable-model-id>", "messages": [{"role": "user", "content": "A futuristic city with flying cars at sunset"}] }'
# Text embeddingscurl -X POST "https://ai.hoody.icu/api/v1/embeddings" \ -H "Authorization: Bearer container-dev-env" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/text-embedding-3-large", "input": "The quick brown fox jumps over the lazy dog" }'Interactive Playground
Section titled “Interactive Playground” Receives Server-Sent Events (SSE) for real-time streaming.
Node.js / TypeScript
Section titled “Node.js / TypeScript”// Using native fetch (Node 18+)async function askAI(prompt: string) { const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-dev-env', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [ { role: 'user', content: prompt } ], max_tokens: 2048 }) });
const data = await response.json(); return data.choices[0].message.content;}
// Example usageconst answer = await askAI('How do I deploy a Next.js app?');console.log(answer);Python
Section titled “Python”import requestsimport json
def ask_ai(prompt: str) -> str: """Query Hoody AI with a prompt""" response = requests.post( 'https://ai.hoody.icu/api/v1/chat/completions', headers={ 'Authorization': 'Bearer container-python-app', 'Content-Type': 'application/json' }, json={ 'model': 'anthropic/claude-sonnet-4.5', 'messages': [ {'role': 'user', 'content': prompt} ], 'max_tokens': 2048 } )
data = response.json() return data['choices'][0]['message']['content']
# Example usageanswer = ask_ai('Explain Docker containers in simple terms')print(answer)AI Coding Assistants
Section titled “AI Coding Assistants”hoody-agent (Native Integration)
Section titled “hoody-agent (Native Integration)”hoody-agent has built-in Hoody AI support:
# Create agent task with Hoody AIcurl -X POST "https://{project}-{container}-workspaces-1.node-us.containers.hoody.icu/api/tasks" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Build a REST API for a todo app with SQLite", "auto_execute": true, "mode": "code", "ai_config": { "provider": "hoody", "model": "anthropic/claude-sonnet-4.5" } }'No API key needed - hoody-agent automatically uses container-{name} when configured for Hoody AI.
Cursor IDE
Section titled “Cursor IDE”Settings → Models → Add Custom Provider:
- Base URL:
https://ai.hoody.icu/api/v1 - API Key:
container-{yourContainerName} - Provider: Custom (OpenAI-compatible)
- Models: Select from dropdown (Claude Opus 4.1, GPT-4o, etc.)
Example .cursor/config.json:
{ "openai": { "baseURL": "https://ai.hoody.icu/api/v1", "apiKey": "container-cursor-dev" }, "defaultModel": "anthropic/claude-sonnet-4.5"}Cline (VS Code Extension)
Section titled “Cline (VS Code Extension)”Extension Settings:
- Open Cline settings in VS Code
- API Provider: Custom (OpenAI-compatible)
- Base URL:
https://ai.hoody.icu/api/v1 - API Key:
container-{containerName} - Model:
anthropic/claude-sonnet-4.5
Cline will now route all AI requests through Hoody AI without exposing real keys.
Continue.dev
Section titled “Continue.dev”config.json:
{ "models": [ { "title": "Hoody AI - Claude Sonnet 4.5", "provider": "openai", "model": "anthropic/claude-sonnet-4.5", "apiKey": "container-continue-dev", "apiBase": "https://ai.hoody.icu/api/v1" } ]}Windsurf
Section titled “Windsurf”AI Settings:
- Provider: Custom OpenAI-compatible
- Endpoint:
https://ai.hoody.icu/api/v1 - API Key:
container-windsurf-env - Model:
anthropic/claude-sonnet-4.5oropenai/gpt-4o
Application Integration Examples
Section titled “Application Integration Examples”Next.js API Route
Section titled “Next.js API Route”import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) { const { message } = await req.json();
const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-nextjs-app', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [ { role: 'user', content: message } ], stream: true // Enable streaming }) });
// Stream response back to client return new NextResponse(response.body, { headers: { 'Content-Type': 'text/event-stream' } });}Express.js Server
Section titled “Express.js Server”const express = require('express');const app = express();
app.use(express.json());
app.post('/api/ask', async (req, res) => { const { prompt } = req.body;
try { const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-express-api', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-haiku-4.0', // Faster, cheaper model messages: [ { role: 'user', content: prompt } ], max_tokens: 1024 }) });
const data = await response.json(); res.json({ answer: data.choices[0].message.content }); } catch (error) { res.status(500).json({ error: error.message }); }});
app.listen(3000);React Component with Streaming
Section titled “React Component with Streaming”'use client';
import { useState } from 'react';
export default function AIChat() { const [prompt, setPrompt] = useState(''); const [response, setResponse] = useState(''); const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setLoading(true); setResponse('');
const res = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-react-app', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [{ role: 'user', content: prompt }], stream: true }) });
const reader = res.body?.getReader(); const decoder = new TextDecoder();
while (true) { const { done, value } = await reader!.read(); if (done) break;
const chunk = decoder.decode(value); const lines = chunk.split('\n').filter(line => line.trim());
for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') continue;
const parsed = JSON.parse(data); const content = parsed.choices[0]?.delta?.content || ''; setResponse(prev => prev + content); } } }
setLoading(false); }
return ( <form onSubmit={handleSubmit}> <input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Ask me anything..." /> <button type="submit" disabled={loading}> {loading ? 'Thinking...' : 'Send'} </button> {response && <div>{response}</div>} </form> );}Advanced Patterns
Section titled “Advanced Patterns”Multi-Model Orchestration
Section titled “Multi-Model Orchestration”Use different models for different tasks:
async function orchestrateTask(userRequest: string) { // Fast model for classification const classification = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-orchestrator', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-haiku-4.0', // Fast & cheap messages: [ { role: 'user', content: `Classify this request: "${userRequest}". Categories: code, creative, data, general. Reply with one word.` } ] }) });
const category = await classification.json();
// Choose model based on category const modelMap = { 'code': 'anthropic/claude-sonnet-4.5', 'creative': 'openai/gpt-4o', 'data': 'google/gemini-2.5-pro-exp', 'general': 'anthropic/claude-haiku-4.0' };
const selectedModel = modelMap[category.choices[0].message.content.trim()];
// Execute with optimal model const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-orchestrator', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: selectedModel, messages: [{ role: 'user', content: userRequest }] }) });
return response.json();}Parallel AI Calls
Section titled “Parallel AI Calls”Execute multiple AI requests simultaneously:
async function parallelAnalysis(text: string) { const [summary, sentiment, keywords] = await Promise.all([ // Summarization fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-analyzer', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-haiku-4.0', messages: [ { role: 'user', content: `Summarize in one sentence: ${text}` } ] }) }).then(r => r.json()),
// Sentiment analysis fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-analyzer', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-haiku-4.0', messages: [ { role: 'user', content: `Sentiment (positive/negative/neutral): ${text}` } ] }) }).then(r => r.json()),
// Keyword extraction fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-analyzer', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-haiku-4.0', messages: [ { role: 'user', content: `Extract 5 keywords: ${text}` } ] }) }).then(r => r.json()) ]);
return { summary, sentiment, keywords };}Rate Limiting & Retry Logic
Section titled “Rate Limiting & Retry Logic”class HoodyAI { private apiKey: string; private baseURL = 'https://ai.hoody.icu/api/v1'; private maxRetries = 3;
constructor(containerName: string) { this.apiKey = `container-${containerName}`; }
async chat(messages: any[], model: string = 'anthropic/claude-sonnet-4.5') { let lastError;
for (let attempt = 0; attempt < this.maxRetries; attempt++) { try { const response = await fetch(`${this.baseURL}/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model, messages }) });
if (response.status === 429) { // Rate limited - exponential backoff const waitTime = Math.pow(2, attempt) * 1000; await new Promise(resolve => setTimeout(resolve, waitTime)); continue; }
if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); }
return await response.json();
} catch (error) { lastError = error; if (attempt < this.maxRetries - 1) { await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1))); } } }
throw lastError; }}
// Usageconst ai = new HoodyAI('production-api');const result = await ai.chat([ { role: 'user', content: 'Hello!' }]);Use Cases
Section titled “Use Cases”AI-Powered API Endpoint
Section titled “AI-Powered API Endpoint”Build a production API that uses AI without key exposure:
// hoody-exec script: api/analyze-code.ts (deploy via scripts/write)// @mode serverless// @cors reflective
const { code, language } = req.body;
const aiResponse = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-code-analyzer', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [ { role: 'system', content: 'You are a code review expert. Analyze code and provide constructive feedback.' }, { role: 'user', content: `Review this ${language} code:\n\n${code}` } ] })});
const analysis = await aiResponse.json();return { feedback: analysis.choices[0].message.content, language, timestamp: new Date().toISOString()};Accessible at:
https://{project}-{container}-exec-1.node-us.containers.hoody.icu/api/analyze-codeChatbot with Context
Section titled “Chatbot with Context”// Maintain conversation historyclass AIChatSession { private messages: any[] = []; private containerKey: string;
constructor(containerName: string) { this.containerKey = `container-${containerName}`; }
async send(userMessage: string) { // Add user message to history this.messages.push({ role: 'user', content: userMessage });
// Get AI response const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${this.containerKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: this.messages }) });
const data = await response.json(); const assistantMessage = data.choices[0].message;
// Add to history this.messages.push(assistantMessage);
return assistantMessage.content; }
reset() { this.messages = []; }}
// Usageconst chat = new AIChatSession('chatbot-prod');await chat.send('What is Hoody?');await chat.send('How does it work?'); // Has context from previous messageBest Practices
Section titled “Best Practices”Model Selection Strategy
Section titled “Model Selection Strategy”Use cheaper models for:
- Classification tasks
- Simple Q&A
- Keyword extraction
- Quick validations
const cheapModel = 'anthropic/claude-haiku-4.0'; // Fast & economicalUse expensive models for:
- Complex reasoning
- Code generation
- Creative writing
- Multi-step analysis
const powerModel = 'anthropic/claude-opus-4.1'; // Most capableError Handling
Section titled “Error Handling”Always handle AI errors gracefully:
async function safeAICall(prompt: string) { try { const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-app', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [{ role: 'user', content: prompt }] }) });
if (!response.ok) { // Log error for monitoring console.error('AI Error:', response.status, await response.text()); return { error: 'AI service unavailable' }; }
return await response.json();
} catch (error) { console.error('Network error:', error); return { error: 'Network error' }; }}Streaming for Better UX
Section titled “Streaming for Better UX”Always use streaming for user-facing applications:
const response = await fetch('https://ai.hoody.icu/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer container-frontend', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'anthropic/claude-sonnet-4.5', messages: [{ role: 'user', content: prompt }], stream: true // Enable streaming })});Users see results as they’re generated instead of waiting for complete response.
What’s Next
Section titled “What’s Next”- Security Model → - Understand key-less security
- Models → - Browse all available models