Extracted from Crypto Hunter AI: the scout → gate → debate → mission machinery that turned out to have almost no crypto in it at all. Two extension points (a gate-hard check hook, a spec-class hook) let a new domain plug in its own verification without forking the engine.
An audit of the shipped, live, 47-test Crypto Hunter AI found that almost none of its trust machinery is actually about crypto. The gate's fail-closed logic, the debate's Advocate/Skeptic/Strategist mechanism, the deterministic mission-budget packer, the SQLite store — none of it references a chain or a token. Only the domain's own verification check (crypto: on-chain contract lookup) and a few optional fields were crypto-specific — and even those already degraded gracefully when absent. So instead of copy-pasting that 80% into every new domain, it became its own package.
A list of callables, each (spec) -> GateEvidence, appended to the built-in evidence list.
This is where a domain's own gate-hard verification lives — comp-price confirmation for collectibles,
official-registry confirmation for unclaimed benefits.
The one real coupling the audit found: the store needs to know which concrete OpportunitySpec
subclass to validate into. Pass your own domain spec class and every read/write round-trips it correctly.
| Module | Generic (this package) | Domain supplies |
|---|---|---|
| spec.py | All fields except type's meaning | A closed type enum + extra fields, via subclassing |
| gate.py | Allowlist, domain-age, confirmation-count, scam-report checks | One or more extra_checks |
| store.py | The whole SQLite schema and API | Its own spec_cls and db path |
| mission.py, debate.py, scoring.py | 100% — zero changes needed | An org_name string, a profile |
| agents/runtime.py | 100% — the whole LLM tool-calling loop | Nothing |
| agents/scouts.py | The Beat/run_scout mechanism | Its own BEATS dict + SPEC_SHAPE |