---
tags: [research, robeing, skills, skill-docs, context-injection, orchestration]
---

# 스킬 계약 문서 기반 컨텍스트 오케스트레이션 리서치

## 관련 문서
- [스킬 계약 문서 기반 컨텍스트 오케스트레이션 아이디어](../ideas/260314_스킬_계약_문서_기반_컨텍스트_오케스트레이션_아이디어.md)
- [스킬 계약 및 실행 원칙](../../book/300_architecture/316_skill-contract-and-execution-principles.md)
- [OpenClaw 기반 로빙 개선 아이디어](../ideas/260309_openclaw_기반_로빙_개선_아이디어.md)
- [로빙 에이전트 루프와 스킬 훅 구조 아이디어](../ideas/260312_로빙_에이전트루프와_스킬훅_구조_아이디어.md)

## 목적
- `rb8001`이 직접 API 호출 세부를 많이 알고 있는 현재 구조를, 스킬 계약 문서 기반 오케스트레이션 구조로 옮길 수 있는지 확인합니다.
- 이번 문서는 `ideas`에서 남긴 세 질문을 닫기 위해 현재 코드와 문서 자산을 기준으로 사실을 정리합니다.
- 구현 순서와 실제 작업 단위 고정은 다음 `plans`에서 다룹니다.

## 조사 질문
1. 현재 `rb8001` 의도분석 출력에서 typed contract로 끌어올릴 최소 필드는 무엇인가
2. 현재 스킬 목록 중 `SKILL.md` 1차 대상은 무엇이며, 공통 계약과 개별 계약은 어디서 갈리는가
3. 후보 스킬 축소에 필요한 최소 기준은 무엇이며, 지금 코드와 문서에서 어디까지 이미 존재하는가

## Facts

### 1. 현재 로빙에는 스킬별 `SKILL.md`가 없습니다
- `/home/admin/robeing` 기준으로 `SKILL.md` 파일은 검색되지 않았습니다.
- 현재 스킬 문서 자산은 각 저장소의 `README.md`가 중심입니다.
- 확인된 대표 문서:
  - `skill-calendar/README.md`
  - `skill_email/README.md`
  - `skill-slack/README.md`
- 즉 현재는 스킬이 실행 서비스로는 존재하지만, 계약 문서 SSOT는 아직 없습니다.

### 2. `rb8001`은 아직 스킬 URL과 엔드포인트 규칙을 직접 알고 있습니다
- `rb8001/app/router/router.py`에서 `service_endpoints`는 `email`, `news`, `slack`, `state`를 직접 가집니다.
- 같은 파일의 `_get_service_url_for_skill()`는 `SkillType.EMAIL`, `NEWS`, `SLACK`, `LLM`, `ANALYSIS`만 매핑합니다.
- `_call_service()`는 URL 문자열과 포트값을 보고 `skill-email`, `skill-news`, `skill-slack`를 판별하고, 액션에 따라 실제 엔드포인트를 직접 조립합니다.
- 예:
  - email: `send`, `messages`, `process`
  - news: `/api/news/search`
  - slack: `/api/v1/send`, `/api/v1/digest/`, `/api/v1/actions/extract`
- 즉 현재 본체는 "어떤 스킬을 고를지"뿐 아니라 "각 스킬을 어느 URL로 어떤 path에 호출할지"까지 직접 알고 있습니다.

### 3. 캘린더는 일반 스킬 매핑과 별도 경로로 붙어 있습니다
- `rb8001/app/services/skills/calendar_skill.py`는 `SKILL_CALENDAR_URL`을 읽고 `/api/events`를 직접 호출합니다.
- `rb8001/app/router/calendar_handler.py`는 `CalendarSkill()`을 직접 생성해 `get_events`, `create_event`, `delete_event`를 사용합니다.
- 즉 캘린더는 `router.py`의 일반 skill routing 표준 밖에 있는 별도 결합 경로입니다.

### 4. 의도분석과 스킬선택을 위한 typed model의 뼈대는 이미 있습니다
- `rb8001/app/services/brain/intent/schemas.py`에는 `IntentGoal`, `ActionPlan`, `SkillSequence`가 `Pydantic BaseModel`로 정의돼 있습니다.
- `IntentGoal` 필드:
  - `category`
  - `description`
  - `confidence`
  - `raw_intent`
  - `context_hints`
- `DecisionEngine._build_intent_pipeline_sync()`와 `_build_intent_pipeline()`는 `IntentAnalyzer -> ActionPlanner -> SkillSelector` 3단계 메타데이터를 `execution_plan["intent_pipeline"]`에 붙입니다.
- 즉 `의도 -> 행동 -> 스킬 후보`를 구조화해서 다루는 골격은 이미 코드에 있습니다.

### 5. 하지만 현재 typed model만으로는 스킬 계약까지 닿지 않습니다
- `ActionPlanner`는 `IntentCategory`를 보고 `ActionType` 목록을 만듭니다.
- `SkillSelector`는 `ActionPlan`을 받아 `"CALENDAR"`, `"EMAIL"`, `"TOOL"`, `"LLM"` 같은 내부 스킬명과 액션명으로만 바꿉니다.
- `SkillSelector.available_skills`는 현재 가능한 액션을 코드 상수로 직접 들고 있습니다.
- 이 구조에는 아래 계약 정보가 없습니다.
  - 호출 조건
  - 금지 조건
  - 필수 입력
  - 실패 기준
  - 권한/승인 조건
  - 검증 방법

### 6. 의도분석을 더 구조화할 수 있는 선행 단서는 이미 별도 경로에 있습니다
- `rb8001/app/services/llm/intent_parser.py`는 `{"intent", "slots", "confidence", "clarify"}` JSON 계약을 가정합니다.
- 즉 현재 로빙 내부에는 이미 자유서술이 아니라 구조화된 의도/슬롯 출력을 상상하는 코드가 있습니다.
- 다만 이 계약은 `brain/intent/schemas.py`의 `IntentGoal`과 아직 통합돼 있지 않습니다.

### 7. 현재 스킬 문서 자산은 계약 문서라기보다 README 수준입니다
- `skill-calendar/README.md`는 포트, API 개요, 환경변수, 실행 예시가 있습니다.
- `skill_email/README.md`는 역할, 주요 엔드포인트, 필수 환경변수, 헬스체크가 있습니다.
- `skill-slack/README.md`는 역할, 일부 API, 필수 환경변수, 트러블슈팅이 있습니다.
- 하지만 공통 형식은 없고, 아래 항목은 스킬마다 들쭉날쭉합니다.
  - 언제 선택해야 하는지
  - 언제 사용하면 안 되는지
  - 승인 필요 여부
  - 실패 분류
  - 완료 판단
  - 검증 방법

## Interpretation

### 1. 의도분석 typed contract는 새로 발명하는 게 아니라 기존 두 구조를 합치면 됩니다
- 현재 `IntentGoal`은 추상 카테고리 중심입니다.
- 현재 `intent_parser.py`는 `intent + slots + confidence + clarify` 중심입니다.
- 따라서 로빙이 실제로 필요한 최소 의도분석 계약은 아래처럼 합치는 쪽이 가장 자연스럽습니다.
  - `task_type`: 추상 작업 성격
  - `goal`: 사용자가 원하는 최종 결과
  - `slots`: 날짜/시간/대상 같은 추출 입력
  - `candidate_skills`: 후보 스킬 목록
  - `needs_human_confirmation`: 승인 필요 여부
  - `confidence`: 신뢰도
- 결론적으로 typed contract의 최소 필드는 완전 신설보다 `IntentGoal + intent_parser JSON`의 결합으로 정리하는 편이 맞습니다.

### 2. 1차 `SKILL.md` 대상은 캘린더, 이메일, 슬랙이 가장 적절합니다
- 이유:
  - 현재 `rb8001`이 직접 호출 세부를 많이 알고 있는 대표 스킬입니다.
  - 세 스킬 모두 기존 README가 있어 계약 문서로 끌어올릴 재료가 이미 있습니다.
  - 사용 흐름 예시가 명확합니다.
    - `calendar`: 조회/등록/삭제
    - `email`: 읽기/쓰기
    - `slack`: 전송/다이제스트/액션 추출
- `news`, `rag-file`, `publish`, `embedding`도 중요하지만, 오케스트레이션 브레인 전환을 보여주기 위한 첫 샘플로는 위 세 개가 더 직접적입니다.

### 3. 공통 계약과 개별 계약의 경계도 이미 보입니다
- 공통 계약:
  - 목적
  - 호출 조건
  - 금지 조건
  - 입력 계약
  - 출력 계약
  - 권한
  - 실행 방법
  - 실패 기준
  - 완료 기준
  - 검증 방법
- 개별 계약:
  - `calendar`: 시간 범위, all-day 규칙, provider, 재인증 필요 실패
  - `email`: 수신/발신 구분, 토큰 파일, watch 갱신, user_id 필수
  - `slack`: channel/thread/message 대상, 봇 토큰/헤더, 전송/요약/액션 추출 분기
- 즉 공통 틀은 `316_skill-contract-and-execution-principles.md`에 있고, 실제 서비스별 변형만 각 `SKILL.md`로 분리하면 됩니다.

### 4. 후보 스킬 축소 기준은 이미 코드에 일부 있고, 계약 기준으로 끌어올리면 됩니다
- 현재도 `IntentCategory -> ActionType -> SkillSequence` 변환이 있으므로 "의도에 따라 후보를 좁힌다"는 생각 자체는 이미 구현되어 있습니다.
- 다만 지금은 후보 축소 기준이 대부분 코드 상수와 문자열 규칙에 머물러 있습니다.
- 리서치 기준으로 최소 축소 기준은 아래 네 가지면 충분합니다.
  - 작업 성격(`task_type`)
  - 필수 능력(`required_capabilities`)
  - 권한/승인 필요 여부
  - 금지 조건
- 이 네 가지가 있으면 전체 스킬 문서를 주입하지 않고도 "이번 요청에서 읽어야 할 후보 스킬"을 좁힐 수 있습니다.

### 5. 현재 가장 큰 구조 문제는 스킬 선택보다 스킬 계약 소유권이 코드에 있다는 점입니다
- 지금도 `DecisionEngine`은 후보 스킬 비슷한 것을 만들 수 있습니다.
- 하지만 최종 실행 단계에서 `router.py`와 `calendar_skill.py`가 호출 경로, 엔드포인트, 헤더, 기본 다운그레이드 동작을 직접 소유합니다.
- 따라서 이번 문제의 본질은 "스킬 선택 기능이 전혀 없다"가 아니라, "스킬 계약이 문서가 아니라 코드 분기 안에 묻혀 있다"에 가깝습니다.

## Unresolved
- `task_type`와 `goal`을 어떤 Enum/문자열 체계로 고정할지
- `candidate_skills`를 내부 스킬명(`CALENDAR`) 기준으로 둘지, 저장소/서비스명(`skill-calendar`) 기준으로 둘지
- `needs_human_confirmation`를 의도분석 단계에서 바로 판단할지, 스킬 계약과 결합해서 후단에서 올릴지
- `news`, `rag-file`, `publish`, `embedding`를 1차에 함께 넣을지 2차로 미룰지

## 결론
- 현재 로빙은 이미 `Pydantic` 기반 의도분석 모델과 3단계 메타데이터 구조를 일부 가지고 있으므로, 의도분석 typed contract를 도입할 기술적 바탕은 충분합니다.
- 현재 로빙에는 `SKILL.md`가 하나도 없고, 스킬 계약은 `README`와 `rb8001` 코드 분기 안에 흩어져 있으므로, 본체를 오케스트레이션 브레인으로 바꾸려면 계약 문서 SSOT가 먼저 필요합니다.
- 1차 `SKILL.md` 대상은 `skill-calendar`, `skill_email`, `skill-slack`이 가장 적절합니다.
- 다음 `plans`는 아래를 고정하면 됩니다.
  - 의도분석 최소 typed contract 필드
  - 1차 `SKILL.md` 대상 3개
  - 공통 계약 템플릿
  - `rb8001`에서 후보 스킬 계약만 읽도록 바꾸는 로더 경계

## 한 줄 결론
- 이 문제는 새 개념 발명이 아니라, 이미 있는 `typed intent skeleton`과 `직접 호출 중인 스킬들` 사이에 `SKILL.md 계약 계층`을 넣어 `rb8001`의 역할을 실행기에서 오케스트레이션 브레인으로 되돌리는 작업으로 해석하는 것이 맞습니다.
