content/skills/ai-agent-integrator/SKILL.md
Build and integrate custom AI agents into websites and applications. Use this skill whenever someone wants to add an AI agent to their app, embed a chatbot that can also modify code or files on the backend, create a task-specific AI assistant within a product, build an agent with constrained outputs, set up dual-channel AI (text responses in chat + code changes on the server), integrate OpenAI/Anthropic/other LLM APIs into a web app, or design an agent system where the AI gives text answers to users but applies code modifications server-side. Also trigger when someone asks about agent configuration, system prompts for embedded agents, tool-calling architectures, streaming chat UIs, function calling with backend execution, or building AI copilot features into their product. This skill covers the full stack: frontend chat interface, backend agent orchestration, provider integration, agent customization, and the critical separation between what the user sees (text) and what the system does (code modifications).
npx skillsauth add rushyop/imperium-cli ai-agent-integratorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You build custom AI agents that live inside websites and applications. These aren't generic chatbots — they're purpose-built agents that do specific tasks and produce specific outputs, integrated directly into a product's architecture.
The core architectural principle: text goes to the chat, code goes to the backend. The user sees conversational responses in a chat interface. Behind the scenes, the agent can read, modify, and create code or data on the server. These are two separate output channels routed through one agent.
Every integration is different, so gather context before writing any code:
If any of these are unclear, ask the user. A well-scoped agent is dramatically more useful than a vaguely-defined one.
┌─────────────────────────────────────────────────────────────┐
│ FRONTEND (Chat UI) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Chat Input │───▶│ Message List │◀──│ Stream Reader │ │
│ └──────────────┘ └──────────────┘ └──────┬───────┘ │
│ │ │ │
│ ▼ │ │
│ POST /api/agent/chat ────────────────── SSE stream back │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ BACKEND (Agent Orchestration) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Agent Router │───▶│ LLM Provider │───▶│ Tool Executor │ │
│ │ (config + │ │ (OpenAI / │ │ (code mods, │ │
│ │ auth + rate │ │ Anthropic / │ │ file ops, │ │
│ │ limiting) │ │ local) │ │ DB queries) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ System Prompt Response Stream Side Effects │
│ (task scope) (text → chat) (code → backend) │
└─────────────────────────────────────────────────────────────┘
The flow:
Text is the user's interface. Code execution is the system's interface. The user never sees raw code output unless the agent is specifically designed to show it (like a coding assistant).
The right architecture depends on what the agent needs to do:
Start with the simplest approach that works. You can always add tool-calling later — ripping out an over-engineered agent system is painful.
Every agent needs a configuration that defines its identity, capabilities, and constraints. This lives on the backend — never expose agent configuration to the frontend.
interface AgentConfig {
// Identity
id: string;
name: string;
description: string;
// LLM settings
provider: 'openai' | 'anthropic' | 'local';
model: string;
systemPrompt: string;
temperature: number;
maxTokens: number;
// Capabilities — what tools this agent can use
tools: ToolDefinition[];
// Constraints — what this agent is NOT allowed to do
constraints: {
maxTurns: number; // prevent infinite loops
allowedPaths?: string[]; // file paths the agent can touch
blockedOperations?: string[]; // operations that require approval
rateLimitPerMinute: number; // cost control
requireApproval?: string[]; // tool names that need user confirmation
};
}
The system prompt is where you make the agent specific. A good system prompt:
→ For system prompt patterns and examples, read references/agent-config.md
The frontend's job is simple: send messages, display responses, and optionally show status updates when the agent is doing backend work.
The chat UI works with any frontend framework. The core pattern is the same — the differences are in component structure and state management.
→ For framework-specific implementations (React, Vue, Next.js, vanilla JS), read references/frontend-patterns.md
Always stream responses. Waiting for the full response before showing anything feels broken to users, especially when tool calls add latency.
SSE (Server-Sent Events) is the simplest streaming approach and works for most cases:
// Frontend: reading an SSE stream
const response = await fetch('/api/agent/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, conversationId }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// Parse SSE events and append text to the current message
}
Use WebSockets instead of SSE when you need bidirectional communication — for example, if the agent needs to push status updates or approval requests while it's still thinking.
The backend is where the real work happens. This is where the agent's personality lives, where tool calls execute, and where code modifications are applied.
Keep it clean. Most agents need just 2-3 endpoints:
POST /api/agent/chat → Main conversation endpoint (streaming response)
GET /api/agent/conversations → List past conversations (optional)
POST /api/agent/approve → User approves a pending operation (if using approval flow)
The core backend logic is a loop: call the LLM, check if it wants to use tools, execute tools if so, feed results back, repeat until the LLM produces a final text response.
async function handleAgentChat(message: string, conversationId: string, config: AgentConfig) {
const history = await loadConversation(conversationId);
history.push({ role: 'user', content: message });
while (true) {
const response = await callLLM(config, history);
if (response.type === 'text') {
// Final answer — stream this to the frontend
yield { type: 'text', content: response.content };
break;
}
if (response.type === 'tool_call') {
// Agent wants to do something — execute it on the backend
const toolResult = await executeToolCall(response.toolCall, config);
history.push({ role: 'assistant', content: response.raw });
history.push({ role: 'tool', content: toolResult });
// Loop continues — LLM will process the tool result
}
}
await saveConversation(conversationId, history);
}
Tools are how the agent interacts with the codebase and backend systems. Each tool is a function the agent can call, with defined inputs and outputs.
interface ToolDefinition {
name: string;
description: string; // Shown to the LLM so it knows when to use this tool
parameters: JSONSchema; // Input validation
requiresApproval: boolean; // Does the user need to confirm before execution?
execute: (params: any) => Promise<ToolResult>;
}
Common tool categories for code-modifying agents:
| Category | Example Tools | Risk Level |
|---|---|---|
| Read | readFile, searchCode, listDirectory, queryDatabase | Low |
| Write | editFile, createFile, runMigration | High — use approval |
| Execute | runCommand, runTests, deployPreview | High — use approval |
| Query | searchDocs, getAPIReference, checkStatus | Low |
→ For backend implementation patterns (Express, Fastify, Next.js API routes, etc.), read references/backend-patterns.md
The agent runs on your backend with your permissions. Treat every tool call as potentially hostile input:
config.constraints.allowedPaths). Path traversal (../../etc/passwd) must be caught.For operations that modify code or data, add a confirmation step:
editFile)src/config.ts — [Approve] [Reject]"This keeps humans in the loop for anything consequential. For read-only tools, skip approval — it would make the agent feel sluggish for no safety benefit.
The skill supports multiple LLM providers. The backend should abstract the provider so you can switch without touching the rest of the code.
→ For provider-specific integration (OpenAI, Anthropic, local models), read references/providers.md
The provider abstraction layer:
interface LLMProvider {
chat(messages: Message[], tools?: ToolDefinition[], config?: LLMConfig): AsyncIterable<StreamChunk>;
}
Each provider implements this interface. The agent orchestration code doesn't care which provider is behind it — it just calls chat() and processes the stream.
When integrating an agent into an existing app, go in this order:
/api/agent/chat route. Stream the LLM response as SSE events.AgentConfig object. Make the system prompt specific to the agent's task.Each step should be testable on its own. If step 2 doesn't work, there's no point building step 3.
The whole point of this architecture is that agents are narrow and good at their job, not broad and mediocre. Here's how to customize:
The system prompt is the strongest lever. It controls:
Don't give the agent every tool. A SQL assistant needs queryDatabase and listTables — not editFile or runCommand. Each tool you add is an attack surface and a source of confusion.
Choose the right memory strategy:
Window-based memory with N=20 is a solid starting point for most agents.
Before considering the integration done:
If any of these fail, fix them before moving on. A broken approval flow is a security issue, not a nice-to-have.
testing
Draft cold emails, warm intro blurbs, follow-ups, update emails, and investor communications for fundraising. Use when the user wants outreach to angels, VCs, strategic investors, or accelerators and needs concise, personalized, investor-facing messaging.
testing
Create and update pitch decks, one-pagers, investor memos, accelerator applications, financial models, and fundraising materials. Use when the user needs investor-facing documents, projections, use-of-funds tables, milestone plans, or materials that must stay internally consistent across multiple fundraising assets.
development
Codified expertise for demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation at multi-location retailers. Informed by demand planners with 15+ years experience managing hundreds of SKUs. Includes forecasting method selection, ABC/XYZ analysis, seasonal transition management, and vendor negotiation frameworks. Use when forecasting demand, setting safety stock, planning replenishment, managing promotions, or optimizing inventory levels.
development
A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).