Skip to content
Hoody.com

Hoody AI requests are ordinary HTTP calls, so you can put hoody-exec in front of the gateway as a MITM (Man-In-The-Middle) proxy and read or rewrite every request and response.

Because the traffic is HTTP (see The HTTP Revolution), it is observable and modifiable the same way any other HTTP call is. AI requests carry nothing special at the transport layer.

A MITM script can log, transform, cache, or reroute every AI interaction in a few lines of JavaScript.

Deploy a MITM script once (see Deploy the MITM script below), then change the base URL in your AI client. The base_url swap shown in the next section is the on-demand toggle, not the whole setup.

Without MITM: https://ai.hoody.com/api/v1
With MITM: https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1
Switching between them is a base URL change.

Turning MITM on and off is a client setting, not a code change: point the AI client’s base URL at hoody-exec instead of at the gateway.

hoody-agent uses Hoody AI automatically. The AI gateway (base URL, key, model) is configured on the session or agent, not passed per request. To route the agent through your MITM proxy, point its configured AI base URL at hoody-exec:

  • Normal Hoody AI: https://ai.hoody.com/api/v1
  • With MITM enabled: https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1

Then dispatch turns exactly as before; only the configured base URL changed:

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{node}.containers.hoody.com/api/v1/agent/sessions/{sessionId}/prompt:sync" \
-d '{
"text": "Build an app"
}'

Everything else stays the same.

To test with MITM, point the client at the hoody-exec URL; to bypass it, point back at https://ai.hoody.com/api/v1. Neither direction needs a redeploy or a config file edit.


A typical AI integration is a black box: you send a prompt and get a response, and everything in between is hidden.

With Hoody’s HTTP architecture:

  • Each AI request is a visible HTTP call
  • Responses flow back through your infrastructure
  • Tool calls arrive as JSON you can inspect and modify
  • Agent decisions are HTTP endpoints you can intercept

Your code can sit anywhere in that path. It can log requests, hold them for human approval, transform prompts, cache responses, route to different models, chain agents together, replace tool calls, and inject context.

Observability:

  • Log every prompt and response for debugging
  • Track token usage per project automatically
  • Analyze AI decision patterns
  • Monitor for prompt injection attempts
  • Build audit trails for compliance

Human-in-the-loop review:

  • Intercept high-stakes decisions for human approval
  • Pause AI execution for review before deployment
  • Add confirmation steps for sensitive operations
  • Let the AI draft and leave the decision to a person

Cost optimization:

  • Compress prompts to reduce token usage (20-40% savings)
  • Cache responses to eliminate duplicate calls (100% on cache hits)
  • Route to cheaper models for simple tasks (40-70% savings)
  • Auto-optimize based on complexity analysis

Prompt and response enrichment:

  • Add context from your knowledge base automatically
  • Inject custom instructions per use case
  • Transform responses to match your style
  • Chain multiple AI calls

Tool call manipulation:

  • Intercept and modify AI tool calls before execution
  • Add safety checks to file operations
  • Reroute dangerous commands to sandbox
  • Replace file paths, command arguments, or entire operations
  • Log all tool usage for audit trails

Agent orchestration:

  • Cascade AI requests across multiple agent instances
  • Coordinate multi-agent workflows via HTTP
  • Distribute tasks across agent swarms
  • Build self-improving agent networks

The basic pattern for an AI MITM proxy built on hoody-exec:

scripts/default/1/api/v1/[...path].js
// This catch-all route handles /api/v1/* (matching OpenAI API structure)
// @mode worker
// @log-level standard
// Handle all /api/v1/* endpoints (chat/completions, embeddings, images, etc.)
const apiPath = metadata.parameters.path.join('/'); // e.g., "chat/completions"
const response = await fetch(`https://ai.hoody.com/api/v1/${apiPath}`, {
method: req.method,
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: req.method === 'POST' ? JSON.stringify(req.body) : undefined
});
const data = await response.json();
// YOUR CUSTOM LOGIC HERE
// - Modify prompts
// - Add context
// - Check cache
// - Log for audit
// - Request human approval
// - Optimize model selection
// - Intercept tool calls
// - Trigger other agents
return res.json(data);

Option 1: catch-all route (recommended, handles all AI endpoints)

/hoody/storage/hoody-exec/scripts/default/1/api/v1/[...path].js

This handles:

  • POST /api/v1/chat/completions
  • POST /api/v1/embeddings
  • GET /api/v1/models
  • Any other OpenAI-compatible endpoint

Option 2: specific endpoint (for targeted control)

/hoody/storage/hoody-exec/scripts/default/1/api/v1/chat/completions.js

This only handles POST /api/v1/chat/completions

Accessing your MITM proxy:

https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1/chat/completions

How to use:

  1. Deploy the script (see deployment section below)
  2. Change base URL in your AI client:
    • Normal: https://ai.hoody.com/api/v1
    • With MITM: https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1
  3. All requests now flow through your MITM proxy.

Toggle between the two URLs to enable or disable MITM; the client code does not change.

Prerequisite: container identity token. The examples below use Bearer container-1. Hoody-minted containers are reachable under both a name-derived form (container-<name>) and a numbered form (container-<N>). Replace container-1 with the identifier that matches the container running the script; both forms are equivalent identity tokens, not copyable API keys.

Terminal window
# Deploy the catch-all MITM proxy (handles all /api/v1/* endpoints)
curl -X PUT "https://PROJECT_ID-CONTAINER_ID-files-1.node-us.containers.hoody.com/api/v1/files/hoody/storage/hoody-exec/scripts/default/1/api/v1/%5B...path%5D.js" \
-H "Content-Type: application/octet-stream" \
--data-binary @- << 'EOF'
// File: scripts/default/1/api/v1/[...path].js
// Catch-all MITM proxy for all OpenAI-compatible endpoints
// @mode worker
// @log-level standard
// Handle all /api/v1/* endpoints
const apiPath = metadata.parameters.path.join('/');
const response = await fetch(`https://ai.hoody.com/api/v1/${apiPath}`, {
method: req.method,
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: req.method === 'POST' ? JSON.stringify(req.body) : undefined
});
const data = await response.json();
// YOUR MITM LOGIC HERE
// Example: Log all requests
console.log(`AI Request: ${req.method} /api/v1/${apiPath}`);
console.log(`Model: ${req.body?.model || 'N/A'}`);
console.log(`Tokens: ${data.usage?.total_tokens || 'N/A'}`);
return res.json(data);
EOF

The proxy is now live at:

https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1/chat/completions
Section titled “Deploy with the hoody-exec scripts API (recommended)”
Terminal window
# Create the script using hoody-exec's script management API
curl -X POST "https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1/exec/scripts/write" \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"path": "default/1/api/v1/[...path].js",
"content": "// @mode worker\n// @log-level standard\n\nconst apiPath = metadata.parameters.path.join('/');\n\nconst response = await fetch(`https://ai.hoody.com/api/v1/${apiPath}`, {\n method: req.method,\n headers: {\n 'Authorization': 'Bearer container-1',\n 'Content-Type': 'application/json'\n },\n body: req.method === 'POST' ? JSON.stringify(req.body) : undefined\n});\n\nconst data = await response.json();\nconsole.log(`AI Request: ${req.method} /api/v1/${apiPath}`);\n\nreturn res.json(data);"
}
EOF
Terminal window
# Test your MITM proxy
curl -X POST "https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1/chat/completions" \
-H "Authorization: Bearer container-1" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-haiku-4.0",
"messages": [{"role": "user", "content": "Hello!"}]
}'

A completion response plus log output confirms the proxy is in the path.


Stop AI from executing high-stakes operations without human approval:

// @mode worker
// @log-level standard
const lastMessage = req.body.messages[req.body.messages.length - 1].content;
// Detect high-stakes operations
const isHighStakes = /deploy|delete|drop|production|payment|transfer/.test(
lastMessage.toLowerCase()
);
if (isHighStakes) {
// Store request for approval workflow
const requestId = crypto.randomUUID();
// Send notification to human via hoody-notifications
await fetch('https://PROJECT_ID-CONTAINER_ID-n-1.node-us.containers.hoody.com/api/v1/notifications/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: ':1',
summary: 'AI Needs Approval',
body: `High-stakes operation detected:\n${lastMessage}\nRequest ID: ${requestId}`,
urgency: 'critical'
})
});
if (!shared.pendingApprovals) shared.pendingApprovals = new Map();
shared.pendingApprovals.set(requestId, req.body);
return res.json({
status: 'pending_approval',
requestId,
message: 'High-stakes operation detected. Awaiting human approval.',
estimatedWait: '2-10 minutes'
});
}
// Normal flow for safe operations
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
return res.json(await response.json());

Agents keep working on their own for routine requests, and the operations matched by the pattern above stop for review. That puts you in the approval path rather than the execution path.

With dozens of agents running across your containers, your work becomes answering the requests they raise: deploy to production, delete this database. You confirm; they execute.

AI agents act on the world through tool calls: file operations, command execution, and so on. A MITM script can rewrite those tool calls before the client executes them.

Redirect file operations to sandbox:

// @mode worker
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
// Intercept tool calls before they execute
if (data.choices[0].message.tool_calls) {
data.choices[0].message.tool_calls = data.choices[0].message.tool_calls.map(call => {
// Redirect dangerous file operations to sandbox
if (call.function.name === 'write_file') {
const args = JSON.parse(call.function.arguments);
// Force all writes into /sandbox/ directory
if (!args.path.startsWith('/sandbox/')) {
args.path = '/sandbox' + args.path;
call.function.arguments = JSON.stringify(args);
}
}
// Add safety checks to delete operations
if (call.function.name === 'delete_file') {
const args = JSON.parse(call.function.arguments);
// Prevent deletion of critical files
if (args.path.match(/config|production|\.env|package\.json/)) {
// Replace with confirmation tool
call.function.name = 'confirm_delete';
call.function.arguments = JSON.stringify({
...args,
warning: 'Critical file deletion requires confirmation'
});
}
}
// Intercept command execution
if (call.function.name === 'execute_command') {
const args = JSON.parse(call.function.arguments);
// Block or modify dangerous commands
if (args.command.match(/rm -rf|sudo|chmod 777/)) {
call.function.name = 'blocked_command';
call.function.arguments = JSON.stringify({
original: args.command,
reason: 'Dangerous command intercepted'
});
}
}
return call;
});
}
return res.json(data);

Net effect:

  • The AI can code freely, but file writes are rewritten into the sandbox
  • Dangerous operations require explicit confirmation
  • Critical files are protected from accidental deletion
  • Command injection is prevented

The agent still picks its own tool calls; the proxy decides what those calls are allowed to reach. The script above is about 50 lines.

Because every service is HTTP, a MITM script can trigger other agents while it handles a request.

Multi-agent coordination:

// @mode worker
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
const aiResponse = data.choices[0].message.content;
// Detect when AI wants to delegate work
if (aiResponse.includes('DELEGATE:')) {
const taskMatch = aiResponse.match(/DELEGATE: (.+)/);
const delegatedTask = taskMatch[1];
// Cascade to another hoody-agent via HTTP (one-shot headless run)
const agentResponse = await fetch(
'https://PROJECT_ID-CONTAINER_ID-agent-2.node-us.containers.hoody.com/api/v1/agent/headless/runs',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: delegatedTask,
model: 'anthropic/claude-sonnet-4.5'
})
}
);
const agentData = await agentResponse.json();
// Modify response to indicate delegation
data.choices[0].message.content =
`Task delegated to Agent-2: ${delegatedTask}\n` +
`Job ID: ${agentData.job_id}\n` +
`Status: In progress...`;
}
// Detect when AI needs specialized capabilities
if (aiResponse.includes('ANALYZE_CODE:')) {
// Trigger code analysis agent
await fetch('https://PROJECT_ID-CONTAINER_ID-agent-1.node-us.containers.hoody.com/api/v1/agent/headless/runs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'Analyze codebase for security issues'
})
});
}
return res.json(data);

What this enables:

  • Agent swarms: one agent spawns and coordinates ten others
  • Specialized agents: route tasks to expert agents (code, security, design)
  • Parallel execution: distribute work across several agents at once
  • Self-organizing systems: agents discover and coordinate with each other

Example: you ask Agent A to “build a complete SaaS app”. Agent A analyzes, then cascades to:

  • Agent B (frontend specialist)
  • Agent C (backend specialist)
  • Agent D (database specialist)
  • Agent E (security auditor)

All of them coordinate over HTTP and report back, orchestrated from one MITM script.

Pause the AI request until a person reviews and approves it.

// @mode worker
// @log-level standard
// Initialize shared state
if (!shared.pendingRequests) {
shared.pendingRequests = new Map();
}
if (req.body.urgent === true) {
const requestId = crypto.randomUUID();
// Store request
shared.pendingRequests.set(requestId, {
request: req.body,
timestamp: Date.now(),
status: 'pending'
});
// Notify human via hoody-notifications
await fetch('https://PROJECT_ID-CONTAINER_ID-n-1.node-us.containers.hoody.com/api/v1/notifications/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: ':1',
summary: 'AI Awaiting Approval',
body: `${req.body.messages[req.body.messages.length - 1].content}\nApprove: /api/approve?id=${requestId} — Reject: /api/reject?id=${requestId}`,
urgency: 'critical'
})
});
// Poll for approval (or use webhook callback)
for (let i = 0; i < 300; i++) { // 5 minutes max
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
const request = shared.pendingRequests.get(requestId);
if (request.status === 'approved') {
break;
} else if (request.status === 'rejected') {
return res.status(403).json({ error: 'Request rejected by human' });
}
}
// Timeout if no response
if (shared.pendingRequests.get(requestId).status === 'pending') {
return res.status(408).json({ error: 'Approval timeout' });
}
}
// Proceed with AI request
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
return res.json(await response.json());

Sequence:

  1. AI agent wants to deploy to production
  2. MITM detects high-stakes operation
  3. Notification sent to the container’s display
  4. AI request pauses (stalls)
  5. You review and approve/reject
  6. AI continues or stops based on your decision

Dozens of agents can run at once while you approve only the decisions that need a person.

A tool call can be replaced outright, so the operation the agent asked for is not the operation that runs.

Example: route every file write through version control:

// @mode worker
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
// Intercept and replace tool calls
if (data.choices[0].message.tool_calls) {
for (const call of data.choices[0].message.tool_calls) {
// Replace write_file with version-controlled write
if (call.function.name === 'write_file') {
const args = JSON.parse(call.function.arguments);
// Create git commit for this change
await fetch('https://PROJECT_ID-CONTAINER_ID-terminal-1.node-us.containers.hoody.com/api/v1/terminal/execute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
command: `git add ${args.path} && git commit -m "AI: ${args.description || 'auto-save'}"`
})
});
// Modify the tool call to include git metadata
call.function.arguments = JSON.stringify({
...args,
git_tracked: true,
commit_message: `AI: ${args.description || 'auto-save'}`
});
}
// Replace read_file to inject AI-generated documentation
if (call.function.name === 'read_file') {
const args = JSON.parse(call.function.arguments);
// Read actual file via hoody-files
const fileResponse = await fetch(
`https://PROJECT_ID-CONTAINER_ID-files-1.node-us.containers.hoody.com/api/v1/files${args.path}`,
{ method: 'GET' }
);
const fileContent = await fileResponse.text();
// Ask AI to add inline documentation
const docResponse = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'anthropic/claude-haiku-4.0',
messages: [{
role: 'user',
content: `Add inline documentation to this code:\n${fileContent}`
}]
})
});
const documented = await docResponse.json();
// Return documented version instead
call.function.arguments = JSON.stringify({
...args,
enhanced: true,
content: documented.choices[0].message.content
});
}
}
}
return res.json(data);

Result:

  • Every file write is version controlled
  • Every file read comes back with AI-generated documentation
  • The agent sees the annotated code context
  • You get a full audit trail of the changes

The agent sees no difference. The tool call it issued still returns, but it now runs against version-controlled writes and annotated reads.

Route the simpler requests to cheaper models:

// @mode worker
const lastMessage = req.body.messages[req.body.messages.length - 1].content;
// Analyze complexity
const wordCount = lastMessage.split(/\s+/).length;
const hasCode = /```|function|class|import|async|await/.test(lastMessage);
const hasMultiStep = /step|then|after|finally|workflow/.test(lastMessage);
const isDeployment = /deploy|production|release/.test(lastMessage);
// Intelligent model selection
let selectedModel = req.body.model;
if (isDeployment) {
// Critical operations get best model
selectedModel = 'anthropic/claude-opus-4.1';
} else if (wordCount < 50 && !hasCode && !hasMultiStep) {
// Simple question → cheapest model
selectedModel = 'anthropic/claude-haiku-4.0';
} else if (hasCode || hasMultiStep) {
// Complex reasoning → balanced model
selectedModel = 'anthropic/claude-sonnet-4.5'; // $3.00/M tokens
} else {
// General tasks → fast model
selectedModel = 'openai/gpt-4o'; // $2.50/M tokens
}
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify({
...req.body,
model: selectedModel // Override with optimal model
})
});
return res.json(await response.json());

Savings: 40-70% when cheaper models handle the simpler requests. Simple tasks do not need an expensive model.

Add your own documentation to every prompt:

// @mode worker
// Modules auto-installed on first require
const { createClient } = require('@supabase/supabase-js');
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_KEY
);
const userPrompt = req.body.messages[req.body.messages.length - 1].content;
// Semantic search in your knowledge base
const { data: context } = await supabase
.from('documentation')
.select('content, source, relevance')
.textSearch('content', userPrompt)
.order('relevance', { ascending: false })
.limit(3);
// Inject context into system prompt
const enhancedMessages = [
{
role: 'system',
content: `You have access to our internal knowledge base. Relevant context for this request:\n\n${
context.map(c => `**${c.source}**:\n${c.content}`).join('\n\n')
}\n\nUse this context to provide accurate, company-specific answers.`
},
...req.body.messages
];
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify({
...req.body,
messages: enhancedMessages
})
});
return res.json(await response.json());

Result: each request carries context retrieved from your own store at call time, whether that store holds documentation, internal wikis, company policies, or codebase notes. The retrieval runs inside the MITM script, so there is no separate RAG service to operate.

Serve repeat requests from cache:

// @mode worker
const { createClient } = require('@supabase/supabase-js');
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY);
// Create cache key from request
const cacheKey = JSON.stringify({
model: req.body.model,
messages: req.body.messages
});
// Check cache (using hoody-sqlite for persistence)
const { data: cached } = await supabase
.from('ai_cache')
.select('response')
.eq('cache_key', cacheKey)
.single();
if (cached) {
return res.json({
...cached.response,
cached: true,
savings: '100% (from cache)'
});
}
// Call AI
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
// Store in cache
await supabase
.from('ai_cache')
.insert({
cache_key: cacheKey,
response: data,
created_at: new Date().toISOString()
});
return res.json(data);

Savings: a cache hit makes no upstream call, so it costs nothing. Useful for:

  • Repeated questions (documentation, support)
  • Code reviews (similar code patterns)
  • Content generation (similar prompts)

Strip filler before forwarding the prompt:

// @mode worker
function compressPrompt(text) {
return text
.replace(/\s+/g, ' ') // Normalize whitespace
.replace(/\b(the|a|an)\b/gi, '') // Remove articles
.replace(/\b(please|kindly|could you)\b/gi, '') // Remove pleasantries
.trim();
}
// Compress verbose prompts
const compressedMessages = req.body.messages.map(msg => ({
...msg,
content: compressPrompt(msg.content)
}));
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify({
...req.body,
messages: compressedMessages
})
});
return res.json(await response.json());

Savings: 20-40% on verbose inputs, without changing what the prompt means.


Write every call to a log table:

// @mode worker
const { createClient } = require('@supabase/supabase-js');
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY);
const requestId = crypto.randomUUID();
const startTime = Date.now();
// Log request
await supabase.from('ai_logs').insert({
request_id: requestId,
container: metadata.executionId,
model: req.body.model,
prompt: req.body.messages[req.body.messages.length - 1].content,
timestamp: new Date().toISOString()
});
// Make AI request
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
const duration = Date.now() - startTime;
// Log response
await supabase.from('ai_logs').update({
response: data.choices[0].message.content,
tokens_used: data.usage?.total_tokens,
duration_ms: duration,
cost: (data.usage?.total_tokens || 0) * 0.000003 // Example cost calculation
}).eq('request_id', requestId);
return res.json(data);

This gives you:

  • A full audit trail of AI interactions
  • Token usage per container and project
  • Cost tracking
  • Request latency
  • Records for a compliance review

Fall back to your own vendor keys when the gateway fails:

// @mode worker
// Try Hoody AI first
let response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
// Fallback to direct OpenAI if Hoody AI fails
if (!response.ok && response.status >= 500) {
response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
}
// Fallback to Anthropic if OpenAI fails
if (!response.ok && response.status >= 500) {
response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'x-api-key': process.env.ANTHROPIC_KEY,
'anthropic-version': '2023-06-01',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: req.body.model.replace('anthropic/', ''),
max_tokens: req.body.max_tokens || 1024,
messages: req.body.messages
})
});
}
return res.json(await response.json());

Resilience: a 5xx from one provider moves the request to the next one in the chain.

Append a plain-language explanation to generated code:

// @mode worker
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
let content = data.choices[0].message.content;
// Detect code blocks
if (content.includes('```')) {
// Ask another AI to explain the code
const explanation = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'anthropic/claude-haiku-4.0', // Cheap model for simple task
messages: [{
role: 'user',
content: `Explain this code in simple terms:\n${content}`
}]
})
});
const explainData = await explanation.json();
// Append explanation
content += '\n\n**How this works:**\n' + explainData.choices[0].message.content;
data.choices[0].message.content = content;
}
return data;

Raise desktop notifications about AI activity on a container display with hoody-notifications:

// @mode worker
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
// Detect significant events
const aiResponse = data.choices[0].message.content;
const isCodeGeneration = aiResponse.includes('```') && aiResponse.length > 500;
const isError = data.error || data.choices[0].finish_reason === 'error';
if (isCodeGeneration) {
// Notify about large code generation
await fetch('https://PROJECT_ID-CONTAINER_ID-n-1.node-us.containers.hoody.com/api/v1/notifications/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: ':1',
summary: 'AI Generated Code',
body: `AI just wrote ${aiResponse.length} characters of code`,
urgency: 'normal',
icon: 'code'
})
});
}
if (isError) {
// Alert about AI errors
await fetch('https://PROJECT_ID-CONTAINER_ID-n-1.node-us.containers.hoody.com/api/v1/notifications/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: ':1',
summary: 'AI Request Failed',
body: data.error?.message || 'Unknown error',
urgency: 'critical',
icon: 'warning'
})
});
}
// Track token usage and alert on threshold
if (data.usage?.total_tokens > 50000) {
await fetch('https://PROJECT_ID-CONTAINER_ID-n-1.node-us.containers.hoody.com/api/v1/notifications/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: ':1',
summary: 'High Token Usage',
body: `Request used ${data.usage.total_tokens} tokens`,
urgency: 'normal'
})
});
}
return res.json(data);

What this covers:

  • Notification when the AI generates a large amount of code
  • Alerts on AI errors or rate limits
  • High token usage, reported as it happens
  • Agent activity visible from any open display session
  • Confirmation when a critical operation completes

Alerts land on the container displays you already have open, so nothing has to sit and watch the logs.

Store every AI interaction in a database, using Bun’s built-in SQLite under /hoody/databases/ for concurrent-write safety:

// @mode worker
// Use Bun's built-in sqlite3 (no npm install needed with Bun)
const { Database } = require('bun:sqlite');
// A database in /hoody/databases/ is concurrent-write safe: the SQLite Drive
// FUSE mount coordinates writes and prevents corruption from concurrent writers
const db = new Database('/hoody/databases/ai-history.db');
// Create table on first run
if (!shared.initialized) {
db.run(`
CREATE TABLE IF NOT EXISTS prompts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
container TEXT,
model TEXT,
prompt TEXT,
response TEXT,
tokens INTEGER,
cost REAL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
db.run('CREATE INDEX IF NOT EXISTS idx_timestamp ON prompts(timestamp DESC)');
db.run('CREATE INDEX IF NOT EXISTS idx_model ON prompts(model)');
db.run('CREATE INDEX IF NOT EXISTS idx_container ON prompts(container)');
shared.initialized = true;
}
// Make AI request
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer container-1',
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
const data = await response.json();
// Store complete interaction in database (concurrent-write safe)
db.run(`
INSERT INTO prompts (timestamp, container, model, prompt, response, tokens, cost)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, [
new Date().toISOString(),
metadata.executionId || 'default',
req.body.model,
req.body.messages[req.body.messages.length - 1].content,
data.choices[0].message.content,
data.usage?.total_tokens || 0,
(data.usage?.total_tokens || 0) * 0.000003 // Example cost calc
]);
return res.json(data);

Why /hoody/databases/ matters here:

  • Multiple containers can log simultaneously without corruption
  • AI agents making parallel requests all write safely
  • FUSE mount coordinates writes automatically
  • Zero locking errors even under heavy concurrent load

See: SQLite Drive for full details on concurrent-write safety.

Query your AI history:

Terminal window
# View recent prompts
bun -e 'const db = require("bun:sqlite").Database("/hoody/databases/ai-history.db");
console.log(db.query("SELECT model, prompt, tokens FROM prompts ORDER BY created_at DESC LIMIT 10").all())'
# Total tokens used per model
bun -e 'const db = require("bun:sqlite").Database("/hoody/databases/ai-history.db");
console.log(db.query("SELECT model, SUM(tokens) as total FROM prompts GROUP BY model").all())'
# Most expensive queries
bun -e 'const db = require("bun:sqlite").Database("/hoody/databases/ai-history.db");
console.log(db.query("SELECT prompt, cost FROM prompts ORDER BY cost DESC LIMIT 5").all())'
# Usage by container
bun -e 'const db = require("bun:sqlite").Database("/hoody/databases/ai-history.db");
console.log(db.query("SELECT container, COUNT(*) as requests, SUM(tokens) as tokens FROM prompts GROUP BY container").all())'

What the history is good for:

  • Audit trails: a complete record of AI interactions
  • Cost analytics: spending by model, container, and time period
  • Pattern analysis: frequently repeated prompts worth caching
  • Debugging: the exact prompt and response behind an issue
  • Compliance: detailed logs for regulatory requirements
  • Training data: prompt history as a corpus for fine-tuning

The script runs on your infrastructure, so nothing forces the upstream to be Hoody AI.

// @mode worker
// Route to OpenAI directly
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(req.body)
});
return res.json(await response.json());
// Or use any other provider:
// - Anthropic directly
// - Together AI
// - Your own self-hosted models (Ollama, LM Studio)
// - Multiple providers with custom routing logic

You decide:

  • Which provider for which tasks
  • When to use Hoody AI vs your own keys
  • How to distribute load
  • Where costs should go

Let the AI generate whole applications, with guardrails around what it can touch:

// Sandbox all AI file operations
if (call.function.name === 'write_file') {
args.path = '/sandbox' + args.path;
}
// Block dangerous commands
if (call.function.name === 'execute_command') {
if (args.command.match(/rm -rf|sudo|chmod 777/)) {
return blocked();
}
}

Each customer’s AI access runs through the same proxy:

const customer = getCustomerFromContainer(metadata.parameters.tenant);
// Customer-specific quota enforcement
if (customer.tokensUsedToday > customer.quota) {
return res.status(429).json({ error: 'Quota exceeded' });
}
// Customer-specific model restrictions
if (!customer.allowedModels.includes(req.body.model)) {
req.body.model = customer.defaultModel;
}

Different MITM rules for development and production:

// Development: Log everything, use cheap models
// (pass ?env=dev / ?env=prod — surfaced via metadata.parameters)
if (metadata.parameters.env === 'dev') {
console.log('Request:', req.body);
req.body.model = 'anthropic/claude-haiku-4.0';
}
// Production: Route to best model, alert on errors
if (metadata.parameters.env === 'prod') {
req.body.model = 'anthropic/claude-opus-4.1';
// monitorForErrors() implementation
}

Chain several MITM proxies rather than doing everything in one script:

App → MITM Layer 1 (logging) → MITM Layer 2 (caching) → MITM Layer 3 (model routing) → Hoody AI

Each layer does one thing, so you can add or remove a layer without touching the others.

Store caches, approval requests, logs in hoody-sqlite:

// Persistent cache across restarts
await fetch('https://PROJECT_ID-CONTAINER_ID-sqlite-1.node-us.containers.hoody.com/api/v1/sqlite/kv/batch/set?db=ai-cache.db', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
items: [{ key: cacheKey, value: aiResponse }]
})
});

A MITM proxy adds latency to every call. Measure it:

const start = Date.now();
const response = await fetch('https://ai.hoody.com/api/v1/chat/completions', { /* ... */ });
const latency = Date.now() - start;
if (latency > 1000) {
console.warn('MITM proxy slow:', latency, 'ms');
}
  1. Log requests.
  2. Add caching.
  3. Add model routing.
  4. Add human approval for high-stakes operations.
  5. Add the agent cascade.

Problem: Requests bypass your proxy

Solution: Ensure apps point to your hoody-exec endpoint:

https://PROJECT_ID-CONTAINER_ID-exec-1.node-us.containers.hoody.com/api/v1
NOT: https://ai.hoody.com/api/v1

Problem: Modifications to tool_calls don’t take effect

Solution: Return the modified data before the tool executes:

// Correct: Modify in response, before tool execution
data.choices[0].message.tool_calls = modified;
return res.json(data);
// Wrong: Trying to modify after execution

Problem: Cached responses are stale

Solution: Add cache invalidation:

const cacheKey = `${model}:${JSON.stringify(messages)}:${Math.floor(Date.now() / 3600000)}`;
// Key changes every hour, auto-invalidates

Problem: Stalled requests time out before a person responds

Solution: Increase timeout or implement webhook callback:

// Webhook approach (better):
// 1. Store request
// 2. Send notification with callback URL
// 3. Return immediately with "pending" status
// 4. Human approves via webhook
// 5. Agent polls or receives event

Build a proxy:

Related concepts: