inbound rag example.md
Inbound Example w/ RAG
In this example, we'll build an inbound voice agent for a fictional property insurance company. Callers can ask any question about their policy and receive accurate answers sourced from a policy document.
Define the Agent
guava.Agent is our starting point for building Guava agents. We'll start by creating one with some basic background details.
export const AGENT_PY = `import guava
agent = guava.Agent(
organization="Harper Valley Property Insurance",
purpose="Answer questions regarding property insurance policy until there are no more questions",
)`;
export const AGENT_TS = `import * as guava from "@guava-ai/guava-sdk";
const agent = new guava.Agent({
organization: "Harper Valley Property Insurance",
purpose: "Answer questions regarding property insurance policy until there are no more questions",
});`;
Set up DocumentQA
Next, we initialize a DocumentQA instance with the policy document. DocumentQA is a built-in RAG that covers a lot of simple use cases. It's a fully pluggable component and we expect many users will bring their own RAG system.
export const QA_PY = `from guava.helpers.rag import DocumentQA
from guava.examples.example_data import PROPERTY_INSURANCE_POLICY
document_qa = DocumentQA(documents=PROPERTY_INSURANCE_POLICY)`;
export const QA_TS = `import { DocumentQA } from "@guava-ai/guava-sdk/helpers/openai";
import { PROPERTY_INSURANCE_POLICY } from "@guava-ai/guava-sdk/example-data";
const documentQA = new DocumentQA("harper-valley-property-insurance", PROPERTY_INSURANCE_POLICY);`;
Handle questions with on_question
Whenever the caller asks something the agent cannot answer from context alone, Guava invokes the on_question callback with the question in natural language. We forward it to DocumentQA and return the answer.
export const ON_QUESTION_PY = `@agent.on_question
def on_question(call: guava.Call, question: str) -> str:
return document_qa.ask(question)`;
export const ON_QUESTION_TS = `agent.onQuestion(async (call: guava.Call, question: string) => {
return await documentQA.ask(question);
});`;
The agent remains fully responsive during the lookup — it continues listening and engaging with the caller while waiting for your response. You are not latency-constrained in your on_question implementation.
Start the agent
Finally, we attach the agent to a channel so that we can actually talk to it.
export const RUN_PY = `# Run this to attach your agent to a phone number. Call your agent's number to talk to it.
agent.listen_phone(os.environ["GUAVA_AGENT_NUMBER"])
# Run this to receive a WebRTC link where you can talk to your agent in the browser.
agent.listen_webrtc()
# Run this to talk to your agent using your local audio device.
agent.call_local()
# Run this to test your agent in a text-based chat session in the terminal (no audio required).
agent.chat()`;
export const RUN_TS = `// Run this to attach your agent to a phone number. Call your agent's number to talk to it.
agent.listenPhone(process.env.GUAVA_AGENT_NUMBER!);
// Run this to receive a WebRTC link where you can talk to your agent in the browser.
agent.listenWebrtc();
// Run this to talk to your agent using your local audio device.
agent.callLocal();
// Run this to test your agent in a text-based chat session in the terminal (no audio required).
agent.chat();`;
Complete example
export const FULL_PY = `import logging
import os
import guava
import argparse
from guava.helpers.rag import DocumentQA
from guava import logging_utils, Agent
from guava.examples.example_data import PROPERTY_INSURANCE_POLICY
logger = logging.getLogger("guava.examples.property_insurance")
agent = Agent(
organization="Harper Valley Property Insurance",
purpose="Answer questions regarding property insurance policy until there are no more questions",
)
document_qa = DocumentQA(documents=PROPERTY_INSURANCE_POLICY)
@agent.on_question
def on_question(call: guava.Call, question: str) -> str:
answer = document_qa.ask(question)
logger.info("RAG answer: %s", answer)
return answer
if __name__ == "__main__":
logging_utils.configure_logging()
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--phone", action="store_true", help="Listen for phone calls.")
group.add_argument("--webrtc", action="store_true", help="Create on a WebRTC code.")
group.add_argument("--local", action="store_true", help="Start a local call.")
group.add_argument("--chat", action="store_true", help="Start a text-based chat session for testing.")
args = parser.parse_args()
if args.phone:
agent.listen_phone(os.environ["GUAVA_AGENT_NUMBER"])
elif args.webrtc:
agent.listen_webrtc()
elif args.chat:
agent.chat()
else:
agent.call_local();`;
export const FULL_TS = `import * as guava from "@guava-ai/guava-sdk";
import { DocumentQA } from "@guava-ai/guava-sdk/helpers/openai";
import { PROPERTY_INSURANCE_POLICY } from "@guava-ai/guava-sdk/example-data";
const agent = new guava.Agent({
organization: "Harper Valley Property Insurance",
purpose: "Answer questions regarding property insurance policy until there are no more questions",
});
const documentQA = new DocumentQA("harper-valley-property-insurance", PROPERTY_INSURANCE_POLICY);
agent.onQuestion(async (call: guava.Call, question: string) => {
return await documentQA.ask(question);
});
const args = process.argv.slice(2);
if (args.includes("--webrtc")) {
agent.listenWebrtc();
} else if (args.includes("--phone")) {
agent.listenPhone(process.env.GUAVA_AGENT_NUMBER!);
} else if (args.includes("--local")) {
agent.callLocal();
} else if (args.includes("--chat")) {
agent.chat();
} else {
console.error("Usage: guava-example property-insurance --phone | --webrtc | --local | --chat");
process.exit(1);
}`;