## 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.

```python
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",
)`;
```

```typescript
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.

```python
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)`;
```

```typescript
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.

```python
export const ON_QUESTION_PY = `@agent.on_question
def on_question(call: guava.Call, question: str) -> str:
    return document_qa.ask(question)`;
```

```typescript
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.

```python
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()`;
```

```typescript
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

```python
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();`;
```

```typescript
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);
}`;
```
