The Agnostic Scout: Decoupling Strategic Intent from Technical Machinery
How we refactored the VENA Engine search motor to kill hardcoded dependencies and embrace a multi-provider architecture.
The Fragility of Hardcoded Intent
In the early stages of building a sovereign engine, speed is often bought at the cost of coupling. You pick a tool—Playwright, in our case—and you bake it into the very heart of your application logic. You tell yourself it’s “just for now,” but “just for now” is the DNA of future legacy debt.
This week, we rebooted the search motor of the VENA Engine / Scout. We realized that our prospecting logic was a hostage to its machinery. By hardcoding Playwright into our core actions, we weren’t just using a tool; we were letting the tool define our architectural boundaries.
The Mess: The Hardcoded “Scout”
The original ScoutAction was the definition of an architectural dead-end. It was responsible for orchestrating prospecting, but it also took upon itself the burden of instantiating the browser engine and the crawler.
class ScoutAction:
"""
Orquestador (ADR Action) que coordina el flujo de prospección.
"""
def __init__(self, headless: bool = True):
# ERROR: Hardcoded Infrastructure inside the Application Layer
self.engine = PlaywrightEngine(headless=headless)
self.crawler = GoogleMapsCrawler(self.engine)
self.scoring_policy = ScoringPolicy()
If we wanted to switch from Playwright to a native Google Maps API for speed, or a headless LinkedIn crawler for specific leads, we would have to physically rewrite the ScoutAction. In a Sovereign System, the “What” (finding leads) must never be married to the “How” (the scraping library).
The Strategy: Inverting the Machinery
The reboot strategy was to implement Sovereign Dependency Injection. We decided that the ScoutAction should not know how to search; it should only know that it needs a search motor.
We introduced a SearchEngineInterface and forced the infrastructure layer to comply with it. The goal was to move from “Creating Tools” to “Receiving Capabilities.”
The Craft: The Agnostic Refactor
We stripped the constructor of all instantiation logic. Now, the ScoutAction receives its engine and crawler from the outside (ideally via a Factory or a Service Provider).
class ScoutAction:
"""
The Refactored Scout: Pure Orchestration.
"""
def __init__(
self,
engine: SearchEngineInterface,
scoring_policy: ScoringPolicy
):
# The Action now focuses on Domain logic, not machinery.
self.engine = engine
self.scoring_policy = scoring_policy
def run(self, query: str, location: str, limit: int = 20):
# Execution remains identical, but the machinery is now swappable.
raw_prospects = self.engine.search(query, location, limit)
# ... rest of the scoring logic
This change allowed us to implement a MockSearchEngine for lightning-fast testing and paved the way for a MultiProviderEngine that can fallback between different scraping strategies without the Application Layer ever noticing.
The Result: Architectural Sovereignty
By decoupling the machinery, we gained Strategic Optionality.
- Testability: We reduced unit test execution time from 15 seconds (browser-based) to 0.1 seconds (mock-based).
- Resilience: If Playwright is blocked by a target’s firewall, we can inject an API-based engine in a single line of configuration.
- Purity: The core business logic of ATLAS is now protected from the volatility of external libraries.
The Scout is no longer a browser script. It is a Sovereign Orchestrator.
dammgo labs - Engineering as Art.