Skip to main content

QueryStrategy

The QueryStrategy class represents a search strategy for a specific channel. It encapsulates the query template, channel type, and relevance scoring used to execute targeted searches across different data sources. This is an internal model used by the research engine to generate and execute search queries. While you typically won’t instantiate this class directly, understanding its structure helps you understand how the engine generates search strategies based on your research goals.

Model Definition

from dataclasses import dataclass

@dataclass(frozen=True)
class QueryStrategy:
    """
    Represents a search strategy for a specific channel.
    """
    channel: str
    query_template: str
    relevance_score: float = 1.0

    def build_query(self, company_domain: str) -> str:
        # jobs_search doesn't use domain/company placeholders
        if self.channel == "jobs_search":
            return self.query_template
            
        # Other channels use domain/company substitution
        company_name = company_domain.split(".")[0]
        
        return self.query_template.format(
            DOMAIN=company_domain, COMPANY_NAME=company_name
        )

Fields

channel
string
required
The search channel or data source where this strategy will be executed.Common channel types:
  • "web_search" - General web search engines
  • "jobs_search" - Job posting aggregators and company career pages
  • "news_search" - News articles and press releases
  • "social_search" - Social media platforms and forums
  • "github_search" - GitHub repositories and code
  • "tech_blogs" - Engineering blogs and technical content
Example: "jobs_search"
query_template
string
required
Template string for the search query. May contain placeholders that are substituted at runtime.Available placeholders:
  • {DOMAIN} - The full company domain (e.g., “stripe.com”)
  • {COMPANY_NAME} - The company name extracted from the domain (e.g., “stripe”)
Note: The jobs_search channel does not use placeholders and returns the template as-is.Examples:
  • "site:{DOMAIN} React TypeScript"
  • "{COMPANY_NAME} engineering blog kubernetes"
  • "Senior Backend Engineer Python PostgreSQL" (for jobs_search)
relevance_score
float
default:"1.0"
Score indicating the expected relevance of this strategy to the research goal. Higher scores indicate strategies that are more likely to produce relevant results.Range: Typically 0.0-1.0, but not strictly enforcedUsage: Used internally to prioritize or weight results from different strategiesDefault: 1.0

Methods

build_query()

Builds the final search query by substituting template placeholders with actual company information.
def build_query(self, company_domain: str) -> str:
    """
    Build a concrete search query from the template.
    
    Args:
        company_domain: The company domain to search for (e.g., "stripe.com")
        
    Returns:
        The final search query with placeholders substituted
    """
Parameters:
  • company_domain (str): The full company domain
Returns:
  • str: The fully constructed search query
Example:
strategy = QueryStrategy(
    channel="web_search",
    query_template="site:{DOMAIN} React TypeScript",
    relevance_score=0.9
)

query = strategy.build_query("stripe.com")
print(query)  # Output: "site:stripe.com React TypeScript"

Usage Examples

from app.models.search import QueryStrategy

# Create a web search strategy
web_strategy = QueryStrategy(
    channel="web_search",
    query_template="site:{DOMAIN} kubernetes docker",
    relevance_score=0.85
)

# Build query for specific company
query = web_strategy.build_query("airbnb.com")
print(query)  # "site:airbnb.com kubernetes docker"

Strategy Generation

Strategies are automatically generated by the QueryGenerator service based on your research goal and search depth. Here’s how the engine uses QueryStrategy:
from app.services import QueryGenerator
from app.models.search import QueryStrategy

# Generate strategies based on research goal
query_generator = QueryGenerator()
strategies: list[QueryStrategy] = await query_generator.generate_strategies(
    research_goal="Find companies using React and GraphQL",
    search_depth="standard"
)

print(f"Generated {len(strategies)} strategies")

# Example strategies that might be generated:
for strategy in strategies:
    print(f"Channel: {strategy.channel}")
    print(f"Template: {strategy.query_template}")
    print(f"Relevance: {strategy.relevance_score}")
    print()
Example output:
Generated 15 strategies

Channel: web_search
Template: site:{DOMAIN} React GraphQL stack
Relevance: 0.95

Channel: jobs_search
Template: Frontend Engineer React GraphQL
Relevance: 0.9

Channel: github_search
Template: org:{COMPANY_NAME} graphql
Relevance: 0.85

...

Strategy Execution Flow

Immutability

The QueryStrategy class is implemented as a frozen dataclass, making it immutable:
@dataclass(frozen=True)
class QueryStrategy:
    ...
Benefits:
  • Thread-safe for parallel execution
  • Can be safely shared across multiple pipeline instances
  • Prevents accidental modification during execution
  • Enables efficient caching and memoization
Example:
strategy = QueryStrategy(
    channel="web_search",
    query_template="site:{DOMAIN} React",
    relevance_score=0.9
)

# This will raise an error
try:
    strategy.relevance_score = 0.8
except AttributeError as e:
    print(f"Cannot modify frozen dataclass: {e}")

Channel-Specific Behavior

# Jobs search uses generic queries without company-specific placeholders
strategy = QueryStrategy(
    channel="jobs_search",
    query_template="Senior Backend Engineer Golang Kubernetes"
)

# Returns template unchanged
query = strategy.build_query("anycompany.com")
# Result: "Senior Backend Engineer Golang Kubernetes"

# This searches across all companies' job postings,
# then filters results to match the target domain

Best Practices

Company Name Extraction

The build_query() method extracts company names from domains using simple logic:
company_name = company_domain.split(".")[0]
Examples:
  • "stripe.com""stripe"
  • "netflix.com""netflix"
  • "aws.amazon.com""aws"
  • "co.uk""co" (edge case)
Limitations:
The current implementation may not handle all edge cases correctly:
  • International domains (e.g., example.co.uk)
  • Subdomain-based companies (e.g., shop.example.com)
  • Multi-word company names
If you need more robust name extraction, consider preprocessing the domain list or extending the build_query() method.

Integration Example

Here’s how QueryStrategy integrates with the full research pipeline:
from app.models import BatchResearchRequest
from app.services import QueryGenerator, ResearchPipeline
from app.models.search import QueryStrategy

async def execute_research(request: BatchResearchRequest):
    # Step 1: Generate strategies
    query_generator = QueryGenerator()
    strategies: list[QueryStrategy] = await query_generator.generate_strategies(
        research_goal=request.research_goal,
        search_depth=request.search_depth,
    )
    
    print(f"Generated {len(strategies)} strategies across {len(set(s.channel for s in strategies))} channels")
    
    # Step 2: Create pipeline with strategies
    pipeline = ResearchPipeline(
        research_goal=request.research_goal,
        company_domains=request.company_domains,
        strategies=strategies,  # QueryStrategy instances passed here
        max_parallel_searches=request.max_parallel_searches,
        confidence_threshold=request.confidence_threshold,
    )
    
    # Step 3: Execute (pipeline internally calls build_query for each strategy/company pair)
    results, total_searches = await pipeline.run()
    
    return results

Additional Resources

Build docs developers (and LLMs) love