# Position Select

> 智能选岗。帮考生按报考条件(学历/专业/政治面貌/应届/意向地区)筛选并推荐跨体系(公务员/事业编/国央企)可报职位,返回职位匹配报告与历年匹配岗位数据;简历完善时给出每个职位的匹配度。触发词:智能选岗、帮我选岗、我能报哪些岗位、有哪些岗位适合我、推荐岗位、职位匹配、选职位、哪些职位能报、给我推荐几个岗位、我这条件能报什么。

- Skill: `ahang1598/position-select` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ahang1598/position-select`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ahang1598/position-select/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ahang1598 (https://skillmd.com/u/ahang1598)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/ahang1598/position-select

---


# 智能选岗 Skill

指导 Agent 用 `position_select` 按报考条件(+登录用户简历)筛选/推荐职位,呈现「职位匹配报告」与「历年匹配岗位明细」。与 **resume skill** 配合:想要真实匹配度就先把简历核心字段补齐。

> 每个入参的取值、枚举、归一化要求都写在 `position_select` 的字段说明里(`filter` / `filter.conditions` 逐字段都有),本 skill 不重复。这里只写工具说明装不下的东西:**多轮编排、两个高频踩坑维度的判断表、出结果后的收尾动作**。

## 何时使用

- 「我是本科计算机,能报哪些岗位?」「帮我推荐几个适合的职位。」
- 「我这条件在山东有什么公务员/事业编岗位能报?」

## 入口:先探简历,按三分支走(核心编排)

用户发起选岗时,**先调 `user_resume_get`**,依据 resume skill 的「核心字段清单」自判完整度,分三种情况:

1. **核心简历齐全**(学历/专业/政治面貌/性别/应届/意向地区基本都有):直接 `position_select(…)` 出带匹配度的推荐,不打断用户。
2. **有简历但不完善**(缺部分核心字段):**先按已有信息推荐**(缺的维度按"不限制"处理),不在此处打断;补缺留到出结果后的「一轮收尾」统一做。
3. **核心简历缺失 / 空简历**:先转 **resume skill** 引导补齐核心字段(专业走归一化确认),再回来 `position_select`。

**选岗全流程都需要登录**:未登录时 `user_resume_get` / `position_select` / `position_render` 会直接返回 401,此时引导用户登录后再继续,不要改用其它工具绕开。

抽取条件时:能抽到几个传几个,**意向地区缺失可默认全国**(不传 `conditions.workAddress`),其它核心条件缺失先追问、不要臆造;整个 `filter` 不传即为纯语义检索。

## 地区:region 与 workAddress 的分工

这是最容易传错的维度。用户口中的地名(「我想在济南工作」「山东有什么岗」)几乎都是**意向工作地**,默认放 `conditions.workAddress`;`filter.region` 只回答另一个问题——**这场考试属于哪个省**,由 `examType` 决定该不该传:

| examType | filter.region | conditions.workAddress |
|---|---|---|
| 国考、军队文职 | **必须留空**(全国统一考试,不属于任何省) | 用户说的地名原样传(市/区都行) |
| 省考、事业单位联考/统考 | **只能传省份名**(`["山东"]`);用户只说了市/区就填其所属省 | 用户说的地名原样传(`["济南"]`) |
| 其它类型(事业单位单招、教师、医疗、国企…) | 用户明确在问某地的考试时可传;考试本身可能属市级,按用户说法传 | 用户说的地名原样传 |

- 「我想在济南考公务员」+ 判定为省考 → `region=["山东"]`(省份)、`workAddress=["济南"]`(意向工作地),两个都要传。
- 「国考山东有什么岗」→ `region` 不传、`workAddress=["山东"]`。
- 传错(国考带 region、省考 region 传市名)服务端会兜底纠正并记日志,但仍以正确传参为准。

## 专业:两段式,默认走语义、过宽才补硬筛

`majorIds` 与其它维度**语义相反**——学历/政治面貌/性别传了都会自动包含"不限"岗位、只会放宽;而 `majorIds` 传了会把「专业不限」的岗位**全部排除**。它是收窄手段,不是匹配增强手段,不要顺手带上。因此分两段:

- **第一轮**:专业信息拼进 `query` 做语义召回,**不传 `conditions.majorIds`**;精确的专业匹配度依赖**登录用户简历里的结构化专业**——这正是引导用户在 resume skill 里确认专业的价值。
- **第二轮**:第一轮结果明显过宽、混进大量与用户专业无关的岗位,或用户明确要求「只看我专业能报的」时,**保留原有条件再加上 `conditions.majorIds` 重查一次**收窄。取值口径见该字段说明。
- 补传后结果反而变空/过少,说明该批岗位多为「专业不限」,**退回不传 `majorIds` 的结果**并向用户说明。

## 返回结果与呈现

`position_select` 的 `items` 是选岗原料,**不要直接复述给用户**——挑定要推荐的岗位后调 `position_render` 渲染成岗位卡清单(可多轮 select 反复筛,最终只调一次 render),再在聊天区补一句整体结论。

- **竞争数据(进面分/报录比/报名人数)**随 `enrollStat`/`history` 一并返回,可以直接告诉用户,但批量选岗时不要逐个复述——这些由 `position_render` 在卡片上展示。
- **历年逐年明细页面放不下**,正适合放进该卡片的 `prompts` 追问按钮(如「分析这个岗位的竞争情况」);用户点了你再拿该岗位的 `history` 口述。
- `resumeAbsent=true` 或 `matchScore=0` 时服务端不展示匹配度徽标,你在聊天区提示一句「完善简历可看匹配度」。
- **职位库外的岗位**(猎聘/国央企社招等无 positionId 的)传不进渲染工具,仍用文字呈现,并说明这部分不在卡片清单里。
- `items` 为空:按「暂无匹配岗位,建议放宽条件(如去掉某限制、扩大意向地区)」引导重试。

多组岗位横向对比(如近三年国考按年份分组)改用 `position_group_render`,整套流程见 **mock-position-select skill**。

## 出结果后:一轮收尾(回存条件 + 补齐简历)

岗位结果**呈现完之后**再做,不打断选岗主流程。回存与补缺**合并成同一轮**,不要连着问两轮;用户不接话就结束,不追问第二次。

引导时**优先输出选择卡片让用户点选**(见 resume skill「交互形态」),减少手动输入。

### 1. 识别本轮条件里的简历字段并问是否保存

只对**用户自述的自身条件**提议保存:假设性("要是我是党员呢")、第三人称("帮我表弟看看")、纯考试维度(`examType`/`region`/`year`/`positionCode`/`fuzzyText`)一律不提。

| 本轮抽到的条件 | 对应简历字段 | 回存注意 |
|---|---|---|
| `conditions.eduBackground` + query 里的专业 | `eduBackgrounds` 段 | 专业必须经 `major_query` 归一化确认;该字段**全量覆盖**,先 `user_resume_get` 合并再存 |
| `conditions.politicStatus` | `politicStatus` | 值域不同需映射:团员→共青团员、民主党派→其他党派;**"党员"有歧义**,问一句是中共党员还是预备党员 |
| `conditions.gender` | `gender` | 直接对应 |
| 用户口述的应届/往届身份 | `graduated` | 选岗侧是"只看应届专项岗"的布尔开关,简历侧是 应届/非应届/择业期,**不要直接搬**,按用户原话判定 |
| `conditions.workAddress` | `intentionRegions` | 整体替换,存时传全量意向地区 |
| `conditions.basicWorkYear` | `basicWorkYear`(+ `basicExperience` 标准名) | |
| 用户口述的年龄/出生年份 | `birthday` | 按 resume skill 的日期规则归一化 |

- 把可回存的字段值**汇总成一次询问**(一张多选卡片:各字段值 + 全部保存 / 暂不保存),用户勾中的才写。
- **与简历已有值冲突**(简历是本科、用户说硕士)→ 先问是**新增一段学历**还是**更正原值**,不要静默覆盖;教育背景尤其要当心(全量覆盖会删掉未传的段)。
- 用户确认后转 **resume skill** 用 `resume_save` 写入,并复述存了什么。

### 2. 按本次结果补齐简历

引导范围 = **resume skill 的核心字段** + **本次结果里实际出现的场景型字段**:

- 核心字段缺失:生日(卡年龄上限)、学位(卡硕博岗)、毕业日期(卡应届判定)、意向地区、政治面貌、性别、应届身份、教育背景。
- 结果里出现限定岗时顺带引导对应场景型字段:限户籍岗→户籍;定向生源岗→生源地;退役军人/残疾人等专项岗→特殊身份;基层岗→基层经历 + 年限;民族限定岗→民族。
- 每项都说明**补了会怎样**(「补上生日能筛掉超龄岗」「补上学位才能判断这批硕士岗能不能报」),不要只是催填。
- 按收益排序,**一轮最多引导 3 项**;用户补完还想继续,再进下一轮并可直接重跑 `position_select` 看结果变化。

