On-demand Scout service (replaces the nightly aggregator): - FastAPI agent-mesh service; card name "matchmaking-service" (HTTP /a2a/tasks + Redis-stream worker matching the sibling-service pattern) - run_search: parallel multi-board sweep (Naukri/blackfalcondata + Foundit + LinkedIn), city-filtered at the board, cheapest-per-result first - per-board adapters + normalizers -> ScoutJob with rich read-only details and offsite apply links; recall mode + MVQ guard - result cache for dev replay ($0); per-board cost knobs; retry-on-5xx - research/: engine design, board cost economics, India-actor shortlist, POC
47 lines
2.4 KiB
Markdown
47 lines
2.4 KiB
Markdown
# matchmaking-v2 (Scout)
|
|
|
|
Fresh, **on-demand** matchmaking service replacing the dead nightly aggregator. Same agent-mesh
|
|
mold as the other GrowQR services (FastAPI · a2a card · /a2a/tasks · orchestrator-routed). Not a
|
|
drop-in — it keeps the existing 4 skills working and **adds new actions from scratch**.
|
|
|
|
## Layout
|
|
```
|
|
app/
|
|
main.py FastAPI app (card + /a2a/tasks + /api/v1/health), lifespan worker
|
|
config.py lean settings (no corpus DB, no scrape schedule)
|
|
a2a/ card.py (discovery), auth.py (bearer), tasks.py (orchestrator entry)
|
|
agent/session.py Session: on_session_start / on_user_action dispatch ← the brain
|
|
adk/worker.py Redis-Streams worker (graceful no-op without Redis)
|
|
api/v1/health.py /api/v1/health
|
|
engine/
|
|
board_adapters/ ScoutPrefs → Apify actor inputs (Naukri-first, verified maps)
|
|
... the §3 cascade (normalize→filter→utility→fusion→rerank) lands here
|
|
contracts/ Pydantic contracts (user_context, transport, …) — added per slice
|
|
research/ docs/ (ENGINE_DESIGN, SIGNAL_AUDIT_V2, ENGINE_INPUTS, …) + poc/ (auto-apply)
|
|
```
|
|
|
|
## Contract (how it connects)
|
|
Frontend `useAgentSession` (page `"job-matching"`) → orchestrator (routes by card `name`
|
|
= `matchmaking-service`) → `POST /a2a/tasks {action, params, user_context}` → `Session` pushes
|
|
`agent_data{action,data}` → orchestrator → frontend `latestData[action]`.
|
|
|
|
**Skills:** existing `get_feed · sync_preferences · record_feedback · get_opportunity_detail`;
|
|
new `run_search · tailor_resume · submit_application · get_apply_proof` (stubbed). Each new action
|
|
needs: card skill (here) + orchestrator action-map entry + frontend `sendAction` wiring.
|
|
|
|
## Run (local)
|
|
```bash
|
|
pip install -r requirements.txt
|
|
uvicorn app.main:app --reload --port 8006
|
|
# card: GET http://localhost:8006/.well-known/agent-card.json
|
|
# health: GET http://localhost:8006/api/v1/health
|
|
# action: POST http://localhost:8006/a2a/tasks (Bearer dev-a2a-key)
|
|
```
|
|
|
|
## Build order (full-stack slices)
|
|
0. ✅ scaffold (this) — bootable skeleton, contract wired, handlers stubbed.
|
|
1. on-demand `run_search` — board_adapters → Apify → engine cascade → ranked feed (+ frontend wire).
|
|
2. feedback labels + `record_feedback`. 3. `tailor_resume`. 4. `submit_application` + `get_apply_proof`.
|
|
5. cut over from old `:8006`, decommission corpus.
|
|
```
|