Instructions for AI coding agents working on the RFP Analyzer project.
RFP Analyzer is an AI-powered application for analyzing Request for Proposals (RFPs) and scoring vendor proposals using Azure AI services and Microsoft Agent Framework. It uses a multi-agent architecture with specialized agents for document processing, scoring, and comparison.
Tech Stack:
- Python 3.13+ with UV package manager
- Streamlit for web UI
- Microsoft Agent Framework for multi-agent orchestration
- Azure OpenAI (GPT-4.1, GPT-5.2 models)
- Azure Content Understanding & Document Intelligence
- Azure Container Apps for deployment
- Bicep/AVM for infrastructure as code
rfp-analyzer/
├── app/ # Main application
│ ├── main.py # Streamlit entry point
│ ├── entrypoint.py # Startup with diagnostics server injection
│ ├── services/ # Core services (subpackage architecture)
│ │ ├── core/ # Foundation layer
│ │ │ ├── logging_config.py # Centralized logging (console/file/OTLP)
│ │ │ ├── telemetry.py # OpenTelemetry tracing
│ │ │ ├── token_utils.py # LLM token counting
│ │ │ ├── retry_utils.py # Exponential backoff
│ │ │ └── utils.py # Shared utilities
│ │ ├── storage/ # Persistence layer
│ │ │ ├── blob_storage_client.py # Azure Blob Storage CRUD
│ │ │ └── session_state_manager.py # Workflow state persistence
│ │ ├── extraction/ # Document processing
│ │ │ ├── document_processor.py # Extraction orchestrator
│ │ │ ├── processing_queue.py # Queue status tracking
│ │ │ ├── resilience.py # Circuit breaker, auto-fallback
│ │ │ └── extractors/ # Pluggable extraction backends
│ │ │ ├── base.py # DocumentExtractor interface
│ │ │ ├── content_understanding.py
│ │ │ └── document_intelligence.py
│ │ ├── agents/ # AI agents
│ │ │ ├── scoring_agent.py # Criteria extraction + proposal scoring
│ │ │ ├── comparison_agent.py # Multi-vendor comparison
│ │ │ └── pipelines.py # High-level async pipeline functions
│ │ ├── jobs/ # Background job tracking
│ │ │ ├── job_registry.py # In-process registry
│ │ │ ├── job_store.py # Blob-backed persistence
│ │ │ └── diagnostics_server.py # /diag/* endpoints + dashboard
│ │ └── reporting/ # Output generation
│ │ └── report_generator.py # Word/CSV/JSON reports
│ ├── ui/ # Streamlit UI pages
│ ├── tests/ # Unit tests (323 tests)
│ ├── pyproject.toml # Python dependencies (UV)
│ └── requirements.txt # Pip fallback dependencies
├── infra/ # Infrastructure as Code
│ ├── main.bicep # Main Bicep template
│ ├── resources.bicep # Azure resources
│ └── modules/ # Bicep modules
├── docs/ # Documentation
└── azure.yaml # Azure Developer CLI config
- Python 3.13+
- UV package manager
- Azure CLI with
az loginauthenticated - Azure Developer CLI (
azd) for deployment
# Navigate to app directory
cd app
# Install dependencies with UV
uv sync
# Create .env file from template
cp .env.example .env # Then fill in Azure credentials
# Run the application locally
uv run streamlit run main.py --server.port=8501cd app
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
streamlit run main.py --server.port=8501Required environment variables in app/.env:
AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com/
AZURE_OPENAI_API_KEY=<key> # Or use managed identity
AZURE_CONTENT_UNDERSTANDING_ENDPOINT=https://<resource>.cognitiveservices.azure.com/
AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=https://<resource>.cognitiveservices.azure.com/
- Use Python type hints for all function signatures
- Follow PEP 8 naming conventions
- Use Pydantic models for data validation
- Async/await for Azure SDK calls where available
- Use
loggingmodule withlogging_config.pyconfiguration - Prefer composition over inheritance for agents
Agents in services/agents/ follow Microsoft Agent Framework patterns:
- Agents are classes with
run()orprocess()methods - Use dependency injection for Azure clients
- Return structured Pydantic models
# External consumers (main.py, ui/):
from services.core.logging_config import get_logger
from services.agents.pipelines import run_criteria_extraction
from services.extraction.document_processor import DocumentProcessor
# Cross-subpackage (within services/):
from ..core.utils import parse_json_response
from ..storage.blob_storage_client import get_blob_storage_clientfrom azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
# Use managed identity in production, CLI auth locally# Install dev dependencies
uv sync --group dev
# Run tests
uv run pytest tests/ -q
# Run tests excluding known-flaky tests
uv run pytest tests/ -q \
--deselect tests/test_utils.py::test_reads_version_from_pyproject \
--deselect tests/test_resilience.py::test_start_and_finish_timing
# Type checking
uv run mypy app/Test count: 323 unit tests covering all subpackages.
# Login to Azure
azd auth login
# Provision infrastructure and deploy
azd up
# Just deploy code changes
azd deployBicep files are in infra/:
main.bicep- Entry point, parametersresources.bicep- All Azure resourcesmodules/- Reusable Bicep modules
# Preview infrastructure changes
azd provision --preview- Never commit
.envfiles or secrets - Use Azure Managed Identity in production
- API keys should use Azure Key Vault references
test.httpis gitignored (contains test secrets)
- Create new file in
app/services/agents/ - Follow pattern in
scoring_agent.py - Add exports to
services/agents/__init__.py - Wire into
pipelines.pyif needed
- Edit
app/scoring_guide.mdfor scoring guidelines - Update
ScoringAgentprompt templates inservices/agents/scoring_agent.py - Criteria weights are in scoring agent configuration
- Create new extractor in
app/services/extraction/extractors/ - Implement the
DocumentExtractorinterface frombase.py - Register in
document_processor.py
- Edit
infra/resources.bicep - Use AVM modules from
modules/where available - Add outputs to
main.bicepif needed for app config
- Include clear description of changes
- Test locally with
streamlit run main.py - Verify Azure deployment with
azd upfor infra changes - Update documentation if adding new features