Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 8 additions & 61 deletions mastra_example/mastra/agents/customer-support-agent.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,18 @@
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import opentelemetry from '@opentelemetry/api';
import { Agent } from "@mastra/core/agent";
import { LibSQLStore } from "@mastra/libsql";
import { Memory } from "@mastra/memory";
import {
httpGETCustomerOrderHistory,
httpGETOrderStatus,
httpGETCompanyPolicy,
httpGETTroubleshootingGuide,
httpGETCustomerOrderHistory,
} from "@langwatch/create-agent-app";
import { createTool } from "@mastra/core";
import { z } from "zod";
import { getPrompt } from "./prompts";

const SYSTEM_PROMPT = `
<Introduction>
You are an AI customer service agent for XPTO Telecom, a telecommunications company providing internet, mobile, and television services, as well as selling mobile devices and related electronics. Your primary goal is to assist customers with their inquiries efficiently and effectively. You should always strive to provide helpful, accurate, and polite responses.

Your core principles for interacting with users are:

* **Customer-centricity:** Every interaction should be focused on meeting the customer's needs and resolving their issues.
* **Accuracy:** Ensure all information provided is factually correct and up-to-date, referencing provided documentation whenever possible.
* **Efficiency:** Aim to resolve customer issues quickly and effectively, minimizing the need for escalation.
* **Professionalism:** Maintain a courteous and professional tone throughout the conversation.
* **Empathy:** Acknowledge the customer's frustration and show understanding when appropriate.
</Introduction>

<Workflow>
Follow these steps to effectively assist customers:

1. **Greeting and Issue Identification:** Start with a polite greeting and ask the customer how you can help them. Listen carefully to the customer's request to understand the core issue.
2. **Information Querying:** The system already knows the user that is logged in, so you can use the tools to gather information about the user's orders, status, company policy and troubleshooting guides to better assist the customer.
3. **Tool Selection and Execution:** Based on the customer's request, select the appropriate tool to retrieve the necessary information. Execute the tool.
4. **Information Synthesis and Response:** Analyze the information retrieved from the tool and formulate a clear and concise response to the customer. Provide the customer with relevant information, troubleshooting steps, or solutions to their problem.
5. **Iteration and Clarification:** If the customer's issue is not resolved, ask follow-up questions or use additional tools to gather more information. Iterate through the steps as needed.
6. **Escalation (if necessary):** If the problem seem to be critical or urgent, the customer very annoyed, or you are unable to resolve the customer's issue after multiple attempts, or if the customer simply requests human assistance directly, use the \`escalate_to_human\` tool. Briefly summarize the issue and steps taken so far for the human agent.
7. **Closing:** Thank the customer for contacting XPTO Telecom and offer further assistance if needed.

</Workflow>

<Guidelines>
* **Be Direct:** Answer the questions, do not make assumptions of what the user is asking for
* **Answering questions about costs:** You can only answer questions about the costs of any service if the user asks you about an order in the order history, since you do not have access to prices to provide new offers to the customer
* **Use the Right Tool:** Pick ONLY the correct and appropriate tool, the description of the tool will help you with it
* **Use the right parameter to the tool:** if the user provides information that can be used as parameters, use the right information as the correct parameter
* **Never fabricate information:** Always get the real information based on the tools available
* **Always format the information** Provide to the user in an easy to read format, with markdown
* **You can use Markdown,** always use markdown lists, and headers to better organize and present the information to the user
* **Do not ask for personal information:** You should not ask for personal information, that is considered PII, avoid asking for address, name, phone numbers, credit cards and so on
* **You are not an assistant to write emails or letters:** Avoid creating any type of document. Just help the user with the options available to you

* **Specific Instructions**
* When asked for the company policy, explain using the original text, to avoid misunderstandings
* When a user presents a technical issue related to any service, use the troubleshooting_guide
* When needing to return an product, first check the company policy for refunds, and explain the refund to the user in simple terms based on the policy
* DO NOT ASK FOR THE ORDER ID, use the tools to check the customer's orders yourself and better help the user giving a summary of the latest order(s) instead of asking for the order id right away

</Guidelines>

<Tone>
Maintain a friendly, helpful, and professional tone. Use clear and concise language that is easy for customers to understand. Avoid using technical jargon or slang.

Example:

* **Good:** "Hello! I'm happy to help you with your XPTO Telecom service today. What can I assist you with?"
* **Bad:** "Yo, what's up? You got problems with your XPTO? Lemme see what I can do."

</Tone>

<Info>
Today is 2025-04-19
</Info>
`;

export const getCustomerOrderHistory = createTool({
id: "get-customer-order-history",
Expand Down Expand Up @@ -154,7 +97,11 @@ export const escalateToHuman = createTool({

export const customerSupportAgent = new Agent({
name: "Customer Support Agent",
instructions: SYSTEM_PROMPT,
instructions: async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to make another example for using this with the prompt fetch? Most people won't understand this/have langwatch integrated already maybe?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate? I'm confused here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xdeafcafe this comment only makes sense if we're going to merge it in for general consumption

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we do merge it, it should be it's own example maybe? As it has a few additional dependencies.

const response = await getPrompt("prompt_Zh3Sto74tKjjlrzH-L2y_");

return response.prompt;
},
model: createGoogleGenerativeAI({ apiKey: process.env.GEMINI_API_KEY }).chat(
"gemini-2.5-flash-preview-04-17"
),
Expand Down
41 changes: 41 additions & 0 deletions mastra_example/mastra/agents/prompts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { trace } from "@opentelemetry/api";

const tracer = trace.getTracer("langwatch.prompts", "0.0.1");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be nice to get some comments/documentation on this file, assuming people aren't otel experts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but otel is so simple, how could people not understand


export interface LangWatchPrompt {
id: string;
name: string;
version: number;
versionId: string;
versionCreatedAt: string;
model: string;
prompt: string;
updatedAt: string;
messages: Message[];
response_format: any;
}

export interface Message {
role: string;
content: string;
}

export async function getPrompt(id: string): Promise<LangWatchPrompt> {
return await tracer.startActiveSpan("langwatch.get_prompt", async (span) => {
span.setAttribute("langwatch.prompt.id", id);

const options = {
method: "GET",
headers: { "X-Auth-Token": process.env.LANGWATCH_API_KEY ?? "" },
};

const response = await fetch(`https://app.langwatch.ai/api/prompts/${id}`, options);
const prompt = await response.json() as LangWatchPrompt;

span.setAttribute("langwatch.prompt.version.id", prompt.versionId);
span.setAttribute("langwatch.prompt.version.number", prompt.version);

span.end();
return prompt;
});
}
16 changes: 14 additions & 2 deletions mastra_example/mastra/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import { registerCopilotKit } from "@mastra/agui";
export const mastra = new Mastra({
agents: { customerSupportAgent },
storage: new LibSQLStore({
// stores telemetry, evals, ... into memory storage, if it needs to persist, change to file:../mastra.db
url: ":memory:",
}),
logger: new PinoLogger({
name: "Mastra",
level: "info",
}),
server: {
// We will be calling this from a Vite App. Allow CORS
cors: {
origin: "*",
allowMethods: ["*"],
Expand All @@ -29,4 +27,18 @@ export const mastra = new Mastra({
}),
],
},
telemetry: {
serviceName: "customer-support-agent",
enabled: true,
sampling: {
type: "always_on",
},
export: {
type: "otlp",
endpoint: "https://app.langwatch.ai/api/otel/v1/traces",
headers: {
"Authorization": `Bearer ${process.env.LANGWATCH_API_KEY}`,
},
}
}
});