Auto2offer 是一款面向个人求职者的 AI 招聘沟通协同智能体。输入岗位条件,它就自动帮你完成 「发现岗位 → 匹配评估 → 生成打招呼 → 安全校验 → 人工审批 → 发送消息 → 等待回复 → 会话应答」的完整闭环。
核心亮点:用 LangGraph 状态图编排 5 个 LLM 角色 Agent,配合 HITL 人工把关(HITL) 与 Guardrail 安全校验——把"该发的发、该拦的拦、该你确认的交给你确认",让 AI 替你跑通招聘沟通,但关键动作永远由你拍板。
- 🕵️ 岗位自动发现:按关键词/城市/学历/经验/薪资/Boss 活跃度/总条数搜岗,
job_agent先做 LLM 搜索规划再驱动工具清洗去重入库。 - 🎯 匹配评估(仅参考,非门禁):
match_agent输出 0~100 分 + 高/中/低,匹配度只作参考,绝不因分低终止任务。 - ✍️ 打招呼双来源:固定话术(免 Guardrail)/ 模型生成(需 Guardrail),支持
{公司}{岗位}逐岗替换。 - 🛡️ Guardrail 安全校验:确定性规则 + LLM 语义复核;拦截后 AI 源有限重试 / custom 源走人工。
- 🤝 HITL 人工审批:打招呼/回复默认停在审批收件箱,你批准才发送(幂等 · 限频 · 时间窗)。
- 💬 消息事件驱动会话:收到 HR 回复→按
task_id恢复原任务→conversation_agent意图识别+建议回复→审批→发送→继续等。 - 🧩 多 Agent + LangGraph:5 个真 LLM Agent;显式条件边(重试环/审批分流)+
Send并行扇出批量匹配(map-reduce)。 - 🖥️ 统一控制台:3 Tab(线索/审核/会话)+ 设置抽屉,零构建 ES 模块前端,直接对接
/api。 - 🧪 Mock 全链路离线可跑:无需任何真实凭据即可完整演示;也可切
openai_compatible+ BOSS 直聘真实账号。
输入岗位条件
↓
Job Agent(发现: search → clean → 去重 → 入库)
↓
Match Agent(规则初筛 + LLM 语义匹配 0~100, 仅参考)
↓
打招呼(Greeting Agent: 固定语/模型生成, {公司}{岗位} 替换)
↓
Guardrail(规则 + LLM 复核; PASS / BLOCK)
↓
HITL 人工审批 / AUTO(高风险动作人工把关)
↓
send_message(幂等 · 限频 · 发送窗口)
↓
WAITING_REPLY(Agent 挂起, 仅状态落库)
↓
HR 回复事件 → 恢复原 Task → Conversation Agent(意图+建议回复)
→ Guardrail → HITL/AUTO → 回复发送 → 继续监听
贯穿:Task 生命周期(创建/暂停/恢复/取消)、LangGraph SqliteSaver 断点恢复(进程重启不重跑)、全链路 Trace(agent/tool/llm/workflow, 含 prompt_version/model)。
| 角色 Agent | 职责 | 是否 LLM 真 Agent |
|---|---|---|
job_agent |
搜索规划 + 驱动发现工具 | ✅ LLM 规划 + 工具执行 |
match_agent |
岗位匹配打分(规则初筛 + LLM) | ✅ |
greeting_agent |
生成打招呼(custom 不走 LLM) | ✅ |
guardrail_agent |
安全校验(规则 + LLM 复核) | ✅ |
conversation_agent |
HR 消息意图识别 + 建议回复 | ✅ |
LangGraph 灵活条件/循环:
- 显式条件边:
match_node用语义路由_match_router;guardrail→greeting重试环、guardrail→send/END审批分流都在add_conditional_edges上显式可见。 - 中断/恢复:
interrupt()打 HITL/暂停/等消息断点,Command(resume=…)恢复。 - 并行扇出:
Send把每个岗位作为独立分支并行跑 Match Agent,batch_results用 reducer 汇聚(POST /api/jobs/batch-match)。
- 后端:FastAPI · LangGraph(SqliteSaver Checkpoint)· SQLAlchemy(SQLite WAL)· Pydantic v2
- Agent:Provider 注入 LLM(mock 默认 / openai_compatible);角色化 prompt + Structured Output
- 平台:PlatformAdapter(mock / boss + 通道:http / Playwright / nodriver chat)
- 前端:原生 ES 模块(零构建)· Lucide 内联图标 · theme/app 双 CSS
# 1) 安装依赖
pip install -r requirements.txt
# 2) 配置(默认 mock:LLM / 平台均为本地确定性实现)
cp .env.example .env
# 3) 启动
python run.py # → http://127.0.0.1:8000 (支持 --host/--port/--reload)
# 4) 运行测试
python -m pytest tests/ -q # 57 个用例(全链路 Mock 离线)页面与接口:
| 入口 | 说明 |
|---|---|
/ |
统一控制台:🔎 线索 · 📬 审核 · ✉️ 会话 + ⚙️ 设置 |
/api/docs |
OpenAPI 接口文档 |
/api/health |
健康检查 |
API 分组(/api/...):jobs(搜索/匹配/批量匹配/打招呼)· resumes(简历上传/当前)· candidate(画像/偏好)·
tasks(生命周期/checkpoints/Guardrail 处理)· messages(HITL 审批)· traces · conversations(消息事件/历史/结束)·
evaluation(Match 评测)· flow(全流程/回复监听)。
Mock 模式无需任何凭据即可全链路演示。切换 PLATFORM_ADAPTER=boss 连真实平台时,项目不做自动登录/验证码破解,登录态一律来自你自己账号的人工登录(Boss App 扫码 / 手机短信),再按通道选择保存方式:
# .env 切换真实平台
PLATFORM_ADAPTER=boss
BOSS_BASE_URL=https://www.zhipin.com
BOSS_CHANNEL=nodriver # 可选: http | browser | nodrivernodriver 通道的搜索/详情/发送共用同一个浏览器登录态,接入成本最低:
pip install nodriver # 额外依赖,Mock 模式不需要,故不在 requirements.txt
python scripts/boss_trust.py # ① 打开专用 Chrome 并只点击一次「登录」boss_trust.py不做任何自动登录:弹出的 Chrome 窗口里扫码/短信登录全部由你手动完成,完成后回终端回车,登录态即存入data/boss_profile(git 忽略);- 校验登录态与搜索链路:
python scripts/boss_probe.py --keyword AI --city 上海; - 发送链路自检(干跑、不输入不发送):
python scripts/boss_send_check.py --job-id <external_id>; - 登录失效/被风控要求重登时,重新运行一次
boss_trust.py即可,配置无需改动。
pip install playwright && python -m playwright install chromiumBOSS_CHANNEL=browser
BOSS_BROWSER_HEADLESS=false # 有头模式:便于人工处理扫码/验证
BOSS_BROWSER_PROFILE_DIR=./data/boss_profile- 登录态以「页面真实状态」为准:profile 未登录时,通道自动打开
login.zhipin.com等你人工扫码,登录成功后再重试原操作; BOSS_COOKIE_FILE注入仅作首次引导:profile 已有有效登录时不会覆盖,避免把过期 Cookie 写成“已登录”假象;- 登录失效(Cookie 里有
zp_at但服务端已吊销)会在操作后自动检测并引导重新扫码。
BOSS_CHANNEL=http
# 方式一:直接填你自己浏览器的登录态请求头(已登录后从 DevTools 网络请求复制)
BOSS_HEADERS_JSON={"User-Agent":"...","Cookie":"..."}
# 方式二(推荐):EditThisCookie 导出的 Cookie JSON 数组,优先级高于 headers 内 Cookie
BOSS_COOKIE_FILE=./data/boss_cookies.json- Cookie 文件格式为 EditThisCookie 浏览器扩展 Export 出的 JSON 数组,无需手工拼接;
- 刷新:重新登录后再次 Export 覆盖同一文件即可,
.env不用改(BOSS_COOKIE_FILE配置后优先于BOSS_HEADERS_JSON里的 Cookie); ⚠️ 纯 HTTP 最易被平台风控识别(如 code 37),自用请优先 browser / nodriver 真实浏览器通道。
安全边界:登录与关键操作保持人工 · 不破解验证码/不绕过风控 · 仅限自用账号 · 频率受限流 + 发送窗口 + HITL 把关。Cookie 属敏感凭据,务必只保存在本地(
data/已被 git 忽略)。
auto2offer/
├── run.py # uvicorn 启动入口(dev)
├── requirements.txt .env.example
├── app/
│ ├── config.py db.py models.py schemas.py factory.py main.py
│ ├── llm/ # Provider 注入: mock(默认) / openai_compatible
│ ├── platform/ # PlatformAdapter: mock / boss + 通道
│ ├── core/ # state · repository · guardrail_rules · task_manager
│ │ # tool_executor · trace · checkpointer · evaluation
│ ├── tools/registry.py # 8 个 Tool: search_jobs/get_job_detail/save_job/
│ │ # get_resume_profile/get_conversation_history/get_latest_message/
│ │ # send_message(幂等·HIGH_RISK)/save_checkpoint
│ ├── agents/ # prompts.py(5 角色,带版本) + worker.py(纯逻辑)
│ ├── graph/ # workflows.py(多图: 单图/发现/流水线/批量并行)
│ ├── runtime/ # AgentExecutor(Runtime 门面: run/resume/线程池/异常兜底)
│ ├── flow/ # pipeline.py(全流程风控) + monitor.py(HR 回复监听)
│ └── api/ # jobs/candidate/resumes/messages/tasks/traces/
│ # conversations/evaluation/flow/pages
├── static/ # app.html + theme/app.css + ES 模块 js/
├── scripts/ # boss_probe / boss_send_check / boss_trust
├── tests/ # 11 个文件 · 57 个用例(离线 Mock 全链路)
├── docs/ # 架构/Agent 配置/工具与工作流/测试/部署 等
└── data/ # 运行时 SQLite / checkpoints(git 忽略)
| 变量 | 默认 | 说明 |
|---|---|---|
DATABASE_URL |
sqlite:///./data/auto2offer.db |
业务库 |
CHECKPOINT_DB_PATH |
./data/checkpoints.db |
LangGraph 断点库 |
LLM_PROVIDER |
mock |
mock / openai_compatible |
PLATFORM_ADAPTER |
mock |
mock / boss(真实平台登录态获取见下文「🔑 真实平台登录态获取」) |
MATCH_THRESHOLD |
60 |
匹配参考阈值(仅展示,不终止) |
GUARDRAIL_MAX_RETRIES |
2 |
AI 源拦截自动重生成上限 |
SEND_WINDOW_START/END |
09:00/16:00 |
发送时间窗 |
SEND_DAILY_LIMIT |
30 |
每日发送上限 |
更多见
app/config.py;真实平台接入、Channel、风控节奏见docs/05_deployment.md。
python -m pytest tests/ -q- 覆盖:搜岗/清洗去重、匹配、打招呼双来源、Guardrail 拦截与重试、HITL 审批与幂等/限频、 Task 生命周期与 Checkpoint 断点恢复、流水线端到端、简历匹配、消息事件会话、评测、并行批量匹配。
- 默认 Mock 全链路离线,无需任何凭据。
- 单机单用户演示形态:无账号体系/多租户;异步基于进程内线程池 + SQLite Checkpoint,无重型中间件。
- 高风险动作默认人工把关:发送、会话应答需 HITL 审批;发送受窗口/日限额/冷却约束。
- 自动应答限定意图集合(面试邀约/岗位详情/薪资/地点/经验/婉拒/寒暄/其他),不承诺开放域全自动; 自动接受面试、薪资谈判、接受 Offer 等更高风险动作不在范围内。
- 不绕过风控:不做验证码破解;登录与关键操作保持人工(登录态获取方式见上文「🔑 真实平台登录态获取」)。真实平台接入仅限自用账号。
docs/01_architecture.md架构 ·docs/02_agent_config.mdAgent 配置docs/03_tools_workflow.md工具与工作流 ·docs/04_test_cases.md测试docs/05_deployment.md部署与配置 ·docs/06_ui_design.mdUI 设计
本项目仅用于个人求职者自用与学习研究,请遵守所接入招聘平台的服务条款。自动发送涉及真实外部动作, 请在了解并接受风险后使用;因使用本项目产生的一切后果由使用者自行承担。