# AI Agents Configuration: [Project Name] **AI Provider**: [OpenAI / Claude / Gemini / Cloudflare AI] **Framework**: [Vercel AI SDK / Custom / Cloudflare Workers AI] **Agent Architecture**: [Single agent / Multi-agent / Agentic workflows] **Last Updated**: [Date] --- ## Overview This document defines AI agents, their capabilities, tools, and workflows for this project. **Agent Philosophy**: - **Purpose-built agents** - Each agent has a specific, well-defined role - **Tool-equipped** - Agents have access to functions they need - **Conversational** - Agents can ask clarifying questions - **Stateful when needed** - Use Durable Objects for long-running conversations - **Fail gracefully** - Always have fallback responses --- ## AI Provider Configuration ### Primary Provider: [Provider Name] **Model**: [e.g., gpt-5, claude-sonnet-4-5, gemini-2.5-pro] **API Key**: Stored in environment variable `[KEY_NAME]` **Base URL**: [API endpoint] **Configuration**: ```typescript // src/lib/ai-config.ts export const aiConfig = { provider: '[provider]', model: '[model-name]', apiKey: process.env.[KEY_NAME], temperature: 0.7, maxTokens: 2000, topP: 1.0 } ``` **Fallback Provider** (optional): [Secondary provider if primary fails] --- ## Agents ### Agent 1: [Agent Name] **Purpose**: [What this agent does] **Model**: [Specific model if different from default] **Context Window**: [Token limit for this agent] **Capabilities**: - [Capability 1] - [Capability 2] - [Capability 3] **System Prompt**: ``` You are [agent role]. Your goal is to [agent purpose]. Guidelines: - [Guideline 1] - [Guideline 2] - [Guideline 3] When you need information you don't have: - Use available tools - Ask the user clarifying questions - Provide your best answer with caveats Response format: - Be concise and actionable - Use markdown for formatting - Include code examples when helpful ``` **Available Tools**: - `[tool_name]` - [Description] - `[tool_name]` - [Description] **Example Conversation**: ``` User: [Example input] Agent: [Example response] User: [Follow-up] Agent: [Agent uses tool and responds] ``` **Endpoint**: `POST /api/agents/[agent-name]` **Request**: ```json { "message": "User message", "conversationId": "optional-conversation-id", "context": { "optional": "context" } } ``` **Response** (streaming): ``` data: {"type":"text","content":"Agent response..."} data: {"type":"tool_call","name":"search","args":{"query":"..."}} data: {"type":"tool_result","result":{...}} data: {"type":"done"} ``` --- ### Agent 2: [Agent Name] **Purpose**: [What this agent does] [... repeat structure from Agent 1 ...] --- ## Tools (Functions) AI agents can call these functions to perform actions or retrieve information. ### Tool: `[tool_name]` **Purpose**: [What this tool does] **Parameters**: ```typescript { param1: string, // Description param2: number, // Description param3?: boolean // Optional description } ``` **Implementation**: ```typescript // src/lib/ai-tools.ts export async function [tool_name](params: ToolParams, context: Context) { // Tool logic const result = await performAction(params) return result } ``` **Example**: ```typescript // Agent calls tool const result = await [tool_name]({ param1: "value", param2: 42 }) // Tool returns { success: true, data: { /* result */ } } ``` **Failure Handling**: [How tool handles errors] --- ### Tool: `search_database` **Purpose**: Search the database for user-specific information **Parameters**: ```typescript { query: string, // Natural language search query table: string, // Which table to search limit?: number // Max results (default 5) } ``` **Implementation**: ```typescript export async function search_database( { query, table, limit = 5 }: SearchParams, context: Context ) { const userId = context.get('userId') // Convert natural language to SQL (simplified example) const results = await context.env.DB.prepare( `SELECT * FROM ${table} WHERE user_id = ? LIMIT ?` ).bind(userId, limit).all() return { success: true, data: results.results } } ``` --- ## Agent Workflows ### Workflow: [Workflow Name] **Purpose**: [What this workflow accomplishes] **Agents Involved**: 1. [Agent 1] - [Role in workflow] 2. [Agent 2] - [Role in workflow] **Flow**: ``` 1. User submits [input] ↓ 2. [Agent 1] analyzes input ↓ 3. [Agent 1] calls tool: [tool_name] ↓ 4. Tool returns data ↓ 5. [Agent 1] generates response ↓ 6. If needed: Hand off to [Agent 2] ↓ 7. [Agent 2] completes task ↓ 8. Return final result to user ``` **Example**: ``` User: "Find all high-priority tasks and create a summary report" [Planner Agent] → Calls search_database(query="high priority tasks") → Receives 5 tasks → Hands off to [Writer Agent] with task data [Writer Agent] → Generates formatted report → Returns markdown report to user ``` --- ## Conversation State ### Stateless Agents (Default) **When to use**: Single-turn interactions, no context needed **Implementation**: Each request is independent **Example**: Simple Q&A, content generation --- ### Stateful Agents (Durable Objects) **When to use**: Multi-turn conversations, context retention **Implementation**: Store conversation history in Durable Object **Setup**: ```typescript // src/durable-objects/conversation.ts export class Conversation implements DurableObject { private messages: Message[] = [] async fetch(request: Request) { const { message } = await request.json() // Add user message to history this.messages.push({ role: 'user', content: message }) // Call AI with full conversation history const response = await callAI({ messages: this.messages, tools: availableTools }) // Add assistant response to history this.messages.push({ role: 'assistant', content: response }) return new Response(JSON.stringify({ response })) } } ``` **Wrangler Config**: ```jsonc { "durable_objects": { "bindings": [ { "name": "CONVERSATIONS", "class_name": "Conversation", "script_name": "app" } ] } } ``` **Usage**: ```typescript // Create/get conversation const conversationId = crypto.randomUUID() const durableObjectId = env.CONVERSATIONS.idFromName(conversationId) const stub = env.CONVERSATIONS.get(durableObjectId) // Send message to conversation const response = await stub.fetch(request) ``` --- ## Streaming Responses **Why stream**: Better UX, appears faster, shows progress **Implementation** (Server-Sent Events): ```typescript // src/routes/agents.ts app.post('/api/agents/:agentName', async (c) => { const { message } = await c.req.json() const stream = await streamAIResponse({ message, agent: c.req.param('agentName') }) return c.newResponse(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' } }) }) ``` **Client** (Vercel AI SDK): ```typescript import { useChat } from '@ai-sdk/react' export function ChatInterface() { const { messages, input, handleInputChange, handleSubmit } = useChat({ api: '/api/agents/chat' }) return (
{messages.map(m => (
{m.content}
))}
) } ``` --- ## Prompt Engineering ### System Prompt Best Practices **Structure**: 1. **Role definition** - "You are a [role]" 2. **Capabilities** - What the agent can do 3. **Constraints** - What the agent cannot do 4. **Tone/style** - How the agent should respond 5. **Output format** - Markdown, JSON, etc **Example**: ``` You are a helpful task management assistant. Your capabilities: - Search user's tasks - Create, update, delete tasks - Generate task summaries and reports - Set reminders and priorities Your constraints: - Never access other users' data - Always confirm before deleting tasks - Ask for clarification if user intent is unclear Response style: - Be concise and actionable - Use bullet points for lists - Include task IDs for reference Output format: - Use markdown formatting - Bold important information - Use code blocks for task IDs ``` --- ## Token Management **Cost Optimization**: - Use smaller models for simple tasks (gpt-5-mini, claude-haiku-4-5) - Use larger models only when needed (gpt-5, claude-sonnet-4-5) - Limit conversation history (keep last N messages) - Summarize long conversations to reduce tokens **Token Budgets**: ```typescript const TOKEN_BUDGETS = { 'simple-qa': { model: 'gpt-5-mini', maxInputTokens: 500, maxOutputTokens: 500 }, 'complex-analysis': { model: 'gpt-5', maxInputTokens: 4000, maxOutputTokens: 2000 } } ``` --- ## Error Handling ### AI Provider Failures **Handle**: - Rate limits (retry with backoff) - API errors (fallback provider or error message) - Timeout (abort and inform user) **Example**: ```typescript try { const response = await callAI({ message, tools }) return response } catch (error) { if (error.code === 'rate_limit') { // Retry with exponential backoff await sleep(2000) return await callAI({ message, tools }) } else { // Return graceful error return { error: true, message: "I'm having trouble processing that right now. Please try again." } } } ``` --- ## Testing AI Agents ### Unit Tests (Tool Functions) Test each tool independently: ```typescript describe('search_database tool', () => { it('returns user-specific results', async () => { const result = await search_database({ query: 'high priority', table: 'tasks' }, mockContext) expect(result.success).toBe(true) expect(result.data.length).toBeGreaterThan(0) }) }) ``` --- ### Integration Tests (Agent Endpoints) Test agent responses: ```typescript describe('POST /api/agents/assistant', () => { it('responds to simple query', async () => { const res = await app.request('/api/agents/assistant', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token' }, body: JSON.stringify({ message: 'List my tasks' }) }) expect(res.status).toBe(200) const data = await res.json() expect(data.response).toContain('task') }) }) ``` --- ### Manual Testing **Test Prompts**: - Simple queries: "What tasks do I have?" - Tool usage: "Create a new task called 'Review PR'" - Edge cases: "Delete all my tasks" (should confirm first) - Unclear input: "Do the thing" (should ask for clarification) - Multi-step: "Find high-priority tasks and summarize them" --- ## Monitoring and Observability **Metrics to track**: - Agent invocations per day - Average response time - Token usage (input + output) - Tool call frequency - Error rate **Logging**: ```typescript console.log('[Agent]', { agent: 'assistant', userId: context.get('userId'), message: message.substring(0, 50), tokensUsed: response.usage.total_tokens, toolsCalled: toolCalls.map(t => t.name), responseTime: Date.now() - startTime }) ``` **Cloudflare Workers Analytics Engine** (optional): ```typescript await env.ANALYTICS.writeDataPoint({ indexes: [userId], doubles: [responseTime, tokensUsed], blobs: [agentName, toolsCalled] }) ``` --- ## Future Agent Enhancements - [ ] Add [agent name] for [purpose] - [ ] Integrate [tool name] for [capability] - [ ] Implement [workflow name] - [ ] Add voice input/output - [ ] Multi-modal support (images, files) --- ## Revision History **v1.0** ([Date]): Initial agent configuration **v1.1** ([Date]): [Changes made]