> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runflow.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Customer Support Agent with RAG

> Build a complete support agent with knowledge base search, tools, and business metrics

A complete customer support agent that searches your documentation, creates tickets, and tracks resolution metrics. This example shows the full project structure with separate files for tools and prompts.

## Project Structure

```
support-agent/
├── main.ts
├── agent.ts
├── tools/
│   ├── index.ts
│   ├── create-ticket.ts
│   └── search-orders.ts
├── prompts/
│   └── index.ts
├── .runflow/
│   └── rf.json
├── package.json
└── tsconfig.json
```

## Step 1: Define Your Prompt

Start with well-structured instructions that tell the agent how to behave, when to use tools, and how to respond.

```typescript prompts/index.ts theme={null}
export const supportPrompt = `You are a customer support agent for ACME Corp.

## Behavior
- Always be professional, empathetic, and solution-oriented
- Respond in the customer's language
- Search the knowledge base before answering technical questions
- If you don't know something, say so honestly — never guess

## Tools
- Use **search-orders** when customers ask about order status, delivery, or tracking
- Use **create-ticket** when:
  - The issue cannot be resolved in this conversation
  - The customer needs a refund or account change
  - Always confirm with the customer before creating a ticket
  - Set priority: 'high' if customer is blocked, 'medium' for inconveniences, 'low' for feature requests

## Knowledge Base
- The knowledge base contains product documentation, FAQs, and policies
- Always search it when customers ask about features, pricing, or processes
- Quote relevant information when answering

## Response Format
- Be concise (2-3 paragraphs max)
- Use bullet points for step-by-step instructions
- Always confirm actions taken ("I've created ticket #123 for you")
- End with a follow-up question when appropriate`;
```

## Step 2: Create Your Tools

Each tool lives in its own file with clear input validation and structured responses.

```typescript tools/search-orders.ts theme={null}
import { createTool } from '@runflow-ai/sdk';
import { z } from 'zod';

export const searchOrdersTool = createTool({
  id: 'search-orders',
  description: 'Search customer orders by order ID or customer email',
  inputSchema: z.object({
    orderId: z.string().optional().describe('Order ID (e.g., ORD-12345)'),
    customerEmail: z.string().email().optional().describe('Customer email'),
  }),
  execute: async (params, toolContext) => {
    try {
      // Example: query your database or API
      const response = await fetch(
        `https://api.yourcompany.com/orders?id=${params.orderId || ''}&email=${params.customerEmail || ''}`,
        { headers: { 'Authorization': `Bearer ${process.env.ORDERS_API_KEY}` } }
      );

      if (!response.ok) {
        return { found: false, error: 'Failed to search orders' };
      }

      const orders = await response.json();

      if (!orders.length) {
        return { found: false, query: params.orderId || params.customerEmail };
      }

      return {
        found: true,
        orders: orders.map((o: any) => ({
          id: o.id,
          status: o.status,
          total: o.total,
          createdAt: o.createdAt,
          estimatedDelivery: o.estimatedDelivery,
        })),
      };
    } catch (error) {
      return { found: false, error: 'Service temporarily unavailable' };
    }
  },
});
```

```typescript tools/create-ticket.ts theme={null}
import { createTool } from '@runflow-ai/sdk';
import { track } from '@runflow-ai/sdk/observability';
import { z } from 'zod';

export const createTicketTool = createTool({
  id: 'create-ticket',
  description: 'Create a support ticket for issues that need human follow-up',
  inputSchema: z.object({
    subject: z.string().describe('Brief description of the issue'),
    description: z.string().describe('Detailed description with context'),
    priority: z.enum(['low', 'medium', 'high']).describe('Issue priority'),
  }),
  execute: async (params, toolContext) => {
    try {
      // Example: create ticket via connector or API
      const ticket = await toolContext.connector('hubspot', 'create-ticket', {
        subject: params.subject,
        content: params.description,
        priority: params.priority,
      });

      // Track for business metrics
      track('ticket_created', {
        priority: params.priority,
        subject: params.subject,
      });

      return {
        success: true,
        ticketId: ticket.id,
        message: `Ticket ${ticket.id} created successfully`,
      };
    } catch (error) {
      return {
        success: false,
        error: 'Failed to create ticket. Please try again.',
      };
    }
  },
});
```

Re-export everything from an index file:

```typescript tools/index.ts theme={null}
export { searchOrdersTool } from './search-orders';
export { createTicketTool } from './create-ticket';
```

## Step 3: Configure the Agent

```typescript agent.ts theme={null}
import { Agent, openai } from '@runflow-ai/sdk';
import { supportPrompt } from './prompts';
import { searchOrdersTool, createTicketTool } from './tools';

export const supportAgent = new Agent({
  name: 'Customer Support',
  instructions: supportPrompt,
  model: openai('gpt-4o'),

  memory: {
    maxTurns: 20,
    summarizeAfter: 15,
    summarizePrompt: 'Summarize key issues, actions taken, and pending items',
  },

  rag: {
    vectorStore: 'support-docs',
    k: 5,
    threshold: 0.7,
    searchPrompt: `Search the knowledge base when the customer asks about:
- Product features or how things work
- Pricing or plan details
- Policies (refund, cancellation, etc.)
- Technical troubleshooting steps`,
  },

  tools: {
    searchOrders: searchOrdersTool,
    createTicket: createTicketTool,
  },

  observability: 'full',
});
```

## Step 4: Wire Everything in `main.ts`

```typescript main.ts theme={null}
import { identify, track } from '@runflow-ai/sdk/observability';
import { supportAgent } from './agent';

export async function main(input: any) {
  // Validate input
  if (!input?.message || typeof input.message !== 'string') {
    return { error: 'message is required' };
  }

  // Identify the customer
  identify(input.email || input.phone || input.userId || 'anonymous');

  try {
    const result = await supportAgent.process({
      message: input.message,
      sessionId: input.sessionId,
    });

    // Track support metrics
    track('support_request', {
      channel: input.channel || 'api',
      resolved: !result.metadata?.toolsUsed?.includes('create-ticket'),
    });

    return {
      message: result.message,
      metadata: result.metadata,
    };
  } catch (error) {
    console.error('[support-agent] Error:', error);
    return { error: 'An error occurred. Please try again.' };
  }
}
```

## Setting Up the Knowledge Base

Upload your documentation to power RAG:

```bash theme={null}
# Create the knowledge base
rf kb create support-docs

# Upload files
rf kb upload support-docs ./docs/faq.md
rf kb upload support-docs ./docs/pricing.md
rf kb upload support-docs ./docs/refund-policy.md

# Or upload an entire directory
rf kb upload support-docs ./docs/

# Test search
rf kb search support-docs "How do I cancel my subscription?"
```

## Key Takeaways

* **Separate concerns**: tools, prompts, and agent config in their own files
* **Always identify**: call `identify()` before `agent.process()` for proper memory and tracing
* **Track metrics**: use `track()` in tools and main.ts to power dashboards
* **Handle errors**: validate input, try/catch in main, return error objects from tools
* **Write specific instructions**: tell the agent exactly when and how to use each tool
* **Use RAG wisely**: write a specific `searchPrompt` so the agent knows when to search

## Next Steps

<CardGroup cols={2}>
  <Card title="Collections Agent" icon="money-bill" href="/use-cases/collections-agent">
    WhatsApp collections example
  </Card>

  <Card title="Knowledge (RAG)" icon="database" href="/core-concepts/knowledge-rag">
    Learn more about RAG
  </Card>

  <Card title="Best Practices" icon="lightbulb" href="/best-practices">
    Tips for effective agents
  </Card>

  <Card title="Project Structure" icon="folder" href="/project-structure">
    Organize your project
  </Card>
</CardGroup>
