mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-06-24 02:04:11 +00:00
Agent environments (OpenClaw, Claude Code, Codex) assume users delegate credentials to the agent. sops+age added setup friction without real security benefit since the agent decrypts on every call anyway. New model: skills declare required env var names; how they are supplied is up to the agent (own vault, shell env, or ~/.config/k-skill/secrets.env as the default fallback with 0600 permissions). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
128 lines
4.9 KiB
Markdown
128 lines
4.9 KiB
Markdown
# 사용자 위치 미세먼지 조회 가이드
|
|
|
|
## 이 기능으로 할 수 있는 일
|
|
|
|
- 지역명/행정구역 힌트로 측정소 후보 찾기
|
|
- 단일 측정소 확정이 어려우면 후보 측정소 목록 반환
|
|
- 정확한 측정소명으로 재조회
|
|
- PM10, PM2.5, 등급, 조회 시각 요약
|
|
|
|
## 먼저 필요한 것
|
|
|
|
- [공통 설정 가이드](../setup.md) 완료
|
|
- [보안/시크릿 정책](../security-and-secrets.md) 확인
|
|
- `k-skill-proxy` 또는 에어코리아 OpenAPI key
|
|
|
|
## 필요한 환경변수
|
|
|
|
클라이언트 기본값:
|
|
|
|
- 기본 external proxy URL: `https://k-skill-proxy.nomadamas.org`
|
|
- `KSKILL_PROXY_BASE_URL` 는 override 가 필요할 때만 사용
|
|
|
|
프록시 없이 direct fallback 으로 쓸 때만:
|
|
|
|
- `AIR_KOREA_OPEN_API_KEY`
|
|
|
|
### Credential resolution order
|
|
|
|
1. **이미 환경변수에 있으면** 그대로 사용한다.
|
|
2. **에이전트가 자체 secret vault(1Password CLI, Bitwarden CLI, macOS Keychain 등)를 사용 중이면** 거기서 꺼내 환경변수로 주입해도 된다.
|
|
3. **`~/.config/k-skill/secrets.env`** (기본 fallback) — plain dotenv 파일, 퍼미션 `0600`.
|
|
4. **아무것도 없으면** 유저에게 물어서 2 또는 3에 저장한다.
|
|
|
|
## 입력값
|
|
|
|
- 기본: 지역명/행정구역 힌트(`regionHint`)
|
|
- 재조회: 정확한 측정소명(`stationName`)
|
|
|
|
## 기본 흐름
|
|
|
|
1. `KSKILL_PROXY_BASE_URL` 가 있으면 먼저 `k-skill-proxy` 의 `/v1/fine-dust/report` endpoint 를 호출합니다.
|
|
2. `regionHint` 가 들어오면 프록시는 먼저 시도명을 추출하고, `getCtprvnRltmMesureDnsty` 로 해당 시도 측정소 목록을 확보합니다.
|
|
3. region token 이 시도 내 실제 측정소명과 **유일하게** 대응하면 그 측정소로 `getMsrstnAcctoRltmMesureDnsty` 를 호출합니다.
|
|
4. 단일 측정소 확정이 어려우면 `ambiguous_location` 과 `candidate_stations` 를 반환합니다.
|
|
5. 클라이언트/사용자는 후보 중 정확한 측정소명으로 다시 `/v1/fine-dust/report?stationName=...` 를 호출합니다.
|
|
6. PM10, PM2.5, 등급, 조회 시점/조회 시각을 함께 요약합니다.
|
|
|
|
프록시 예시:
|
|
|
|
```bash
|
|
python3 scripts/fine_dust.py report --region-hint "서울 강남구" --json
|
|
```
|
|
|
|
후보 반환 예시:
|
|
|
|
```bash
|
|
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/v1/fine-dust/report' \
|
|
--data-urlencode 'regionHint=광주 광산구'
|
|
```
|
|
|
|
정확한 측정소명 재조회:
|
|
|
|
```bash
|
|
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/v1/fine-dust/report' \
|
|
--data-urlencode 'stationName=우산동(광주)'
|
|
```
|
|
|
|
원본 AirKorea endpoint 형태를 거의 그대로 쓰고 싶으면 passthrough endpoint 도 사용할 수 있습니다. 별도 client API 는 불필요하고, 프록시가 `serviceKey` 만 서버에서 주입합니다.
|
|
|
|
```bash
|
|
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/B552584/ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty' \
|
|
--data-urlencode 'returnType=json' \
|
|
--data-urlencode 'numOfRows=1' \
|
|
--data-urlencode 'pageNo=1' \
|
|
--data-urlencode 'stationName=강남구' \
|
|
--data-urlencode 'dataTerm=DAILY' \
|
|
--data-urlencode 'ver=1.4'
|
|
```
|
|
|
|
## 예시
|
|
|
|
지역 기반 direct fallback:
|
|
|
|
```bash
|
|
curl -sG "http://apis.data.go.kr/B552584/MsrstnInfoInqireSvc/getMsrstnList" \
|
|
--data-urlencode "serviceKey=${AIR_KOREA_OPEN_API_KEY}" \
|
|
--data-urlencode "returnType=json" \
|
|
--data-urlencode "numOfRows=50" \
|
|
--data-urlencode "pageNo=1" \
|
|
--data-urlencode "addr=서울 강남구"
|
|
```
|
|
|
|
실시간 측정값:
|
|
|
|
```bash
|
|
curl -sG "http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty" \
|
|
--data-urlencode "serviceKey=${AIR_KOREA_OPEN_API_KEY}" \
|
|
--data-urlencode "returnType=json" \
|
|
--data-urlencode "numOfRows=100" \
|
|
--data-urlencode "pageNo=1" \
|
|
--data-urlencode "stationName=중구" \
|
|
--data-urlencode "dataTerm=DAILY" \
|
|
--data-urlencode "ver=1.4"
|
|
```
|
|
|
|
helper script 반복 검증:
|
|
|
|
```bash
|
|
python3 scripts/fine_dust.py report \
|
|
--station-file scripts/fixtures/fine-dust-stations.json \
|
|
--measurement-file scripts/fixtures/fine-dust-measurements.json \
|
|
--region-hint "서울 강남구"
|
|
```
|
|
|
|
## fallback / 대체 흐름
|
|
|
|
- 지역명/행정구역을 먼저 받습니다
|
|
- 단일 측정소를 확정하지 못하면 후보 측정소 목록을 돌려줍니다
|
|
- 사용자는 후보 중 하나를 선택해 `stationName` 으로 다시 조회합니다
|
|
- 측정소 목록 API가 403 이어도 `getCtprvnRltmMesureDnsty` 와 측정소별 실측 API 조합으로 우회합니다
|
|
|
|
## 주의할 점
|
|
|
|
- 실시간 수치라 조회 시각을 같이 적어야 합니다
|
|
- PM10/PM2.5 값이 `-` 이거나 비정상이면 등급도 함께 재확인합니다
|
|
- API 가 `khaiGrade` 를 비워 보내면 통합대기등급은 `정보없음` 으로 표시합니다
|
|
- regionHint 는 자연어이므로 단일 측정소가 안 잡히는 경우가 자주 있습니다
|
|
- hosted 모드에서는 upstream AirKorea key 를 클라이언트에 배포하지 않고 proxy 에만 둡니다
|