### Setup Virtual Environment and Clone Repository Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Clones the repository and sets up a Python virtual environment for managing project dependencies. Activate the environment before installing packages. ```bash git clone cd PydanticAI-Research-Agent python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate ``` -------------------------------- ### Run Guided Gmail Setup Wizard Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Execute the `gmail_setup.py` script to initiate an interactive command-line wizard for setting up Gmail OAuth2 authentication. This process validates credentials, handles the browser OAuth flow, saves the token, and tests the connection. ```bash # Run the guided setup wizard python gmail_setup.py # Expected interactive flow: # ┌─ Gmail Setup ────────────────────────────────────────────┐ # │ Prerequisites: Google Cloud Project, OAuth2 credentials │ # └──────────────────────────────────────────────────────────┘ # Credentials path: credentials.json # Token path: token.pickle # # [yellow] Starting OAuth2 authentication flow... # [blue] Opening browser for authentication... # [green] ✓ Authentication successful! Token saved to token.pickle # [yellow] Testing Gmail API connection... # [green] ✓ Gmail API connection successful! # [green] ✓ Connected to: you@gmail.com # # ┌─ Setup Complete ✅ ──────────────────────────────────────┐ # │ Next: copy .env.example → .env, add API keys, then │ # │ run: python research_email_cli.py │ # └──────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Setup Gmail OAuth2 Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Executes the Python script to initiate the Gmail OAuth2 setup wizard. This process guides the user through obtaining credentials for Gmail API access. ```bash python gmail_setup.py ``` -------------------------------- ### Claude CLI Setup Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Installs the Claude CLI globally using npm and then runs the setup command to generate a 1-year OAuth token. This token is required for the Claude Code GitHub Actions workflow. ```bash npm install -g @anthropic-ai/claude-code claude setup-token ``` -------------------------------- ### Python Gmail Setup Script Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md This script handles the initial setup and validation of Gmail API credentials and tokens. It guides the user through downloading credentials, running the OAuth2 flow, and testing the connection. ```python import os import sys import asyncio from pathlib import Path from rich.console import Console from rich.markdown import Markdown from rich.panel import Panel from rich.prompt import Confirm # Import custom modules from gmail_tools import authenticate_gmail_service from research_agent.settings import ( guide_credentials_download, check_credentials_file, run_oauth_flow, test_gmail_connection, create_env_example, display_welcome ) console = Console() # --- Constants --- # Environment variables for Gmail configuration ENV_VARS = { "GMAIL_CREDENTIALS_PATH": "credentials.json", "GMAIL_TOKEN_PATH": "token.pickle", } # Content for the .env.example file env_content = """ # Gmail Configuration GMAIL_CREDENTIALS_PATH=credentials.json GMAIL_TOKEN_PATH=token.pickle # Brave Search Configuration BRAVE_API_KEY=your-brave-api-key """ def main(): """Main setup function.""" display_welcome() # Get paths from environment or defaults credentials_path = os.getenv('GMAIL_CREDENTIALS_PATH', ENV_VARS['GMAIL_CREDENTIALS_PATH']) token_path = os.getenv('GMAIL_TOKEN_PATH', ENV_VARS['GMAIL_TOKEN_PATH']) console.print(f"[blue]Credentials path: {credentials_path}[/blue]") console.print(f"[blue]Token path: {token_path}[/blue]\n") # Check for existing setup if os.path.exists(token_path): if Confirm.ask("Gmail already appears to be set up. Re-run setup?", default=False): os.remove(token_path) else: # Test existing setup if test_gmail_connection(token_path): console.print("\n[green]Gmail is already configured and working![/green]") return True else: console.print("[yellow]Existing setup appears broken. Continuing with fresh setup...[/yellow]") # Check credentials file if not check_credentials_file(credentials_path): console.print(f"[yellow]Credentials file not found or invalid: {credentials_path}[/yellow]") guide_credentials_download() # Wait for user to download credentials while not check_credentials_file(credentials_path): if not Confirm.ask(f"Have you saved credentials.json to {credentials_path}?"): console.print("[red]Setup cancelled. Please download credentials.json first.[/red]") return False if not check_credentials_file(credentials_path): console.print("[red]Credentials file still not found or invalid.[/red]") console.print("[green]✓ Credentials file found and valid[/green]") # Run OAuth2 flow if not run_oauth_flow(credentials_path, token_path): console.print("[red]Setup failed during OAuth2 flow.[/red]") return False # Test connection if not test_gmail_connection(token_path): console.print("[red]Setup failed during connection test.[/red]") return False # Create environment example create_env_example() # Success message success_message = """ # Gmail Setup Complete! ✅ ## What was configured: - OAuth2 credentials validated - Authentication tokens generated and saved - Gmail API connection tested successfully ## Next steps: 1. Copy `.env.example` to `.env` 2. Add your other API keys (OpenAI, Brave) 3. Run the research agent: `python cli.py` ## Security reminders: - **Never commit credentials.json or token.pickle to version control** - Add them to your .gitignore file - Keep your API keys secure in the .env file """ console.print(Panel(Markdown(success_message), title="Setup Complete", border_style="green")) return True if __name__ == "__main__": try: success = main() sys.exit(0 if success else 1) except KeyboardInterrupt: console.print("\n[yellow]Setup cancelled by user.[/yellow]") sys.exit(1) except Exception as e: console.print(f"\n[red]Unexpected error: {e}[/red]") sys.exit(1) ``` ```python if not os.path.exists('.env.example'): with open('.env.example', 'w') as f: f.write(env_content) console.print("[green]✓ Created .env.example with Gmail configuration[/green]") ``` -------------------------------- ### Documentation Creation Plan Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Specifies the documentation requirements, including README, setup guides for credentials and APIs, usage examples, and project structure documentation. ```yaml Implementation Task 9 - Documentation: CREATE documentation: - README with setup instructions including credentials/ folder setup - Google Cloud Console credential setup guide - API key configuration guide - Usage examples and CLI commands - Project structure documentation ``` -------------------------------- ### Environment Configuration Example Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Example of environment configuration using pydantic-settings. ```python # settings.py: Environment configuration with pydantic-settings ``` -------------------------------- ### Gmail OAuth2 Setup Wizard Welcome Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Displays a welcome message and instructions for setting up Gmail OAuth2 authentication. Requires `rich` library for console output. ```python import os import sys import pickle import webbrowser from pathlib import Path from rich.console import Console from rich.prompt import Prompt, Confirm from rich.panel import Panel from rich.markdown import Markdown from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build console = Console() SCOPES = ['https://www.googleapis.com/auth/gmail.compose'] def display_welcome(): """Display welcome message and setup instructions.""" welcome_text = """ # Gmail OAuth2 Setup Wizard This wizard will help you set up Gmail OAuth2 authentication for the Research Agent. ## Prerequisites: 1. **Google Cloud Project** with Gmail API enabled 2. **OAuth2 Credentials** downloaded from Google Cloud Console 3. **Internet connection** for authentication flow ## What this script will do: - Guide you through credential file setup - Run OAuth2 authentication flow - Test Gmail API connection - Save authentication tokens securely """ console.print(Panel(Markdown(welcome_text), title="Gmail Setup", border_style="blue")) ``` -------------------------------- ### Environment Setup Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Commands to create and activate a Python virtual environment for your agent project. ```bash python -m venv venv source venv/bin/activate ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Copies the example environment file and instructs to edit it with personal API keys and configuration settings for LLM, Brave Search, and Gmail OAuth2. ```bash cp .env.example .env # Edit .env with your API keys ``` -------------------------------- ### Multi-Tool Agent Example Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Example of a multi-tool agent integrating web search and email functionalities. ```python # research_agent.py: Multi-tool agent with web search and email integration ``` -------------------------------- ### Standalone Gmail OAuth2 Setup Script Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md A placeholder for a standalone Python script designed to guide users through the interactive Gmail OAuth2 setup process, including credential download and token validation. ```python # Standalone script for OAuth2 setup def setup_gmail_oauth(): """Interactive Gmail OAuth2 setup script""" # Guide user through credential download # Run OAuth2 flow once # Validate tokens work # Save for future use ``` -------------------------------- ### Model Provider Abstraction Example Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Example of abstracting model providers using a get_llm_model function. ```python # providers.py: Model provider abstraction with get_llm_model() ``` -------------------------------- ### Clone and Setup Pydantic AI Template Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README_TEMPLATE.md Clone the repository and use the provided script to copy the template to your new project. Navigate to your project and begin building your agent. ```bash # Clone the context engineering repository git clone https://github.com/coleam00/Context-Engineering-Intro.git cd Context-Engineering-Intro/use-cases/pydantic-ai # 1. Copy this template to your new project python copy_template.py /path/to/my-agent-project # 2. Navigate to your project cd /path/to/my-agent-project # 3. Start building with the PRP workflow # Fill out PRPs/INITIAL.md with the agent you want to create # 4. Generate the PRP based on your detailed requirements (validate the PRP after generating!) /generate-pydantic-ai-prp PRPs/INITIAL.md # 5. Execute the PRP to create your Pydantic AI agent /execute-pydantic-ai-prp PRPs/generated_prp.md ``` -------------------------------- ### Install PydanticAI and Dependencies Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Installs the core PydanticAI library with OpenAI support, along with necessary packages for HTTP requests, rich CLI output, environment variable management, Google authentication, and testing. ```bash pip install 'pydantic-ai-slim[openai]' httpx rich python-dotenv pip install google-auth google-auth-oauthlib google-api-python-client pip install pytest pytest-asyncio # For testing ``` -------------------------------- ### Guide Gmail Credentials Download Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Provides instructions to the user on how to download their Gmail API credentials from the Google Cloud Console. This is a placeholder function. ```python def guide_credentials_download(): """Guide user through credentials download process.""" instructions = """ # Download Gmail API Credentials ``` -------------------------------- ### Specialized Agent Example Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Example of a specialized agent for creating Gmail drafts. ```python # email_agent.py: Specialized agent for Gmail draft creation ``` -------------------------------- ### Example Environment Variables Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Illustrates the structure and required values for environment variables used to configure the LLM provider, API keys, model names, base URLs, and Brave Search API key. ```dotenv LLM_PROVIDER=openai LLM_API_KEY=your-openai-api-key-here LLM_MODEL=gpt-4o LLM_BASE_URL=https://api.openai.com/v1 BRAVE_API_KEY=your-brave-search-api-key-here GMAIL_CREDENTIALS_PATH=credentials.json GMAIL_TOKEN_PATH=token.pickle ``` -------------------------------- ### Activate Virtual Environment and Run CLI Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Activate your Python virtual environment and launch the research agent's command-line interface. Ensure dependencies are installed. ```bash source venv/bin/activate python research_email_cli.py ``` -------------------------------- ### Install Pydantic-AI Slim Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README.md Install the pydantic-ai-slim package with OpenAI support. This is a common solution for 'No module named pydantic_ai' errors. ```bash pip install 'pydantic-ai-slim[openai]' ``` -------------------------------- ### Validate Gmail Setup Programmatically Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Use the `validate_gmail_setup` function to programmatically check the status of your Gmail OAuth2 configuration. This function returns a dictionary indicating whether credentials and tokens exist and if further setup is required. ```python # Validate setup state programmatically from tools.gmail_tools import validate_gmail_setup status = validate_gmail_setup("credentials.json", "token.pickle") # { # "credentials_exists": True, # "token_exists": True, # "setup_required": False, # "messages": ["Gmail OAuth2 appears to be configured"] # } print(status) ``` -------------------------------- ### Define Agent Requirements in Markdown Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README_TEMPLATE.md Start by clearly defining your agent's requirements in a markdown file. This includes an overview, core functionalities, and specific features. ```markdown # Customer Support Agent - Initial Requirements ## Overview Build an intelligent customer support agent that can handle inquiries, access customer data, and escalate issues appropriately. ## Core Requirements - Multi-turn conversations with context and memory - Customer authentication and account access - Account balance and transaction queries - Payment processing and refund handling ... ``` -------------------------------- ### Email Agent Initialization Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Initializes the email agent with a language model and specifies dependencies for Gmail authentication. The system prompt guides the agent's behavior for professional email composition. ```python from pydantic_ai import Agent, RunContext from dataclasses import dataclass from typing import Dict, Any, List from .providers import get_llm_model from .models import EmailDraft import logging logger = logging.getLogger(__name__) @dataclass class EmailAgentDependencies: gmail_credentials_path: str gmail_token_path: str session_id: str = None email_agent = Agent( get_llm_model(), deps_type=EmailAgentDependencies, system_prompt="""Professional email composition agent that creates well-structured emails based on research findings. Guidelines: - Use clear, professional language for business communication - Structure emails with proper greeting, body, and closing - Include relevant research insights - Return properly formatted EmailDraft objects - Creates drafts only - does not send emails""" ) ``` -------------------------------- ### Email Agent Development Plan Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Details the implementation of the email agent, including dependency setup, Gmail authentication, tool creation for sending emails, and error handling. ```yaml Implementation Task 3 - Email Agent Development: IMPLEMENT email_agent.py: - EmailAgentDependencies dataclass with credentials folder paths - Gmail OAuth2 authentication using validated credentials - Tools for draft creation and email sending - Error handling for Gmail API failures - Professional email template generation ``` -------------------------------- ### Dockerfile for Pydantic AI Agent Deployment Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Sets up a Docker environment for running a Pydantic AI agent. Installs dependencies and exposes the application port. ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` -------------------------------- ### Pre-Setup Validation for Gmail OAuth2 Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md This bash command checks if the necessary Gmail OAuth2 configuration files exist using environment variables. It prints a success message or a warning to run the setup script. ```bash python -c " import os required = ['GMAIL_CREDENTIALS_PATH', 'GMAIL_TOKEN_PATH'] if all(os.path.exists(os.getenv(var, '')) for var in required): print('✓ Gmail OAuth2 already configured') else: print('⚠ Run setup_gmail.py for first-time OAuth2 setup') " ``` -------------------------------- ### Launch Research Email CLI Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Launches the command-line interface for the research and email agent. This script starts a streaming REPL loop that integrates with tools and provides real-time feedback. ```bash # Launch the CLI python research_email_cli.py # Example session: # ┌─────────────────────────────────────────────────────────┐ # │ 🔬 PydanticAI Research & Email Agent │ # │ Real-time tool execution with Gmail integration │ # │ Type 'exit' to quit, 'help' for commands │ # └─────────────────────────────────────────────────────────┘ # # You: Research AI safety trends and email summary to alice@company.com # Assistant: # 🔹 Calling tool: search_web # Args: query=AI safety trends 2024, max_results=10 # ✅ Tool call complete. # 🔹 Calling tool: create_email_draft # Args: recipient_email=alice@company.com, subject=AI Safety Trends... # ✅ Tool call complete. # I've researched the latest AI safety trends and created a Gmail draft # for alice@company.com summarising the key findings. # # You: exit # 👋 Goodbye! ``` -------------------------------- ### Basic Agent with Dependencies and Tool Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/AGENTS.md Defines a simple PydanticAI agent with custom dependencies and an example asynchronous tool. Ensure settings are loaded and API keys are managed securely. ```python # Follow main_agent_reference patterns - no result_type unless structured output needed from pydantic_ai import Agent, RunContext from dataclasses import dataclass from .settings import load_settings @dataclass class AgentDependencies: """Dependencies for agent execution""" api_key: str session_id: str = None # Load settings with proper dotenv handling settings = load_settings() # Simple agent with string output (default) agent = Agent( get_llm_model(), # Uses load_settings() internally deps_type=AgentDependencies, system_prompt="You are a helpful assistant..." ) @agent.tool async def example_tool( ctx: RunContext[AgentDependencies], query: str ) -> str: """Tool with proper context access""" return await external_api_call(ctx.deps.api_key, query) ``` -------------------------------- ### Test Gmail Setup Script Credential Validation Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Validates the `check_credentials_file` function within the `setup_gmail` script. Tests its behavior with a non-existent file to ensure it correctly returns `False`. ```python from setup_gmail import check_credentials_file # Test with non-existent file result = check_credentials_file('nonexistent.json') assert result == False print('✓ Setup script credential validation works') ``` -------------------------------- ### Create .env.example for Gmail and LLM Configuration Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Generates a sample `.env.example` file to configure Gmail OAuth2 paths and LLM settings. This file serves as a template for environment variables. ```dotenv # Gmail OAuth2 Configuration GMAIL_CREDENTIALS_PATH=credentials.json GMAIL_TOKEN_PATH=token.pickle # LLM Configuration LLM_PROVIDER=openai LLM_API_KEY=your-openai-api-key LLM_MODEL=gpt-4o ``` -------------------------------- ### Main CLI Entry Point Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Sets up dependencies and runs the main interactive loop for the CLI. Handles user input, agent interaction, and graceful exit. Catches KeyboardInterrupt and other exceptions. ```python async def main(): """Main CLI entry point.""" settings = load_settings() deps = ResearchAgentDependencies( brave_api_key=settings.brave_api_key, gmail_credentials_path=settings.gmail_credentials_path, gmail_token_path=settings.gmail_token_path ) console.print("[bold green]Research & Email Agent CLI[/bold green]") console.print("Type 'exit' to quit\n") while True: try: prompt = console.input("[bold cyan]You:[/bold cyan] ") if prompt.lower() in ['exit', 'quit']: break await stream_agent_response(prompt, deps) console.print() # Add spacing except KeyboardInterrupt: console.print("\n[yellow]Interrupted by user[/yellow]") break except Exception as e: console.print(f"[red]Error: {e}[/red]") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Validate Gmail OAuth2 Setup Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Run the Gmail OAuth2 validation script to confirm that credentials and API access are correctly configured before proceeding with implementation. This script provides guided prompts if issues are detected. ```bash python scripts/validate_gmail_oauth.py ``` -------------------------------- ### Check for Hardcoded Secrets Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Scans Python files for hardcoded secrets like API keys (prefixed with 'sk-') or credentials files. Ensures sensitive information is not present in the codebase, except where expected in example or setup files. ```bash grep -r "sk-" . --include="*.py" | grep -v ".env" # Should be empty grep -r "credentials.json" . --include="*.py" | grep -v "example" | grep -v "setup_gmail" # Should use env vars (except in setup script) ``` -------------------------------- ### Tool: `authenticate_gmail` Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt A `@email_agent.tool` that authenticates against the Gmail API using OAuth2 credentials. Returns a status dict. Handles expired tokens (refresh), missing credentials (guides user to setup wizard), and test mode (returns `MockGmailService`). ```APIDOC ## Tool: `authenticate_gmail` A `@email_agent.tool` that authenticates against the Gmail API using OAuth2 credentials. Returns a status dict. Handles expired tokens (refresh), missing credentials (guides user to setup wizard), and test mode (returns `MockGmailService`). ```python import asyncio, os from agents.email_agent import email_agent, EmailAgentDependencies from pydantic_ai.models.test import TestModel async def demo(): os.environ["TESTING"] = "true" deps = EmailAgentDependencies( gmail_credentials_path="credentials.json", gmail_token_path="token.pickle" ) with email_agent.override(model=TestModel()): result = await email_agent.run("Authenticate Gmail", deps=deps) # Tool returns: # {"success": True, "message": "Gmail authenticated successfully", "service_available": True} # OR on missing creds: # {"success": False, "error": "Gmail OAuth2 not configured", # "recoverable": True, "setup_command": "python setup_gmail.py"} print(result.output) asyncio.run(demo()) ``` ``` -------------------------------- ### Define Agent Dependencies and Initialize Agent Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/CLAUDE.md Sets up dependencies for agent execution and initializes a simple agent with a system prompt. Ensure settings are loaded properly using dotenv. ```python # Follow main_agent_reference patterns - no result_type unless structured output needed from pydantic_ai import Agent, RunContext from dataclasses import dataclass from .settings import load_settings @dataclass class AgentDependencies: """Dependencies for agent execution""" api_key: str session_id: str = None # Load settings with proper dotenv handling settings = load_settings() # Simple agent with string output (default) agent = Agent( get_llm_model(), # Uses load_settings() internally deps_type=AgentDependencies, system_prompt="You are a helpful assistant..." ) ``` -------------------------------- ### Setting Up API Keys with Environment Variables Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Manage API keys securely using environment variables. Never commit these directly into your codebase. ```bash # Environment variables (never commit to code) export LLM_API_KEY="your-api-key-here" export LLM_MODEL="gpt-4" export LLM_BASE_URL="https://api.openai.com/v1" # Or use .env file (git-ignored) echo "LLM_API_KEY=your-api-key-here" > .env echo "LLM_MODEL=gpt-4" >> .env ``` -------------------------------- ### Verify Production Readiness and Security Patterns Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/templates/prp_pydantic_ai_base.md Checks for security best practices, including ensuring API keys are not exposed, an environment template exists, and proper error handling and logging mechanisms are implemented. ```bash # Verify security patterns grep -r "API_KEY" agent_project/ | grep -v ".py:" # Should not expose keys test -f agent_project/.env.example && echo "Environment template present" # Check error handling grep -r "try:" agent_project/ | wc -l # Should have error handling grep -r "except" agent_project/ | wc -l # Should have exception handling # Verify logging setup grep -r "logging\|logger" agent_project/ | wc -l # Should have logging # Expected: Security measures in place, error handling comprehensive, logging configured # If issues: Implement missing security and production patterns ``` -------------------------------- ### Simple Agent with String Output Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Creates a basic agent that defaults to returning string output. It uses environment-based configuration and dependency injection for context. ```python from pydantic_ai import Agent, RunContext from dataclasses import dataclass @dataclass class AgentDependencies: """Dependencies for agent execution""" api_key: str session_id: str = None # Simple agent - no result_type, defaults to string agent = Agent( get_llm_model(), # Environment-based configuration deps_type=AgentDependencies, system_prompt="You are a helpful assistant..." ) ``` -------------------------------- ### Loading and Accessing Settings Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Load application settings using `get_settings` and access individual configuration values. Ensure settings are loaded before use. ```python from config.settings import get_settings settings = get_settings() print(settings.llm_model) # "gpt-4o" print(settings.brave_api_key) # "BSA..." print(settings.gmail_credentials_path) # "credentials.json" print(settings.app_env) # "production" ``` -------------------------------- ### Handling Model Token Limits with FallbackModel Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Demonstrates how to use FallbackModel to specify multiple model options, allowing the agent to gracefully fall back to less capable but potentially cheaper models when needed. ```python # ✅ Handle different model capabilities from pydantic_ai.models import FallbackModel model = FallbackModel([ "openai:gpt-4o", # High capability, higher cost "openai:gpt-4o-mini", # Fallback option ]) ``` -------------------------------- ### EmailAgentDependencies Setup Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Defines the dataclass for email agent dependencies, including Gmail credential paths. Can be constructed directly or via a dependency injection helper. ```python from agents.email_agent import EmailAgentDependencies from agents.dependencies import EmailAgentDependencies as DepsDI # Direct construction deps = EmailAgentDependencies( gmail_credentials_path="credentials.json", gmail_token_path="token.pickle", session_id="session-xyz" ) # Via dependency injection helper (reads from Settings) deps_from_settings = DepsDI.from_settings() ``` -------------------------------- ### Verify Project Structure Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Use find and test commands to verify the presence and structure of Python files and directories within the project. This ensures all necessary components are in place. ```bash find . -name "*.py" -path "./agents/*" | sort ``` ```bash find . -name "*.py" -path "./cli/*" | sort ``` ```bash test -f agents/research_agent.py && echo "Research agent present" ``` ```bash test -f agents/email_agent.py && echo "Email agent present" ``` ```bash test -f agents/tools.py && echo "Tools module present" ``` ```bash test -f cli/streaming.py && echo "Streaming interface present" ``` ```bash test -d credentials && echo "Credentials folder present" ``` ```bash test -f scripts/validate_gmail_oauth.py && echo "OAuth validation script present" ``` -------------------------------- ### Template Structure Overview Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Illustrates the directory structure of the Pydantic AI Context Engineering Template. ```bash pydantic-ai/ ├── CLAUDE.md # Pydantic AI global development rules ├── copy_template.py # Template deployment script ├── .claude/commands/ │ ├── generate-pydantic-ai-prp.md # PRP generation for agents │ └── execute-pydantic-ai-prp.md # PRP execution for agents ├── PRPs/ │ ├── templates/ │ │ └── prp_pydantic_ai_base.md # Base PRP template for agents │ └── INITIAL.md # Example agent requirements ├── examples/ │ ├── basic_chat_agent/ # Simple conversational agent │ │ ├── agent.py # Agent with memory and context │ │ └── README.md # Usage guide │ ├── tool_enabled_agent/ # Agent with external tools │ │ ├── agent.py # Web search + calculator tools │ │ └── requirements.txt # Dependencies │ └── testing_examples/ # Comprehensive testing patterns │ ├── test_agent_patterns.py # TestModel, FunctionModel examples │ └── pytest.ini # Test configuration └── README.md # This file ``` -------------------------------- ### Environment-Based Configuration Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Defines settings using Pydantic-Settings and provides a function to get an LLM model instance based on these settings. Ensure a .env file is present for configuration. ```python from pydantic_settings import BaseSettings from pydantic import Field class Settings(BaseSettings): llm_provider: str = Field(default="openai") llm_api_key: str = Field(...) llm_model: str = Field(default="gpt-4") llm_base_url: str = Field(default="https://api.openai.com/v1") class Config: env_file = ".env" from pydantic_ai.providers.openai import OpenAIProvider from pydantic_ai.models.openai import OpenAIModel def get_llm_model() -> OpenAIModel: settings = Settings() provider = OpenAIProvider( base_url=settings.llm_base_url, api_key=settings.llm_api_key ) return OpenAIModel(settings.llm_model, provider=provider) ``` -------------------------------- ### Check Project File Structure Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Verifies the presence of essential project files and the structure of test files. Ensures all required components for the agents are available. ```bash test -f .env.example && echo "✓ Environment template present" test -f README.md && echo "✓ README documentation present" test -f requirements.txt && echo "✓ Requirements file present" test -f setup_gmail.py && echo "✓ Gmail setup script present" find tests/ -name "test_*.py" | wc -l # Should have multiple test files ``` -------------------------------- ### Configuring Agent with String Output (Default) Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Configure agents for default string output, suitable for conversational or creative tasks. No specific `result_type` is needed. ```python # ✅ Simple chat agent chat_agent = Agent(get_llm_model(), system_prompt="You are helpful...") # ✅ Tool-enabled agent tool_agent = Agent(get_llm_model(), tools=[search_tool], system_prompt="...") # Result: agent.run() returns string result = agent.run_sync("Hello") print(result.data) # "Hello! How can I help you today?" ``` -------------------------------- ### Test Mock Gmail Service Integration Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md This snippet demonstrates how to set up environment variables and run a test for the mock Gmail service integration using Python. ```python import os os.environ['TESTING'] = 'true' import asyncio from gmail_tools import authenticate_gmail_service async def test_mock(): service = await authenticate_gmail_service('', '', test_mode=True) print('✓ Mock Gmail service working for automated testing') asyncio.run(test_mock()) ``` -------------------------------- ### Streaming Output with .iter() Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Illustrates how to stream output from an agent using the `.iter()` method. This pattern is useful for real-time display of agent responses, especially when combined with libraries like Rich for enhanced CLI output. ```python async with agent.iter(user_prompt, deps=deps) as run: async for node in run: if Agent.is_model_request_node(node): async for event in node.stream(): if isinstance(event.delta, TextPartDelta): console.print(event.delta.text, end="") ``` -------------------------------- ### Gmail OAuth2 Pre-Validation Script Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Outlines the steps for creating a script to validate Gmail OAuth2 setup, ensuring credentials and API access are correctly configured before agent implementation. ```yaml Implementation Task 2 - Gmail OAuth2 Pre-Validation: CREATE OAuth2 validation infrastructure: - scripts/validate_gmail_oauth.py: Step-by-step OAuth2 setup validation - credentials/.gitkeep: Ensure credentials folder exists in repo - Guided credential setup with clear error messages - Test OAuth2 flow before agent implementation begins - Validate Gmail API access and permissions ``` -------------------------------- ### Getting and Validating LLM Model Configuration Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Retrieve an LLM model instance using `get_llm_model` and validate the LLM configuration. Supports default and specified models, and inspects active settings. ```python from config.providers import get_llm_model, get_model_info, validate_llm_configuration # Default: uses settings.llm_model ("gpt-4o") model = get_llm_model() # Override to a specific model model_gpt35 = get_llm_model(model_choice="gpt-3.5-turbo") # Inspect active configuration info = get_model_info() # { # "llm_provider": "openai", # "llm_model": "gpt-4o", # "llm_base_url": "https://api.openai.com/v1", # "app_env": "production", # "debug": False # } # Validate before startup if not validate_llm_configuration(): raise RuntimeError("LLM is not configured correctly") ``` -------------------------------- ### Test Gmail API Connection Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Verifies the Gmail API connection by loading saved credentials and executing a simple API call to get the user's profile. Reports success or failure. ```python def test_gmail_connection(token_path: str) -> bool: """Test Gmail API connection.""" try: console.print("\n[yellow]Testing Gmail API connection...[/yellow]") # Load credentials with open(token_path, 'rb') as token: creds = pickle.load(token) # Build service service = build('gmail', 'v1', credentials=creds) # Test with a simple API call profile = service.users().getProfile(userId='me').execute() email_address = profile.get('emailAddress') console.print(f"[green]✓ Gmail API connection successful![/green]") console.print(f"[green]✓ Connected to: {email_address}[/green]") return True except Exception as e: console.print(f"[red]✗ Gmail API connection failed: {e}[/red]") return False ``` -------------------------------- ### Run PydanticAI Research Agent (Async) Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Demonstrates how to run the `research_agent` asynchronously for single-shot results or streaming node events. Requires setting up dependencies with API keys and credentials. ```python import asyncio from agents.research_agent import research_agent, ResearchAgentDependencies from config.settings import get_settings async def main(): settings = get_settings() deps = ResearchAgentDependencies( brave_api_key=settings.brave_api_key, gmail_credentials_path=settings.gmail_credentials_path, gmail_token_path=settings.gmail_token_path ) # Single-shot run result = await research_agent.run( "Research the latest developments in quantum computing", deps=deps ) print(result.output) # Streaming run with real-time tool visibility async with research_agent.iter( "Research AI safety trends and email summary to alice@example.com", deps=deps ) as run: async for node in run: from pydantic_ai import Agent if Agent.is_model_request_node(node): async with node.stream(run.ctx) as s: async for event in s: if type(event).__name__ == "PartDeltaEvent": if hasattr(event.delta, "content_delta"): print(event.delta.content_delta, end="", flush=True) elif Agent.is_call_tools_node(node): async with node.stream(run.ctx) as s: async for event in s: if type(event).__name__ == "FunctionToolCallEvent": print(f"\n[Tool] {event.part.tool_name}") print("\nFinal:", run.result.output) asyncio.run(main()) ``` -------------------------------- ### Verify Environment Settings Loading Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Tests the `load_settings` function to ensure it can load configuration without a `.env` file, relying on default values or environment variables. Reports success or failure based on exception handling. ```python from settings import load_settings try: settings = load_settings() print('✓ Settings load without .env file (using defaults or env vars)') except Exception as e: print(f'✗ Settings require .env file: {e}') ``` -------------------------------- ### Async vs. Sync Tool Patterns in Pydantic AI Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Illustrates correct and incorrect patterns for defining asynchronous tools within a Pydantic AI agent. Avoid mixing sync and async operations inconsistently. ```python # ❌ Don't mix sync and async inconsistently def bad_tool(ctx): return asyncio.run(some_async_function()) # Anti-pattern # ✅ Be consistent with async patterns @agent.tool async def good_tool(ctx: RunContext[Deps]) -> str: result = await some_async_function() return result ``` -------------------------------- ### Enhanced Error Recovery for Gmail Authentication Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md This Python code demonstrates how to implement robust error handling within an email agent tool for Gmail authentication, specifically catching `FileNotFoundError` for missing setup and general exceptions. ```python # In email agent tools @email_agent.tool async def authenticate_gmail(ctx: RunContext[EmailAgentDependencies]) -> Dict[str, Any]: try: service = await authenticate_gmail_service(...) return {"success": True, "message": "Gmail authenticated successfully"} except FileNotFoundError: return {"success": False, "error": "Run 'python setup_gmail.py' first", "recoverable": True} except Exception as e: return {"success": False, "error": str(e), "recoverable": False} ``` -------------------------------- ### PydanticAI Research Agent Implementation Plan Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Details the tasks for implementing the research agent, including email agent completion, Gmail integration, research agent updates, streaming CLI build, configuration, testing, Gmail setup script, and documentation. Each task outlines specific files and actions. ```yaml Implementation Task 1 - Complete Email Agent: CREATE email_agent.py: - Import patterns from research_agent.py - EmailAgentDependencies with Gmail paths - System prompt for professional email composition - Tools: authenticate_gmail(), create_gmail_draft() - Error handling for OAuth failures Implementation Task 2 - Gmail Integration: CREATE gmail_tools.py: - OAuth2 authentication flow implementation - Token storage and refresh logic - Draft creation with MIME formatting - Error handling for API failures - Rate limiting considerations Implementation Task 3 - Update Research Agent: MODIFY research_agent.py: - Import email_agent at module level - Update delegate_to_email_agent tool - Ensure proper error propagation - Add truthful reporting in system prompt Implementation Task 4 - Build Streaming CLI: CREATE cli.py: - Rich Console initialization - Async main loop with agent.iter() - Stream processing with TextPartDelta - Tool invocation visualization - Markdown rendering for responses - Error display with tracebacks Implementation Task 5 - Configuration and Setup: CREATE/UPDATE configuration: - .env.example with all required variables - README.md with setup instructions - Project structure documentation - Gmail OAuth2 setup guide - Brave API registration guide Implementation Task 6 - Comprehensive Testing: CREATE tests/: - test_research_agent.py (with TestModel) - test_email_agent.py (with FunctionModel) - test_gmail_integration.py (with mocks) - test_cli.py (streaming behavior) - test_integration.py (full workflow) Implementation Task 7 - Gmail Setup Script: CREATE setup_gmail.py: - Interactive Gmail OAuth2 setup wizard - Credential validation and download guidance - Token generation and storage - Connection testing and verification Implementation Task 8 - Documentation: CREATE documentation: - API key setup instructions - Gmail OAuth2 configuration - CLI usage examples - Troubleshooting guide ``` -------------------------------- ### Copy Template Script Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Use this script to quickly set up a new Pydantic AI agent project by copying the template structure. ```bash python copy_template.py /path/to/my-agent-project ``` -------------------------------- ### Agent-to-Agent Delegation Pattern Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Demonstrates how one agent can call another agent as a tool. Dependencies for the delegate agent are created within the tool implementation. Usage tracking is passed through for token counting, and error handling is managed at the tool level. ```python @research_agent.tool async def create_email_draft( ctx: RunContext[ResearchAgentDependencies], ... ) -> Dict[str, Any]: email_deps = EmailAgentDependencies(...) result = await email_agent.run( email_prompt, deps=email_deps, usage=ctx.usage # Pass usage for token tracking ) return result.output ``` -------------------------------- ### Run Unit and Integration Tests Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research-email-agent-cli.md Executes unit tests for individual agents and integration tests for their combined functionality. Includes running tests with mocked Gmail services. ```bash python -m pytest tests/test_research_agent.py -v python -m pytest tests/test_email_agent.py -v python -m pytest tests/test_gmail_integration.py -v TESTING=true python -m pytest tests/test_integration.py -v ``` -------------------------------- ### CLI Streaming Implementation for Real-time Display Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/PRPs/research_email_multi_agent.md Describes the CLI streaming implementation for real-time display of generated nodes and event handling for user feedback and error presentation. ```markdown - Real-time display: Process nodes as they're generated via `.iter()` - Event handling: Parse ModelRequestNode events for displayable content - User experience: Immediate feedback on research progress and email creation - Error display: Graceful error presentation in streaming context ``` -------------------------------- ### Implement a Tool with Context Access Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/CLAUDE.md Defines an asynchronous tool that accepts a RunContext with dependencies and performs an external API call. Ensure proper context and dependency injection. ```python @agent.tool async def example_tool( ctx: RunContext[AgentDependencies], query: str ) -> str: """Tool with proper context access""" return await external_api_call(ctx.deps.api_key, query) ``` -------------------------------- ### Environment Variables for Settings Source: https://context7.com/coleam00/pydanticai-research-agent/llms.txt Define runtime configuration using environment variables or a .env file. These settings control LLM provider, API keys, and application behavior. ```dotenv # .env LLM_PROVIDER=openai LLM_API_KEY=sk-... LLM_MODEL=gpt-4o LLM_BASE_URL=https://api.openai.com/v1 BRAVE_API_KEY=BSA... GMAIL_CREDENTIALS_PATH=credentials.json GMAIL_TOKEN_PATH=token.pickle APP_ENV=production LOG_LEVEL=INFO DEBUG=false ``` -------------------------------- ### Execute PRP Document Source: https://github.com/coleam00/pydanticai-research-agent/blob/main/README-template.md Command to implement the AI agent based on the generated PRP document. ```bash /execute-pydantic-ai-prp PRPs/agent_20250119_1200.md ```