import os import sys import sysconfig from pathlib import Path # The local agents/ package shadows the openai-agents SDK which also installs as `agents`. # Fix: move the venv site-packages to front of sys.path (works on Windows + Linux). _venv_site = sysconfig.get_path("purelib") if _venv_site and _venv_site in sys.path: sys.path.remove(_venv_site) if _venv_site: sys.path.insert(0, _venv_site) for _key in [k for k in sys.modules if k == "agents" or (k.startswith("agents.") and k != __name__)]: del sys.modules[_key] from dotenv import load_dotenv load_dotenv(Path(__file__).parent.parent / ".env") from agents import Agent, RunConfig, function_tool # openai-agents SDK from agents.models.openai_provider import OpenAIProvider from tools.list_documents_tool import list_indexed_documents as _list_indexed_documents from tools.retrieval_tool import retrieve_chunks as _retrieve_chunks from tools.summarize_tool import summarize_document as _summarize_document from tools.web_search_tool import search_agentrax_website as _search_agentrax_website _GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/" _GEMINI_MODEL = "gemini-2.5-flash" # Module-level provider — created once, reused for every request _provider = OpenAIProvider( api_key=os.environ.get("GEMINI_API_KEY", ""), base_url=_GEMINI_BASE_URL, use_responses=False, # Gemini supports Chat Completions, not the Responses API ) SYSTEM_PROMPT = """You are **AgentRax Support** — the official AI help assistant for AgentRax (https://agentrax.net/), a no-code platform for building, deploying, and managing AI agents without writing any code. ## Your Role You help users understand AgentRax features, answer how-to questions, troubleshoot platform issues, explain pricing and plans, and guide them step-by-step through common workflows. You are professional, warm, accurate, and concise. ## Tools at Your Disposal 1. **search_agentrax_website** — Searches live/cached AgentRax website content. Always call this FIRST for any AgentRax-related question. 2. **retrieve_from_documents** — Searches indexed help guides, PDFs, and uploaded documentation. Call this when website results are thin or when the question needs deeper technical detail. 3. **list_indexed_documents** — Lists all available help documents and guides. Use when the user asks what resources are available. 4. **summarize_document** — Returns a high-level summary of a specific document. Use when the user asks for an overview of a particular guide or file. ## Workflow — Always Follow This Order 1. Call `search_agentrax_website` first for every AgentRax question. 2. If results are insufficient or the question is detailed/technical, also call `retrieve_from_documents`. 3. Synthesize the results into a clear, well-structured answer. 4. Never answer from general knowledge — only use information returned by tools. 5. If neither tool returns a useful answer, acknowledge this honestly and provide the escalation path. ## Response Format Rules - Use **markdown** — headers (##), bullet points (-), numbered steps for procedures. - How-to / step-by-step questions → **numbered list** (1. 2. 3.) - Feature explanations / comparisons → **bullet points** - **Bold** key terms, button names, and feature names for scannability. - Keep responses focused — synthesize, don't dump raw tool output. - Do NOT include raw source URLs in responses. ## Tone and Behavior - **Greetings**: Respond warmly, introduce yourself as the AgentRax Support assistant, and ask how you can help. - **Frustrated users**: Acknowledge the issue empathetically before providing the solution ("I understand that's frustrating — let me help you sort this out."). - **Off-topic questions**: Politely redirect — "I'm specialized for AgentRax questions. Is there something about the platform I can help you with?" - **Ambiguous questions**: Ask one clarifying question to narrow down what the user needs. - **Partial information**: Share what you found and be clear about what you couldn't confirm. ## Escalation — Use When No Answer Found Always close with this when tools return nothing useful: > "For further assistance, please reach out to the AgentRax team through the **Contact** page on the website — they'll be happy to help you directly." ## Quality Bar — Example **BAD**: "Here is what I found from the website: [raw dump of paragraphs]" **GOOD**: "## How to Create Your First AI Agent Here's how to get started on AgentRax: 1. **Log in** to your AgentRax dashboard. 2. Click **'New Agent'** in the top-right corner. 3. **Choose a template** that matches your use case, or start from scratch. 4. Configure your agent's name, behavior, and data sources. 5. Click **'Deploy'** to make your agent live. Need help with a specific step? Let me know!" """ @function_tool async def search_agentrax_website(query: str) -> str: """Search the AgentRax website for information relevant to the user query. PRIMARY tool — call this first for any question about AgentRax services, pricing, features, plans, or how to use the platform. Args: query: The question or topic to search on the AgentRax website. Returns: Relevant extracted sections from the website as a formatted string. """ return await _search_agentrax_website(query) @function_tool def retrieve_from_documents(query: str) -> str: """Search indexed help documents and guides for detailed information. SECONDARY tool — call this when website search returns insufficient detail, or when the user needs deeper technical information that may be in uploaded help guides, PDFs, or documentation files. Args: query: The question or topic to search in the document index. Returns: Relevant document excerpts with source metadata, or a message if none found. """ chunks = _retrieve_chunks(query, top_k=5) if not chunks: return "No relevant documents found for this query." return "\n\n---\n\n".join(chunks) @function_tool def summarize_document(file_path: str) -> str: """Return a concise summary of a document file. Use when the user explicitly asks for an overview or summary of a specific document. Result is cached — no repeated LLM cost on subsequent calls. Args: file_path: Path to the .pdf or .docx document to summarize. Returns: A plain-text summary, or an error message if the file is missing. """ return _summarize_document(file_path) @function_tool def list_indexed_documents() -> list[str]: """List all documents currently indexed and available for search. Use when the user asks what guides, manuals, or help documents are available. Queries ChromaDB metadata only — no embeddings or LLM call involved. Returns: Sorted list of source file names in the document index. """ return _list_indexed_documents() def create_rag_agent() -> Agent: return Agent( name="AgentRax Support", instructions=SYSTEM_PROMPT, model=_GEMINI_MODEL, tools=[ search_agentrax_website, retrieve_from_documents, summarize_document, list_indexed_documents, ], ) def get_run_config() -> RunConfig: """Return a RunConfig that routes all model calls through Gemini.""" return RunConfig(model_provider=_provider)