Files
gh-jezweb-claude-skills-ski…/templates/AGENTS_CONFIG.md
2025-11-30 08:25:20 +08:00

12 KiB

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:

// 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:

{
  "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:

{
  param1: string,  // Description
  param2: number,  // Description
  param3?: boolean // Optional description
}

Implementation:

// src/lib/ai-tools.ts
export async function [tool_name](params: ToolParams, context: Context) {
  // Tool logic
  const result = await performAction(params)
  return result
}

Example:

// 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:

{
  query: string,      // Natural language search query
  table: string,      // Which table to search
  limit?: number      // Max results (default 5)
}

Implementation:

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:

// 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:

{
  "durable_objects": {
    "bindings": [
      {
        "name": "CONVERSATIONS",
        "class_name": "Conversation",
        "script_name": "app"
      }
    ]
  }
}

Usage:

// 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):

// 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):

import { useChat } from '@ai-sdk/react'

export function ChatInterface() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: '/api/agents/chat'
  })

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>{m.content}</div>
      ))}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
      </form>
    </div>
  )
}

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:

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:

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:

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:

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:

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):

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]