k-skill 的 seoul-subway-arrival 技能:通过 k-skill-proxy 实现首尔地铁实时到站查询
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
导读
seoul-subway-arrival是 k-skill 技能集中面向公共交通场景的 lookup 型技能,其核心价值在于:无需用户自行申请首尔开放数据广场(서울 열린데이터 광장)的 OpenAPI key,即可通过k-skill-proxy代理查询以车站为维度的实时列车到站信息,并自动汇总为简洁回答。本文将以该技能的指令文档为主体,结合k-skill-proxy的源码实现与测试用例,完整讲解代理解析顺序、/v1/seoul-subway/arrival端点用法、参数别名与默认值、响应字段含义以及常见失败模式,让读者既能直接上手调用,也能理解其底层代理与缓存机制。
技能定位:做什么、何时用
功能概述
根据 指令文档 的定义,该技能通过k-skill-proxy调用首尔开放数据广场的实时地铁到站信息 Open API,将"以车站为基准的预计到站列车信息"汇总成简明摘要返回给用户。技能元数据中将其归类为category: transit、locale: ko-KR、phase: v1,并声明了proxy与lookup两个 profile(见 skill.json),表明它是一个经由代理完成的只读查询型技能。
典型触发场景
指令文档给出了三类最典型的使用场景:
- "강남역 지금 몇 분 뒤 도착해?"(江南站还有几分钟到?)
- "서울역 1호선 도착 정보 보여줘"(给我看首尔站 1 号线的到站信息)
- "잠실역 곧 들어오는 열차 정리해줘"(整理一下蚕室站即将进站的列车)
这类需求统一落在 lookup 范畴内:检索数据、标注数据来源与时间基准,并把后续可能的行动连接到官方支持渠道即可,不涉及任何写操作或外部副作用。
前置条件与环境变量:零 key 依赖的设计
必填环境变量:无
这是该技能最具吸引力的设计点之一。指令文档明确写到:
필요한 환경변수: 없음(无需任何环境变量)。
KSKILL_PROXY_BASE_URL是可选配置,留空时使用默认托管代理https://k-skill-proxy.nomadamas.org。
用户不需要自行到首尔开放数据广场申请个人 OpenAPI key。/v1/seoul-subway/arrival路由由默认托管代理调用,upstream key 仅保存在代理服务器端。只有使用自建或第三方代理时才需要设置KSKILL_PROXY_BASE_URL。
可选前置条件
jq:可选,用于对 JSON 响应做格式化与字段提取,让摘要阶段更顺手;KSKILL_PROXY_BASE_URL:可选,仅在自托管/单独代理时设置。
Proxy 解析顺序(Proxy resolution order)
指令文档给出了严格的优先级规则:
KSKILL_PROXY_BASE_URL存在时,直接使用其值;- 不存在或为空时,使用默认托管代理
https://k-skill-proxy.nomadamas.org; - 仅在自行运营代理时,才在代理服务器端配置 upstream key。
其中最后一条是硬性约束:客户端/用户侧绝不直接接触 upstream key,密钥只存在于代理服务器环境变量中。这一约束与 k-skill 整体的密钥安全策略一致,相关安全要求可参考 docs/security-and-secrets.md。
快速开始:两个可复制的 curl 示例
基础查询
指令文档给出的最小可运行示例:
BASE="${KSKILL_PROXY_BASE_URL:-https://k-skill-proxy.nomadamas.org}" curl -fsS --get "${BASE}/v1/seoul-subway/arrival" \ --data-urlencode 'stationName=강남'要点说明:
${VAR:-default}语法正是"存在则用、为空则回退到托管代理"这一解析规则的 Bash 实现;--get --data-urlencode组合确保韩文站名(如 강남)被正确 URL 编码后以 GET 方式发送;-f使 HTTP 非 2xx 状态时 curl 以失败退出,-sS静默但保留错误输出。
调整响应范围
若需要控制返回条数,可用startIndex、endIndex调整。对应文档 docs/features/seoul-subway-arrival.md 中的示例:
BASE="${KSKILL_PROXY_BASE_URL:-https://k-skill-proxy.nomadamas.org}" curl -fsS --get "${BASE}/v1/seoul-subway/arrival" \ --data-urlencode 'stationName=서울역' \ --data-urlencode 'startIndex=0' \ --data-urlencode 'endIndex=4'四步工作流:从解析代理到谨慎汇报
指令文档将整个处理过程规范为四个步骤,是 Agent 执行该技能时的操作蓝图:
1. 解析代理基础 URL
按上文"Proxy 解析顺序"决定本次请求使用的BASE。
2. 查询官方到站端点
代理在服务端注入首尔实时地铁 API key,仅对外暴露"按站名查询实时到站"这一只读端点。调用方式即上文curl示例,必要时通过startIndex/endIndex控制返回范围。
3. 汇总响应
拿到响应后,优先只摘要以下字段(避免一次性输出过载):
- 호선(线路):如 2호선;
- 상/하행 또는 외/내선(上行/下行或外线/内线):方向信息;
- 첫 번째 도착 메시지(第一条到站消息);
- 두 번째 도착 메시지(第二条到站消息);
- 도착 예정 시간(预计到站时间,若有则注明秒)。
4. 对实时数据保持保守
实时数据可能在数秒内变化,因此回答中必须附带查询时点(조회 시점),让用户明确知道信息的时效边界。
完成判定(Done when)
一次合格的执行需同时满足:
- 请求车站的预计到站列车已被整理输出;
- 明确标注 live data 的基准时间;
- upstream key 未暴露给客户端。
响应结构与字段说明
虽然指令文档未贴出原始响应样例,但从代理实现与测试可以确认响应遵循首尔开放数据广场realtimeStationArrival的结构。代理测试(packages/k-skill-proxy/test/server.test.js)中构造的典型载荷如下:
{ "errorMessage": { "status": 200, "code": "INFO-000", "message": "정상 처리되었습니다." }, "realtimeArrivalList": [ { "statnNm": "강남", "trainLineNm": "2호선", "updnLine": "내선", "arvlMsg2": "전역 출발", "arvlMsg3": "역삼", "barvlDt": "60" } ] }字段与摘要项的对应关系一目了然:
| 字段 | 含义 | 对应摘要项 |
|---|---|---|
trainLineNm | 列车线路名 | 호선 |
updnLine | 上下行/内外线方向 | 상/하행 또는 외/내선 |
arvlMsg2 | 第二条到站消息 | 두 번째 도착 메시지 |
arvlMsg3 | 第三条到站消息(常为前一站站名) | — |
barvlDt | 预计到站剩余秒数 | 도착 예정 시간(초) |
此外,代理会在 JSON 中附加proxy元信息块,包含代理名称name、缓存状态cache.hit与 TTLcache.ttl_ms、请求时间requested_at(见 server.js),这也是"标注查询时点"的可靠数据来源。
源码级解析:代理端点是如何工作的
路由入口与参数归一化
/v1/seoul-subway/arrival路由定义在 packages/k-skill-proxy/src/server.js。请求先经normalizeSeoulSubwayQuery(server.js)做参数归一化:
- 站名支持三个别名:
stationName/station_name/station,取第一个非空值,缺失时报Provide stationName.; startIndex(别名start_index)默认0;endIndex(别名end_index)默认8;- 若
startIndex < 0或endIndex < startIndex,抛出Provide valid startIndex and endIndex.,由路由层转为 HTTP 400bad_request响应。
也就是说,指令文档中"用startIndex、endIndex调整响应范围"一句背后,是默认返回 0–8 共 8 条的规范行为。
upstream 请求与密钥注入
proxySeoulSubwayRequest(server.js)负责真正打向上游:
- 将上游地址拼为
{SEOUL_OPEN_API_BASE_URL}/api/subway/{apiKey}/json/realtimeStationArrival/{startIndex}/{endIndex}/{encodedStationName},其中apiKey来自代理服务器环境变量SEOUL_OPEN_API_KEY,只存在于服务端; - 请求使用
AbortSignal.timeout(20000),即 20 秒超时保护; - 若代理服务器未配置
SEOUL_OPEN_API_KEY,直接返回 HTTP 503 与{"error": "upstream_not_configured", ...},测试用例 server.test.js 验证了该行为。
缓存与幂等
路由在转发前先按route + 归一化参数生成缓存键并查询缓存,命中时直接返回并标记proxy.cache.hit: true;未命中则请求上游,成功(2xx)后写入缓存(TTL 由KSKILL_PROXY_CACHE_TTL_MS控制)。测试 server.test.js 用两种别名形式station=강남&start_index=0&end_index=8与stationName=강남各请求一次,断言fetchCalls === 1且第二次cache.hit === true,验证了参数别名归一化后共享同一缓存键的行为——这也能说明为何代理要容忍station这类非规范别名。
测试同时确认该端点无需代理鉴权即可公开调用(server.test.js),并验证了 upstream URL 以realtimeStationArrival/0/8/강남结尾的拼接格式。
失败模式与排查
指令文档列出了三类主要失败场景:
- Proxy upstream key 未设置:代理服务器缺少
SEOUL_OPEN_API_KEY,表现为 503upstream_not_configured;该情况只可能出现在自建代理侧,托管代理已配置好密钥; - Quota 超限:首尔开放数据广场对实时地铁 Open API 可能设有每日调用上限,命中限额时上游会返回错误;
- 站名写法不一致:例如"서울역"与"서울"等不同写法可能导致结果为空,文档建议核对站名官方写法。
延伸阅读与注意事项
- 代理的部署与全部环境变量说明见 docs/features/k-skill-proxy.md;
- 技能对应的功能指南(韩文)见 docs/features/seoul-subway-arrival.md,其中包含分步示例与"站名写法不同结果可能为空"等提醒;
- 公共配置与密钥安全基线可参考 docs/setup.md 与 docs/security-and-secrets.md;
- 指令文档特别提醒:endpoint path 可能随 API 版本调整,若调用失败,应回到数据集控制台核对最新样例 URL;
- 该技能经 k-skill CLI 分发,可用
npx -y @nomadamas/k-skill@0 instruct seoul-subway-arrival获取按当前运行时裁剪的最新指令,也可直接阅读 指令源文件 与仓库根目录下的 seoul-subway-arrival/SKILL.md。
小结
seoul-subway-arrival是一个典型的"代理托管密钥 + 只读 lookup"技能范本:技能侧只需处理stationName与索引范围两个输入,密钥安全由k-skill-proxy承担,配合参数别名归一化、服务端缓存与proxy元信息回填,既保证了调用者的零配置体验,也为"答案附带查询时点"提供了可靠依据。掌握它的调用参数与四步工作流,即可将该模式复用于 k-skill 中其他同类交通/城市数据查询技能。
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考