Hermes Lead Researcher
How to read this doc
Start with §2 Architecture for the system diagram and component map, then §3 for the archetype brief format that drives everything. §5 covers the search-and-score pipeline in detail — the core logic. Skip §4 (Hermes config) unless you’re doing the setup. Markdown source: docs/devtasks/hermes-lead-researcher.md.
Contents
1. Context
The Relations CRM pipeline is live with kanban boards, table view, contact drawers, and custom fields per pipeline. The sourced_via column on relations_contacts tracks how each lead was discovered and renders as a chip on both kanban cards and the table view. Pipelines have a “Not a Fit” terminal stage for pre-outreach rejection.
The infrastructure is ready for leads. What’s missing is the supply side — an autonomous agent searching the web daily for candidates that match our archetype briefs, evaluating their portfolios, and writing qualified prospects into the pipeline for human review.
Hermes (Nous Research) is already running on Alpuca as a launchd daemon with built-in scheduled tasks, web search (DDGS backend), web page extraction, browser automation, batch processing, and external API tool calling. It supports Ollama, OpenRouter, Anthropic, and any OpenAI-compatible model provider.
Goal: ship a daily autonomous agent that reads briefs, searches the web, scores candidates, writes qualified leads to the Relations pipeline, deduplicates against existing contacts, and sends a Telegram summary.
2. Architecture
System overview
Component responsibilities
| Component | Role | Free? |
|---|---|---|
| Hermes daemon | Orchestrator, scheduler, tool host | Yes (self-hosted) |
| DDGS web_search | Candidate discovery queries | Yes (DuckDuckGo) |
| web_extract | Portfolio/profile page reading | Yes (built-in) |
| hermes-gemma4 (26B) | Fit scoring, brief interpretation, summaries | Yes (local Ollama) |
| Supabase PostgREST | Write leads to relations_contacts | Yes (existing) |
| Telegram bot | Daily summary notifications | Yes |
| Claude API (optional) | Quality upgrade for scoring when budget allows | Paid (~$0.02/lead) |
Model strategy
Default: hermes-gemma4 (26B) via local Ollama on Alpuca. Adequate for structured scoring against explicit criteria, search-query generation, and JSON output.
Upgrade path: change one config line to route scoring calls through the Claude API (Haiku for bulk, Sonnet for nuanced evaluation). No code changes — Hermes supports provider switching per-tool or per-task. Budget-gated: only enable when the team decides the local model’s miss rate justifies the cost.
3. Archetype briefs
Briefs live in obsid-sponic/archetypes/ as markdown files, one per pipeline. They’re part of the sponic git repo and editable in Obsidian by anyone on the team. The agent reads them from disk on each run — no database sync needed.
Brief format
Each brief is a markdown file with YAML frontmatter mapping it to a specific Relations pipeline and stage, followed by the ideal candidate profile, search queries, and a scoring rubric:
---
pipeline_slug: staff-recruiting
pipeline_id: <uuid>
default_stage_slug: sourced
default_stage_id: <uuid>
sourced_via: hermes-auto
search_cadence: daily
max_leads_per_run: 10
---
# Staff Recruiting — Archetype Brief
## Ideal candidate profile
- Role: Events & Marketing coordinator
- Location: Warsaw or remote-friendly in Poland
- Experience: 2-5 years in event management, hospitality, or creative agency
- Skills: social media management, vendor coordination, bilingual (PL/EN)
## Search queries
- "event coordinator Warsaw portfolio"
- "marketing manager hospitality Poland LinkedIn"
## Scoring rubric
| Signal | Weight | Notes |
|-----------|--------|---------------------------------|
| Location | 30% | Warsaw or remote-PL preferred |
| Experience| 25% | Events/marketing background |
| Portfolio | 20% | Active online presence |
| Language | 15% | Polish + English required |
| Culture | 10% | Creative, community-oriented |
## Disqualifiers
- No public portfolio or professional presence
- Only corporate/enterprise experience with no creative work
## Notes for scorer
Focus on candidates with visible creative output.
Frontmatter fields
| Field | Purpose |
|---|---|
pipeline_slug / pipeline_id | Which Relations pipeline to write to |
default_stage_slug / default_stage_id | Stage for new leads (e.g. “Sourced”) |
sourced_via | Value written to the sourced_via column. Default hermes-auto |
search_cadence | daily, weekly, or manual |
max_leads_per_run | Cap to prevent flooding the pipeline |
4. Hermes configuration
Tools to enable
- web_search — set backend to
ddgs(free, no API key). Brave and Tavily available as paid fallbacks. - web_extract — built-in readable-text extractor. Just needs enabling in config.
- Custom tool:
supabase_postgrest— new external API tool wrapping Supabase PostgREST calls for reading and writingrelations_contacts.
PostgREST tool definition
Endpoint: https://xumcmantignrocihtrdx.supabase.co/rest/v1/relations_contacts
Operations:
- Check for duplicates:
GET ?name=ilike.*{name}*&city=eq.{city}&select=id,name,city - Insert lead:
POSTwith the candidate’s extracted fields mapped to therelations_contactsschema — name, company, city, country, notes, tags, sourced_via, priority, linkedin_url, website, emails, and acustomJSON blob with fit_score, scoring breakdown, and source URL.
Scheduled task
Daily at 06:00 local time (before the team’s workday). The task reads all .md files from obsid-sponic/archetypes/, parses frontmatter for pipeline mapping and search config, runs the search-evaluate-write loop for each brief, and sends a Telegram summary.
Credential storage
- Supabase service_role JWT: stored in Hermes environment config (not in git). Obtain via
npx supabase projects api-keys. - Telegram bot token: existing Sponic bot token from Bitwarden (
DevOps-sponicgardencollection).
5. Search & scoring pipeline
Per-brief flow
- Parse brief — read markdown, extract frontmatter config and scoring rubric.
- Generate queries — use the brief’s search queries section. If fewer than 3 are listed, ask the model to generate additional ones from the ideal candidate profile.
- Search — run each query through
web_search(DDGS). Collect top 10 results per query. - Deduplicate URLs — merge results across queries, remove duplicate URLs.
- Extract — call
web_extracton each unique result to get readable page content. Skip pages that error or are under 100 words. - Score — pass page content + the brief’s scoring rubric to hermes-gemma4. Request structured JSON: candidate name, company, city, fit score (0–100), scoring breakdown, summary, disqualification flag, and contact signals.
- Filter — drop candidates with fit_score < 40 or disqualified flag set.
- Deduplicate against DB — check
relations_contactsvia PostgREST for existing contacts with similar name + city. Skip if already present. - Write — POST qualified leads with all extracted fields mapped to the schema.
- Collect stats — track per-brief: queries run, pages extracted, candidates scored, leads written, duplicates skipped.
Deduplication logic
Before inserting, query existing contacts by surname (case-insensitive partial match) and company within the target pipeline. If any result has a fuzzy name match (Levenshtein distance < 3 on surname) in the same city, skip the candidate and log the reason for the Telegram summary.
Rate limiting
| Tool | Limit | Delay |
|---|---|---|
| DDGS web_search | 30 searches per brief per run | 2s between searches |
| web_extract | 50 page extractions per run total | 1s between extractions |
| PostgREST writes | Capped by max_leads_per_run from brief | None |
6. Telegram notifications
After all briefs are processed, a single Telegram message goes to the Sponic ops channel with a per-pipeline breakdown: new leads written, candidates evaluated, duplicates skipped, and the top-scoring leads by name and fit score. Uses the existing Sponic Telegram bot — plain text with monospace sections for readability.
7. Monitoring & observability
Hermes has built-in run logging. Each scheduled task execution produces a log entry with timestamps, tool calls, model invocations, and errors, accessible via the Hermes UI on Alpuca.
Failure modes
| Failure | Mitigation |
|---|---|
| DDGS rate limit / block | Exponential backoff with 3 retries. Skip query and note in summary. Fall back to Brave (paid) if persistent. |
| web_extract timeout | 15-second timeout per page. Skip and continue. |
| Ollama down / model unloaded | Check availability before run. Telegram alert and skip if unavailable. |
| Supabase PostgREST error | Retry once. Buffer leads to local JSON and alert via Telegram if still failing. |
| Brief parse error | Skip malformed brief, log error, continue with others. |
Custom field tracking
Each lead includes metadata in the custom JSON column: fit score, search query that found it, source URL, Hermes run ID, full scoring breakdown, and evaluation timestamp. This lets the team see exactly why Hermes scored a lead the way it did.
8. Claude API upgrade path
When the team decides the local model’s quality isn’t sufficient: add the Anthropic API key to Hermes environment config and change the model provider for the scoring step from ollama/hermes-gemma4 to anthropic/claude-haiku (or anthropic/claude-sonnet for high-value pipelines). No code changes needed — Hermes handles provider switching natively.
Estimated cost: ~$0.01–0.03 per candidate evaluation with Haiku. At 25 candidates/day, that’s ~$0.25–0.75/day or ~$8–23/month.
9. Build phases
Phase 1: Archetype briefs (day 1)
- Create
obsid-sponic/archetypes/folder. - Write 3–4 starter briefs (staff-recruiting, location-partners, founder-network, fundraising) with pipeline IDs, scoring rubrics, and search queries.
- Verify briefs render correctly in Obsidian.
Phase 2: Hermes tool setup (days 2–3)
- Enable
web_search(DDGS backend) andweb_extractin Hermes config. - Create the
supabase_postgrestcustom tool with the service_role JWT. - Test each tool individually: search returns results, extract reads pages, PostgREST can read and write contacts.
Phase 3: Search-and-score task (days 4–6)
- Build the Hermes task script that reads briefs, runs searches, extracts pages, scores candidates, and outputs structured JSON.
- Test with a single brief end-to-end: brief in, scored candidates out.
- Tune the scoring prompt for structured output quality with hermes-gemma4.
Phase 4: Pipeline integration (days 7–8)
- Add deduplication logic (query existing contacts before insert).
- Wire up PostgREST writes with all field mapping.
- Configure the daily scheduled task in Hermes.
- Send test Telegram summaries.
- Run a full end-to-end: brief → search → score → write → notify.
Phase 5: Production hardening (days 9–10)
- Add error handling for all failure modes.
- Set up rate limiting and backoff.
- Run 3 consecutive daily runs and verify lead quality in the Relations UI.
- Document operational procedures (how to add briefs, adjust scoring, pause/resume).
- Evaluate whether Claude API upgrade is needed based on initial lead quality.
Build journal
No entries yet — appended by /feature, /journal, and /wrap.