oll.am · Techniques teardown · agentic job search + alert · 2026-07-10

The best agentic job search + alert — the techniques.

The proven OpenCLAW loop · Postiz's tool-seam · the matching engine that beats keyword alerts. Not a build plan — a study of the techniques that make an agentic scout good, each traced to code we already run or a source we can cite, and mapped onto the oll.am stack.
Re-aim, don't rebuild Hybrid retrieve-then-rerank Cited rationale + abstention Never auto-apply
Part of the oll.in thread. The positioning study picks the wedge (agentic-not-toolbox); the agent-seam plan says the scout is a driven pattern, not a new backend. This page goes one level lower — the techniques themselves: what, concretely, makes an agentic job scout better than a keyword alert, sourced from the loop we run (OpenCLAW), a well-behaved tool-seam (Postiz), and the matching-engine literature.

1The engine you already own

OpenCLAW is already a live agentic "watch → score → draft → digest on a schedule" engine — the distribution scout that surfaces Reddit/HN lead-gen threads. It's a proven 8-stage loop, and it's ~90% reusable for jobs: only the source-watchers and the draft step change. Don't build a job scout — re-aim the distribution scout.

Stage 1Heartbeat dispatcherFire-window eval; double-fire prevented via last_fired
Stage 2·3 — CHANGESWatch sourcesKeyword pre-filter (~100 → ~20 items)
Stage 4LLM relevance-scoreThreshold ≥ 7 to survive
Stage 5Dedup + per-entity cap30-day rolling window
Stage 6 — CHANGESDraftJob digest entry, not a reply
Stage 7Telegram digest4096-char smart split
Stage 8Persist seen-stateBounded store (<2KB live) — closes the loop

The two accent-2 bordered boxes are the only stages that change for jobs. Everything else — heartbeat, scoring gate, dedup, digest, persistence — is verbatim.

StageWhat it doesJob re-aim
1Heartbeat dispatcher — evaluate the fire-window; skip if already fired this windowverbatim
2·3Watch sources with a keyword pre-filterswap watchers
4LLM relevance-score; only ≥ 7 continuesverbatim (new rubric)
5Dedup + per-entity cap so one source can't floodverbatim
6Draft the surfaced itemdigest entry
7Telegram digest with 4096-char smart splitverbatim
8Persist seen-stateverbatim

The thesis

Don't build a job scout — re-aim the distribution scout. A schedule-driven watch→score→draft→digest agent is a solved problem in our own codebase. The novel work is not the loop; it's the two swapped stages and the quality of the scoring — which is what the rest of this page is about.

2Techniques that make the loop good — from OpenCLAW

Code-verified against the live scout. These aren't aspirations — each is running today in the distribution scout and carries over unchanged.

Keyword pre-filter before the LLM

A cheap keyword pass cuts ~100 candidate items to ~20 before any model call — roughly 80% token savings on the expensive stage.

Why it matters · cost discipline for a capped scout

Context-aware scoring, not generic

The model scores "does THIS role fit THIS narrative profile", not "is it on-topic." That's the watching-not-searching insight: a scout evaluates fit against a rich profile, where a keyword alert only matches strings.

Why it matters · narrative-fit is the whole differentiator

30-day rolling dedup + double-fire idempotency

Bounded state (live seen-stores are <2KB) means no repeats, no wasted tokens, and idempotency within a fire-window even if the heartbeat double-fires.

Why it matters · bounded, repeat-free, idempotent — for free

Per-entity context file as the single source of truth

The deep structured profile lives in one editable markdown file, never hardcoded. A ## Status field can block output — a one-line kill switch that needs no deploy.

Why it matters · profile is data, editable + gate-able

Telegram digest with smart splitting + heartbeat fire-windows

The daily-alert delivery already works: fire-windows control cadence, and a 4096-char smart split keeps long digests intact across Telegram's message cap.

Why it matters · the alerting channel is already built

3Tool-seam design — from Postiz

Postiz (gitroomhq/postiz-app, code-verified) is the reference for a well-behaved agentic tool seam — how an MCP tool set should be shaped so the runtime, not prose, keeps the agent honest.

ONE write tool, MANY read tools — declared in MCP annotations

Read tools carry readOnlyHint:true, idempotentHint:true; the single world-changing tool carries readOnlyHint:false, openWorldHint:true — so the runtime can auto-gate the one dangerous call without bespoke logic.

Why it matters · the runtime gates by annotation, not by hope

Discovery-then-act, ENFORCED BY SCHEMA

The write tool requires real IDs the agent can only obtain from the read/discovery tools — so it physically cannot skip discovery. In their words: it "forced the LLM always to call it before." Correctness by construction, not by instruction.

Why it matters · sequencing is a schema constraint, unskippable

Description-as-instruction

Tool descriptions carry worked examples + self-correction directives — "if the tools return errors, rerun with the right parameters, don't ask again." The description IS the prompt.

Why it matters · behaviour ships with the tool, not a separate system prompt

Human-approved side effects via a type enum

A single type field (draft | schedule | now) — draft is the safe default, with strict validation applied only on the real-publish path. No separate confirm tool; the safety is a parameter.

Why it matters · one tool, graduated safety — approval is in-band

Never throw — return errors as corrective next-step data

Errors come back as structured "here's what to do next" payloads, not exceptions. This keeps the agent self-correcting instead of dead-ending on a stack trace.

Why it matters · a self-healing loop needs data, not tracebacks

Batch to beat the rate limit

The write tool takes an array — a week × N channels is one request against the API cap, not N requests. Batching is a first-class parameter shape.

Why it matters · one call amortizes the whole plan against the limit

Auth resolved once at the seam

Identity lives in context, never in tool args — the agent can't spoof a user by passing an ID. This matches our token-identity-not-entitlement rule exactly: the JWT sub is the identity, the tool never asks for it.

Why it matters · the agent can't act as someone it isn't

Postiz technique → job-scout tool

Postiz techniqueJob-scout tool
Read-only + idempotent discovery toolslistOpenings / getApplicationSchemareadOnlyHint:true, idempotentHint:true
ONE world-changing write toolsubmitApplicationopenWorldHint:true, needs IDs from discovery
type enum, draft as defaulttype: 'draft' | 'submit' — strict checks ONLY on submit
Array-batched writesubmit an array of applications = one call against the cap
Errors as corrective dataa bad ID returns "call listOpenings first", not a throw

Crucial house note — the mapping is the lesson, not the plan

The submitApplication row above shows the shape — but for OUR job scout we register NO submit tool at all. Discover / rank / draft only. The agent cannot auto-apply by construction: there is no world-changing tool in its set. Postiz teaches how to gate the dangerous call; we take it one step further and don't hand the agent the dangerous call.

Honesty note — small local fixes to make later

  • Postiz ships 10 tools on current main, not 9 — earlier docs undercounted.
  • The env var is API_LIMIT (default 30 in .env.example, 90 in code) — our deploy README + skill use the wrong name POSTIZ_API_LIMIT. A small local truth-up, not a blocker.

4The matching engine that beats keyword alerts

This is the differentiator. A keyword alert matches strings; a matching engine reasons about fit. Six techniques, each cited — most beat a naive baseline by a measured margin.

Why keyword / boolean alerts fail

Synonymy kills recall (the same role under a different title never matches), polysemy kills precision (one keyword hits three unrelated fields). One market fragments into disconnected vocabularies plus noise. (ScienceDirect · Weaviate)

Why it matters · the baseline is structurally broken, not just weak

Two-stage retrieve-then-rerank

Cheap bi-encoder recall (~top 100) → expensive cross-encoder / LLM listwise rerank on just those. RankGPT-style listwise beats pointwise reranking. (sbert · RankVicuna, arXiv 2309.15088)

Why it matters · precision where it's affordable, recall where it's cheap

Hybrid, not pure-semantic

Dense + BM25 fused with RRF. Keep BM25 for exact tokens — company names, framework versions, certifications — that dense pooling averages away. BEIR showed dense often loses cross-domain. (TianPan · BEIR)

Why it matters · exact tokens matter, and dense forgets them

Structured profile beats raw-résumé dumps

The strongest cited number here: structured decomposition scores 0.84 human correlation vs 0.67 for a single-LLM raw-text pass (+0.17). Separate Extractor → Evaluator; structure the job side too (must-have / good-to-have / screening as typed arrays). (arXiv 2504.02870)

Why it matters · +0.17 correlation, for free, from structure alone

Scoring rubric with cited rationale

A fixed rubric reused per candidate; typed extractive quotes per criterion — quote the requirement → quote the evidence → met / partial / gap. Reason BEFORE scoring, small integer scales (0/1/2), structured JSON out. (arXiv 2601.08654 · Monte Carlo)

Why it matters · a score you can audit line-by-line, not a vibe

Honest abstention over fabricated fit

An explicit "none qualifies" option plus a relevance FLOOR — abstaining below a support threshold cut false attributions ~45%. Quote-then-answer grounding; self-consistency as an uncertainty signal. Reduces, does not eliminate — validate on the real model. (Claude docs · arXiv 2504.14856)

Why it matters · a scout that lies about fit is worse than none

5Sources, legally

The matching engine is only as good — and as safe — as its input. The rule: use what employers and portals publish for machines, and never touch what they contractually forbid.

schema.org/JobPosting JSON-LD — the clean spine

Curated employer career pages emit JSON-LD the employer published for Google for Jobs. Its required-field contract IS your ingest schema — structured, sanctioned, free. (schema.org · Google docs)

Why it matters · the employer already structured it for a crawler

Free aggregator APIs for breadth

Arbeitnow (free, no-auth, DACH/Switzerland) as the zero-cost seed; Adzuna + Jooble free tiers layered on. Verify each portal's rate limits, CH coverage, and commercial terms first. (Arbeitnow)

Why it matters · breadth with a signed contract, at zero cost

NEVER scrape LinkedIn / Indeed

hiQ WON on CFAA but LOST on breach-of-contract — permanent injunction, $500k, company dead. Indeed's ToS bans bots. The safe envelope = logged-out + machine-published JSON-LD + sanctioned APIs; GDPR still applies to any personal data. (hiQ v. LinkedIn · Indeed legal)

Manual paste ingestion

An MCP add_posting(url_or_text) tool keeps the value of jobs.ch / portal-alert emails without touching them programmatically — the human pastes, the engine ingests. Zero ToS surface.

Why it matters · portal value without a portal contract

6Alerting that doesn't fatigue

A scout that pings on every posting trains the user to ignore it. The alerting discipline is as important as the matching.

Scheduled DIGEST, not per-posting pings

Alert fatigue trains users to tune out; irregular sending drives more unsubscribes than frequent. A daily digest is the workhorse; let the user set the frequency. (Atlassian · MailerLite)

Why it matters · cadence, not volume, is what burns trust

Tier the digest

"Apply-grade" (act now — top slot, optional real-time breakthrough) vs "watch" (FYI). One list, two urgencies — the user's attention goes to the top tier.

Why it matters · scarcity of the top slot IS the signal

Near-duplicate fingerprinting, not exact match

50–80% of listings are reworded reposts. Shingling + MinHash; canonicalize to the employer ATS (Greenhouse / Ashby) for one true identity + an honest first-seen date. (Textkernel)

Why it matters · one job = one alert, with an honest "first seen"

Email default, Telegram for breakthroughs

Email = low-friction universal default + an audit trail. Telegram = opt-in high-priority breakthrough (<1s, bypasses spam) for the apply-grade tier only.

Why it matters · match the channel to the urgency

7Agentic ops — the AIOps demo layer

The scout is also a portfolio artifact: an agent that runs unattended needs cost control, self-monitoring, a human gate, and a feedback loop. This is the AIOps layer.

Cost gradient — the biggest lever

Cheap-wide recall first (JSON-LD/API ingest + BM25 + dense), expensive-narrow last. A FrugalGPT cascade escalates only low-confidence cases; hard-cap the top-N to the frontier model. Batch API (async, 50% off) + prompt-cache the stable rubric prefix (0.1× reads) → ~95% combined cut. Tier Haiku → Sonnet → Opus. (FrugalGPT 2305.05176 · Batch · Prompt caching)

Why it matters · the single biggest determinant of whether a scout is affordable to run

Self-monitoring

Treat "expected data, got zero" (a 200 OK with an empty body) as an ERROR. Watch volume-drop vs baseline; validate schema/fields; a consecutive-error circuit breaker per source; end-to-end run tracing with token/cost (Langfuse / Phoenix); golden-set drift detection on prompt changes.

Why it matters · a silent-failing scout is the worst kind — it looks fine

Human-in-the-loop — NO auto-apply

A propose-then-wait interrupt before any side-effecting call; gate ONLY the irreversible. Offer approve / reject / EDIT — the edit is the genuine-interest signal, richer than a click.

Why it matters · the human's edit is both the safety gate and the best label

Feedback loops

Thumbs / save / dismiss = strong sparse labels; clicks / dwell = noisy abundant (absence ≠ dislike). Periodically re-weight + re-rank; add diversity to avoid a filter bubble; keep the inferred profile editable; cold-start via attribute / pairwise elicitation + content-based CV→JD match.

Why it matters · the scout gets sharper the longer it's used

Leading tools 2026 — the reputation-safe lane vs the trap

Reputation-safe lane: Teal / Jobscan / Careerset — curate + match-score + track, helping the human apply better.

Reputational trap: Sonara / LazyApply auto-appliers — mass-apply ≈ 0.1% success, LazyApply blacklisted on LinkedIn. This is worse in small, recruiter-dense Switzerland: the same limited recruiter pool notices the spray. Our stance: discover + rank + alert, never auto-apply.

8The through-line + the build delta

Two disciplines both sources — OpenCLAW and the matching literature — converge on. Get these right and the scout is good; get them wrong and it's an expensive keyword alert.

① A COST GRADIENT

Cheap-and-wide first, expensive-and-precise last. Keyword pre-filter and hybrid recall are pennies; the cross-encoder / frontier rubric runs on only the survivors. Every stage earns its cost by narrowing the next.

② POINT AT TEXT BEFORE JUDGING

Force the model to quote before it scores — extract-then-judge, typed quotes per rubric line, relevance floors — and license it to say "not enough here." Explicit abstention over fabricated fit.

Plus the product stance borrowed from Postiz's type enum: the agent searches / ranks / drafts autonomously, but the ONE irreversible act is gated — and in our case not even registered. Never auto-apply.

Build delta on the oll-am stack

REUSE live

  • The OpenCLAW loop — watch→score→draft→digest, running today
  • oll-model gateway — cost-cap + provider switch + batch/cache
  • oll-memory — pgvector hybrid retrieval (dense + keyword, RRF)
  • The oll-mcp agent seam
  • Telegram delivery

ADD new

  • A structured narrative profile
  • JSON-LD career-page + Arbeitnow source-watchers
  • Hybrid dense + BM25 + RRF recall → cross-encoder / LLM rerank with cited rationale + abstention
  • Cross-source near-dup dedup
  • A feedback loop + relevance calibration

Single next action

Author the structured narrative profile + wire the first JSON-LD source-watcher + the cited-rationale scoring rubric onto the proven loop. No submit tool, ever.

§Sources & grounding

OpenCLAW and Postiz techniques are code-verified against the live distribution scout and gitroomhq/postiz-app respectively — not projections. Matching-engine numbers are cited inline: structured decomposition 0.84 vs 0.67, abstention-floor ~45% fewer false attributions, listwise reranking, FrugalGPT cascade. Legal sourcing rests on hiQ v. LinkedIn and schema.org/JobPosting.

Honesty line holds: reductions ("~45%", "~80%", "~95%") are directional and model-dependent — validate on the real model, not the paper. No auto-apply, ever: the agent discovers, ranks and drafts; the human reviews and sends. No "Swiss-hosted" / data-residency claim. Postiz counts (10 tools, API_LIMIT) noted as a local truth-up in §3.