You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AI-powered job hunting assistant — automates job search, company research, cover letter writing, and application tracking via a LangGraph conversational agent.
Features
Feature
Description
Job Search
Search LinkedIn, Indeed, BOSS 直聘, Lagou by keyword + location + job type via DuckDuckGo
Company Research
Research target company overview, culture (Glassdoor), recent news, and funding
Cover Letter Generation
Generate personalized cover letters/emails using the user's stored profile
Application Tracking
Record and manage job applications with status lifecycle (applied → interviewing → rejected / offer)
Daily Auto-Search
Save search preferences; a daily 08:00 cron fetches new listings into "Today's Picks"
Long-Term Memory
Cross-session memory of user skills, experience, and preferences for personalized responses
Custom System Prompt
Per-user editable system prompt with a modal UI
Streaming Chat
Real-time SSE streaming with live tool-call cards in the frontend
flowchart LR
START(["START"]) --> ChatNode
subgraph Graph["LangGraph StateGraph"]
ChatNode["💬 chat\nLLM call · load long-term memory\napply system prompt"]
ToolNode["🔧 tool_call\ndispatch to named tool\ncollect ToolMessages"]
END_N(["END"])
ChatNode -->|"tool_calls present"| ToolNode
ToolNode -->|"results → goto chat"| ChatNode
ChatNode -->|"no tool_calls"| END_N
end
subgraph Tools["Available Tools (Function Calls)"]
T1["🔍 job_search_tool\nkeywords · location · job_type\nDuckDuckGo multi-site search\n(LinkedIn / Indeed / BOSS / Lagou)"]
T2["🏢 company_research_tool\ncompany_name · aspects\noverview · culture · news · funding"]
T3["✉️ cover_letter_tool\njob_title · company · jd · tone\nLLM-generated letter using user profile"]
T4["📋 application_tracker_tool\nadd · list · update · delete\nPostgreSQL-backed CRUD"]
T5["⚙️ job_preferences_tool\nkeywords · location · job_type\nsave daily auto-search config"]
T6["🌐 duckduckgo_search_tool\nquery\ngeneral web search"]
end
ToolNode --> T1
ToolNode --> T2
ToolNode --> T3
ToolNode --> T4
ToolNode --> T5
ToolNode --> T6
subgraph LLMSvc["LLMService — Circular Fallback"]
M1["gemini-2.5-flash\n(primary)"]
M2["gemini-2.0-flash"]
M3["gemini-1.5-flash"]
M1 -->|"fail + retry"| M2
M2 -->|"fail + retry"| M3
M3 -->|"fail + retry"| M1
end
subgraph Mem["Long-Term Memory (mem0 + pgvector)"]
MR["retrieve\nbefore each invoke\nsemantic search on user_id"]
MU["async update\nafter response completes"]
end
ChatNode <--> LLMSvc
ChatNode --> MR
ChatNode -.->|"background task"| MU
Loading
Quick Start
Prerequisites
Python 3.13+
PostgreSQL with pgvector extension
Docker + OrbStack (optional, for containerized setup)
Setup
# 1. Install dependencies
uv sync
# 2. Configure environment
cp .env.example .env.development
# Edit .env.development with your keys# 3. Run (development)
make dev
make docker-run # development
make docker-run-env ENV=staging # staging
make docker-logs ENV=development
make docker-stop ENV=development
Monitoring stack:
Prometheus: http://localhost:9090
Grafana: http://localhost:3000 (admin / admin)
API Reference
Auth
Method
Path
Description
POST
/api/v1/auth/register
Register a new user
POST
/api/v1/auth/login
Login and get JWT token
GET
/api/v1/auth/sessions
List user sessions
DELETE
/api/v1/auth/sessions/{id}
Delete a session
Chat
Method
Path
Description
POST
/api/v1/chatbot/chat
Send message, get response
POST
/api/v1/chatbot/chat/stream
SSE streaming response
GET
/api/v1/chatbot/history
Get conversation history
DELETE
/api/v1/chatbot/history
Clear conversation history
Job Data
Method
Path
Description
GET/PUT
/api/v1/preferences
Get/update daily search config
GET
/api/v1/listings
List today's auto-discovered jobs
GET/POST/PATCH/DELETE
/api/v1/applications
Application tracker CRUD
Settings
Method
Path
Description
GET/PUT
/api/v1/settings/system-prompt
Get/update custom system prompt
Health
Method
Path
Description
GET
/health
Health check with DB status
GET
/metrics
Prometheus metrics
Model Evaluation
make eval# interactive mode
make eval-quick # non-interactive, default settings
make eval-no-report # skip JSON report
The evaluator fetches Langfuse traces from the last 24 hours, scores them with OpenAI structured output against metric prompts in evals/metrics/prompts/*.md, and writes a JSON report to evals/reports/.
To add a custom metric, create a new .md file in evals/metrics/prompts/ — it is auto-discovered at runtime.