← All docs

Hermes Lead Researcher

Agent reads archetype briefs, searches the web for matching candidates, and populates the Relations pipeline.
2026-05-22 Build plan ~1–2 week build Touches: Hermes · Alpuca · Supabase · Obsidian · Telegram

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
  2. Architecture
  3. Archetype briefs
  4. Hermes configuration
  5. Search & scoring pipeline
  6. Telegram notifications
  7. Monitoring & observability
  8. Claude API upgrade path
  9. Build phases
  10. Build journal

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

obsid-sponic/archetypes/ staff-recruiting.md archetype briefs (Obsidian markdown) location-partners.md synced via sponic git repo founder-network.md โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Hermes on Alpuca (scheduled task, daily) โ”‚ โ”‚ โ”‚ โ”‚ 1. Read briefs from disk โ”‚ โ”‚ 2. web_search (DDGS) per brief โ”‚ โ”‚ 3. web_extract on promising results โ”‚ โ”‚ 4. Score fit with hermes-gemma4 (local) โ”‚ โ”‚ 5. Deduplicate against existing contacts โ”‚ โ”‚ 6. POST to Supabase PostgREST โ”‚ โ”‚ 7. Send Telegram summary โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ–ผ โ–ผ relations_contacts Telegram bot (Supabase Postgres) (summary message)

Component responsibilities

ComponentRoleFree?
Hermes daemonOrchestrator, scheduler, tool hostYes (self-hosted)
DDGS web_searchCandidate discovery queriesYes (DuckDuckGo)
web_extractPortfolio/profile page readingYes (built-in)
hermes-gemma4 (26B)Fit scoring, brief interpretation, summariesYes (local Ollama)
Supabase PostgRESTWrite leads to relations_contactsYes (existing)
Telegram botDaily summary notificationsYes
Claude API (optional)Quality upgrade for scoring when budget allowsPaid (~$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

FieldPurpose
pipeline_slug / pipeline_idWhich Relations pipeline to write to
default_stage_slug / default_stage_idStage for new leads (e.g. “Sourced”)
sourced_viaValue written to the sourced_via column. Default hermes-auto
search_cadencedaily, weekly, or manual
max_leads_per_runCap to prevent flooding the pipeline

4. Hermes configuration

Tools to enable

  1. web_search — set backend to ddgs (free, no API key). Brave and Tavily available as paid fallbacks.
  2. web_extract — built-in readable-text extractor. Just needs enabling in config.
  3. Custom tool: supabase_postgrest — new external API tool wrapping Supabase PostgREST calls for reading and writing relations_contacts.

PostgREST tool definition

Endpoint: https://xumcmantignrocihtrdx.supabase.co/rest/v1/relations_contacts

Operations:

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

5. Search & scoring pipeline

Per-brief flow

  1. Parse brief — read markdown, extract frontmatter config and scoring rubric.
  2. 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.
  3. Search — run each query through web_search (DDGS). Collect top 10 results per query.
  4. Deduplicate URLs — merge results across queries, remove duplicate URLs.
  5. Extract — call web_extract on each unique result to get readable page content. Skip pages that error or are under 100 words.
  6. 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.
  7. Filter — drop candidates with fit_score < 40 or disqualified flag set.
  8. Deduplicate against DB — check relations_contacts via PostgREST for existing contacts with similar name + city. Skip if already present.
  9. Write — POST qualified leads with all extracted fields mapped to the schema.
  10. 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

ToolLimitDelay
DDGS web_search30 searches per brief per run2s between searches
web_extract50 page extractions per run total1s between extractions
PostgREST writesCapped by max_leads_per_run from briefNone

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

FailureMitigation
DDGS rate limit / blockExponential backoff with 3 retries. Skip query and note in summary. Fall back to Brave (paid) if persistent.
web_extract timeout15-second timeout per page. Skip and continue.
Ollama down / model unloadedCheck availability before run. Telegram alert and skip if unavailable.
Supabase PostgREST errorRetry once. Buffer leads to local JSON and alert via Telegram if still failing.
Brief parse errorSkip 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)

Phase 2: Hermes tool setup (days 2–3)

Phase 3: Search-and-score task (days 4–6)

Phase 4: Pipeline integration (days 7–8)

Phase 5: Production hardening (days 9–10)

Build journal

No entries yet — appended by /feature, /journal, and /wrap.