Files
hermes-agent-mission-control/src/app/api/agent-chat/route.ts
T
sharbelxyzandClaude Opus 4.8 b463027468 Hermy HQ: self-hostable mission-control template for your Hermes agent
A Next.js 16 + Prisma/Postgres dashboard that pairs with a local Hermes
agent over a Postgres message bus: dispatch work, approve side-effecting
actions, browse the agent's memory, and watch it run. Ships with an
agent-onboarding prompt (ONBOARDING.md) so your Hermes can install it for
you step by step. All secrets are env-configured; nothing sensitive is
bundled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 09:33:24 +02:00

108 lines
3.5 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
interface AgentChatRequest {
agentId: string;
message: string;
history?: Array<{ role: 'user' | 'assistant'; content: string }>;
}
interface AgentChatResponse {
reply: string;
agentId: string;
}
const AGENT_PROMPTS: Record<string, string> = {
max: "You are Max 🐺, an AI executive assistant and COO-level strategist helping the user run their business. The user is a founder and content creator who runs AI trading bots. Be sharp, concise, strategic. Give real actionable advice.",
sage: "You are Sage 🌿, X/Twitter content specialist for the user. You write viral tweets in their voice — conversational, sharp, specific. Focus on hooks that make people stop scrolling. No fluff.",
knox: "You are Knox 🔐, operations and trading analyst for the user. You analyze Polymarket and Hyperliquid trading performance, spot patterns, suggest strategy improvements. Be data-driven and direct.",
nova: "You are Nova ⭐, YouTube strategy specialist for the user. You write scripts, hooks, thumbnails, titles. Think Mr Beast structure applied to the user's niche.",
pixel: "You are Pixel 🎨, web app product specialist for the user's products. You find UX improvements, feature ideas, competitor gaps. Think product manager + growth hacker.",
};
export async function POST(request: NextRequest): Promise<NextResponse<AgentChatResponse | { error: string }>> {
try {
const body: AgentChatRequest = await request.json();
const { agentId, message, history = [] } = body;
// Validate inputs
if (!agentId || !message) {
return NextResponse.json(
{ error: 'Missing agentId or message' },
{ status: 400 }
);
}
if (!AGENT_PROMPTS[agentId]) {
return NextResponse.json(
{ error: `Unknown agent: ${agentId}` },
{ status: 400 }
);
}
const systemPrompt = AGENT_PROMPTS[agentId];
const apiKey = process.env.OPENROUTER_API_KEY;
if (!apiKey) {
console.error('OPENROUTER_API_KEY not configured');
return NextResponse.json(
{ error: 'API configuration error' },
{ status: 500 }
);
}
// Build messages array: system prompt + history + current message
const messages = [
...history,
{ role: 'user' as const, content: message },
];
// Call OpenRouter API
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'HTTP-Referer': 'https://your-app.vercel.app',
},
body: JSON.stringify({
model: 'anthropic/claude-haiku-4-5',
messages: [
{ role: 'system', content: systemPrompt },
...messages,
],
max_tokens: 800,
}),
});
if (!response.ok) {
const error = await response.text();
console.error('OpenRouter API error:', error);
return NextResponse.json(
{ error: 'Failed to get response from AI model' },
{ status: 500 }
);
}
const data = await response.json();
const reply = data.choices?.[0]?.message?.content || '';
if (!reply) {
return NextResponse.json(
{ error: 'No response from AI model' },
{ status: 500 }
);
}
return NextResponse.json({
reply,
agentId,
});
} catch (error) {
console.error('Agent chat error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}