A FastAPI backend that collects remote job listings, pre-filters them against your profile, and scores promising matches with Claude (Anthropic).
Users register, define a career profile, and pull listings from multiple sources into the database. A keyword filter and LLM analysis then answer “how well does this fit you?” with a 1–10 score, reasoning, and pros/cons.
- Job collection — Fetches remote jobs from RemoteOK and Remotive APIs, stores them in PostgreSQL (duplicates are skipped).
- Profile — Skills, target roles, exclusions, minimum salary, location preferences, and more.
- Pre-filter — Fast keyword-based screening before any LLM calls.
- Matching — New jobs that pass the filter are analyzed with Claude; scores and explanations are saved to
job_matches.
| Layer | Tools |
|---|---|
| API | FastAPI, Uvicorn |
| Database | PostgreSQL, SQLAlchemy |
| Auth | JWT (python-jose), bcrypt |
| LLM | Anthropic API (claude-haiku-4-5) |
| Job sources | RemoteOK, Remotive |
okuma-asistani/
├── main.py # FastAPI application
├── app/
│ ├── routers/ # auth, profile, jobs, matches
│ ├── models.py # User, UserProfile, JobPosting, JobMatch
│ ├── schemas.py # Pydantic models
│ ├── auth.py # JWT and password hashing
│ ├── database.py
│ └── services/
│ ├── job_collector.py
│ ├── keyword_filter.py
│ ├── matcher.py # Claude scoring
│ ├── match_orchestrator.py
│ └── sources/ # remoteok, remotive
├── .env # Secrets (not committed to git)
└── .gitignore
- Python 3.11+
- PostgreSQL
- Anthropic API key
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install fastapi uvicorn sqlalchemy psycopg2-binary python-dotenv \
anthropic bcrypt python-jose pydantic email-validator httpxCreate a .env file in the project root (it is listed in .gitignore):
DATABASE_URL=postgresql://user:password@localhost:5432/remote_job_agent
SECRET_KEY=a-long-random-production-secret
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=60
ANTHROPIC_API_KEY=sk-ant-...Security: Never commit
ANTHROPIC_API_KEYorSECRET_KEYto the repository. Rotate keys if they were ever exposed.
uvicorn main:app --reload- API: http://127.0.0.1:8000
- Swagger docs: http://127.0.0.1:8000/docs
flowchart LR
A[Register / Login] --> B[Create profile]
B --> C[POST /jobs/collect]
C --> D[GET /jobs/candidates]
D --> E[POST /matches/refresh]
E --> F[GET /matches]
POST /auth/register— create an accountPOST /auth/login— obtainaccess_token(useAuthorization: Bearer <token>on later requests)PUT /profile— skills, roles, exclusions, etc.POST /jobs/collect— pull jobs from sourcesGET /jobs/candidates— pre-filtered listings for your profile (no LLM)POST /matches/refresh?max_jobs=30— analyze selected jobs with Claude (uses API tokens)GET /matches?min_score=7— ranked matches by score
All protected endpoints require JWT (/auth/register and /auth/login are public).
| Method | Path | Description |
|---|---|---|
| POST | /auth/register |
Create user |
| POST | /auth/login |
Get token (form: username=email, password) |
| GET/PUT/DELETE | /profile |
Read / update / delete profile |
| POST | /jobs/collect |
Collect jobs from all sources |
| GET | /jobs |
List all jobs (paginated) |
| GET | /jobs/candidates |
Jobs that pass the keyword filter |
| GET | /jobs/filter-stats |
Filter statistics (debug) |
| GET | /jobs/{job_id} |
Single job |
| POST | /matches/refresh |
Run LLM analysis (limited by max_jobs) |
| GET | /matches |
Scored matches with job details |
For each job, Claude returns roughly:
- score — 1–10 (10 = strong apply recommendation)
- reasoning — short explanation
- pros / cons — highlights and caveats
POST /matches/refresh only processes jobs that have not been analyzed yet and pass the keyword filter; use max_jobs to control API cost.
Not specified yet.