TaskManager Device Context Planning Spec
이 문서는 A2A planner가 DevicePlanningContext와 DeviceAgent TaskManager를 함께 사용할 때 제품/사양적으로 무엇을 만들 수 있는지 정리한다. 핵심은 기기가 단순 명령 수신기가 아니라, 현재 상태를 제공하고 장기 task를 관리하며 callback을 통해 planner가 다시 판단할 수 있는 실행 파트너가 된다는 점이다.
1. 한 줄 결론
TaskManager와 device context가 안정적으로 연결되면 A2A는 “발화를 token으로 변환하는 라우터”가 아니라 현재 상태를 보고, 작업을 등록하고, 진행 중 이벤트를 관찰하고, 필요한 순간에만 재계획하는 기기 작업 planner가 된다.
2. 현재 구현 경계
현재 스케줄링은 세 층으로 존재한다. 제품 사양에서는 이 층들을 구분해야 한다.
| 층 | 현재 역할 | 의미 |
|---|---|---|
| Cloud SCH | 시간, 반복, 조건 표현을 구조화하고 schedule 종류와 실행 owner를 결정 | 자연어 schedule intent와 slot을 만드는 계층 |
| On-device product scheduler | 반복 규칙과 제품 고유 schedule을 등록, 수정, 삭제, 조회 | 사용자가 장기간 관리하는 제품 예약 자산 |
| DeviceAgent TaskManager scheduler | 일회성 task/workflow를 SCHEDULED로 보존하고 실행 시점에 admission |
가까운 미래의 지연 실행과 임의 복합 workflow 예약 |
| Workflow condition wait | task callback 또는 device state가 충족될 때 다음 step을 연다 | 시간 예약이 아닌 event 기반 연속 실행 |
SCH는 자연어 소유 family이고 특정 저장소의 이름이 아니다. Cloud SCH는 발화의 의미를 해석한 뒤 native_product, deferred_task, event_continuation 중 하나를 선택한다. 기기 고유 schedule과 TaskManager schedule은 같은 “예약” 표현을 쓰지만 수명주기와 사용자 기대가 다르므로 하나의 저장소로 합치지 않는다.
2.1 2026-07-26 구현 정합 상태
| 경계 | 현재 상태 | 판정 |
|---|---|---|
| Cloud SCH schema/prompt | schedule_kind를 세 값으로 구조화하고 반복성, 일회성 미래 실행, callback 연속 실행을 의미로 구분 |
구현 |
| Cloud SCH -> ODL case-2 | schedule_execution_payload.schedule_kind를 보존 |
구현 |
| On-device payload parser | ScheduleExecutionPayload.scheduleKind로 owner 태그 수신 |
구현 |
| MR6 TaskManager | 누락값은 deferred_task로 정규화하고 다른 두 owner는 unsupported_schedule_kind로 거부 |
구현 |
| TaskManagerClient/monitor/worker | schedule API와 중첩 trigger 전달, 허용 command catalog |
구현 및 단위 테스트 |
| On-device owner dispatch adapter | 단일 deferred_task의 상대시간을 절대 triggerAtMs로 확정하고 scheduleTask로 변환 |
구현 및 실기기 등록 검증 |
| On-device workflow dispatch adapter | 복합 deferred_task를 범용 scheduleWorkflow로 변환하고 room/capability를 resolve |
부분 구현 |
event_continuation |
active workflow의 depends_on/completion callback으로 유지 |
부분 구현 |
| 예약 record boot restore | MR6 durable store에서 같은 scheduleId 복원 |
실기기 검증 |
| exact alarm/due admission | MR6 소스와 단위 테스트 | 실기기 실행 검증 필요 |
schedule_kind가 전달된다는 사실과 해당 owner의 저장소에 실제 등록됐다는 사실은
구분한다. 단일 고정 청정 지연 예약은 Cloud 의미값에서 MR6 scheduleTask까지
연결됐지만, 복합 workflow와 제품 반복 예약의 owner adapter는 아직 남아 있다.
이 구간을 문자열별 분기표로 만들지 않고 capability catalog와 planner metadata로
변환해야 한다.
3. Planner가 사용할 수 있는 context
DeviceAgent DevicePlanningContextProvider 기준으로 planner가 활용할 수 있는 대표 정보는 아래다.
| context 영역 | planner 활용 | 사용자 응답 원칙 |
|---|---|---|
location |
현재 공간, 스테이션 도킹 여부, 이동 전제 확인 | “스테이션에 있습니다”, “공간1에 있습니다”처럼 자연어로만 말한다 |
map.rooms |
공간명/area id/position id resolve, 복합 이동 workflow 생성 | ID를 직접 말하지 않는다 |
air_quality |
공기질 설명, 상태 기반 청정 제안, 조건부 실행 판단 | 원시 key 이름 대신 좋음/보통/나쁨과 근거만 요약한다 |
cleaning |
청정 중 여부, pause 상태, 기존 청정 정지 필요 여부 | 실행 전 “현재 청정 중이라 멈추고 진행합니다” 같은 안내 가능 |
movement |
이동 중/일시정지/차단 상태, 재시도 가능성 판단 | 실패 reason과 다음 행동을 짧게 설명한다 |
battery |
저전력 시 장기 작업 차단 또는 스테이션 복귀 제안 | 안전상 필요한 경우에만 언급한다 |
task_manager |
현재 작업, queue, running task, scheduled task count | “진행 중인 작업은 없습니다/있습니다”처럼 요약한다 |
capabilities |
현재 가능한 기능 후보 제한 | 불가능한 기능은 실행하지 않고 이유를 설명한다 |
중요한 금지사항은 raw context를 TTS로 그대로 노출하지 않는 것이다. air_quality.co2, current_room_id, context 기준, capabilities.room_cleaning=true 같은 표현은 디버그 UI에는 표시할 수 있지만 사용자 음성 응답에는 쓰지 않는다.
4. 제품적으로 가능한 기능
4.1 현재 상태 Q&A
기기가 자신의 상태를 설명한다.
| 발화 | 기대 동작 |
|---|---|
너 지금 어디 있어? |
현재 위치 또는 스테이션 도킹 상태를 자연어로 응답 |
지금 작업 중이야? |
TaskManager running/queue 상태 응답 |
공기질 어때? |
공기질 센서 값을 자연어 등급과 짧은 판단으로 응답 |
배터리 괜찮아? |
장기 작업 가능 여부를 포함해 응답 |
이 영역은 대부분 ODL -> DEF 성격이다. device context를 조회하지만 side effect는 없다.
4.2 즉시 복합명령
여러 기기 동작을 하나의 workflow로 묶는다.
| 발화 | 기대 workflow |
|---|---|
공간4 갔다가 공간1로 가서 청정하고 스테이션 복귀해줘 |
이동 -> 청정 -> 이동 -> 청정 -> 복귀 |
공간1로 가서 바이탈사인 켜줘 |
이동 완료 확인 -> 기능 실행 |
청정 멈추고 공간2로 가줘 |
기존 청정 정지 -> 이동 |
이 영역은 ODL -> ODL이다. planner는 목표 순서를 만들고, TaskManager는 각 step의 실제 완료와 실패 reason을 관리한다.
4.3 조건부 실행
context를 먼저 읽고 조건이 맞으면 실행한다.
| 발화 | 기대 동작 |
|---|---|
스테이션에 있으면 청정 켜봐 |
도킹 여부 확인 -> 가능하면 실행, 부적절하면 이유 설명 |
공기질 안 좋으면 청정해줘 |
공기질 판단 -> 실행 또는 미실행 사유 응답 |
작업 중 아니면 공간1로 가줘 |
TaskManager 상태 확인 -> 이동 |
이 영역은 DEF/ODL -> ODL 혼합이다. 조건이 device context에 의해 결정되므로 TaskManager admission 전 context refresh가 중요하다.
4.4 작업 스케줄링
즉시 실행하지 않고 task/workflow를 예약한다.
| 발화 | schedule 종류 | 기대 동작 |
|---|---|---|
20분 뒤에 청정해줘 |
deferred_task |
상대 시간을 절대 triggerAtMs로 확정한 뒤 scheduleTask 등록 |
내일 공간4 갔다가 공간1 청정하고 복귀해줘 |
deferred_task |
일회성 scheduleWorkflow 등록 |
매일 밤 10시에 안방 청정해줘 |
native_product |
반복 규칙을 지원하는 제품 schedule 등록 |
청정이 끝나면 스테이션으로 복귀해 |
event_continuation |
cleaning 완료 callback을 dependency로 갖는 workflow |
예약된 작업 목록 보여줘 |
query | 제품 예약과 지연 실행을 출처별로 합쳐 자연어 요약 |
방금 예약한 작업 취소해줘 |
cancel | 최근 예약의 owner와 schedule id를 확인해 해당 저장소에서 취소 |
이 영역은 SCH -> ODL/TaskManager handoff다. Cloud SCH가 schedule slot과 종류를 결정하고, 실행 owner가 등록/조회/취소를 담당한다. 실행 시점에는 deferred_task가 원래 ODL task/workflow로 TaskManager queue에 admission된다.
4.4.1 시간 표현을 구분하는 기준
| 표현 | 의미 | 처리 |
|---|---|---|
20분 뒤에 청정해줘 |
시작 시각 지연 | deferred_task |
20분 동안 청정해줘 |
실행 지속 시간 | 즉시 ODL task의 duration/완료 조건 |
20분마다 확인해줘 |
반복 규칙 | native_product, 지원 capability가 없으면 미지원 또는 확인 |
청정 끝나면 복귀해 |
선행 task 완료 조건 | event_continuation |
단기와 장기를 분 단위 threshold 하나로 나누지는 않는다. 반복성, 사용자 관리 기대, 제품 고유 capability, 임의 workflow 여부를 함께 본다. 다만 deferred_task는 일회성만 허용하고, 반복·수정 가능한 예약은 product scheduler가 소유한다.
4.4.2 상대시간과 멱등성 계약
상대시간 발화는 각 계층이 현재 시각을 다시 추론하지 않도록 의미값을 보존한다.
Cloud SCH relative_delay_seconds
-> case-2 trigger.relative_delay_ms
-> on-device triggerAtMs = now + relativeDelayMs
-> MR6 SCHEDULED record
중복 방지는 발화 문자열이 아니라 request_id를 기준으로 한다. local shim은 짧은
전송 중복을 막고, on-device는 같은 request/session을 전달하며, MR6는 같은
request_id의 예약 record가 있으면 deduplicated=true와 기존 scheduleId를
반환한다. 네트워크 retry나 Cloud 재추론이 있어도 actuator 예약은 한 건이어야 한다.
조회 명령의 source는 두 의미를 분리한다. command envelope의 source는 호출
주체이고, payload의 source는 사용자가 명시한 record filter다. envelope source를
암묵적 filter로 사용하면 API/monitor에서 생성 주체가 다른 예약이 사라져 보이므로
금지한다.
4.5 작업 중 개입
진행 중인 task에 사용자가 개입한다.
| 발화 | 기대 동작 |
|---|---|
잠깐 멈춰 |
현재 workflow pause 또는 movement/cleaning pause |
계속해 |
pause 상태 resume |
그 작업 취소해 |
active task/workflow cancel |
다음 공간은 가지 말고 복귀해 |
현재 workflow 변경 또는 replan |
이 영역은 callback과 active workflow state가 있어야 안정된다. 정상 진행 event는 로컬에서 처리하고, FAILED, BLOCKED, PAUSED, NEEDS_USER_INPUT처럼 판단이 필요한 event만 Cloud replan 후보가 된다.
4.5.1 실행 중 동일 작업의 NOOP 계약
Planner가 새 단일 device task를 만들었더라도, device_context.task_manager.active_tasks의
현재 step이 같은 taskMethod로 이미 RUNNING이면 Cloud dispatch preflight에서 새
task를 보내지 않는다. 이때 기존 workflow owner와 active_workflow_id를 유지하고
device_task_noop.code=ACTIVE_TASK_ALREADY_RUNNING을 반환한다. 사용자에게는 같은
작업이 이미 진행 중이라고 알린다.
이 판정은 발화 문자열이 아니라 구조화된 실행 의미를 비교한다. 현재 구현은 파라미터가
없는 단일 task에만 적용해 서로 다른 목적지나 설정값을 가진 작업을 잘못 합치지 않는다.
예를 들어 복합 workflow의 현재 step이 returnToStation인 동안 다시 복귀 명령이
들어오면 중복 task를 만들지 않는다. 2026-07-30 실기기 검증에서는 중복 제출 시
RETURN_TO_STATION_POLICY_NOT_ALLOWED와 원 workflow 중단이 발생했던 반면, 이
preflight 적용 후 단일 복귀 task는 STARTED -> COMPLETED와 물리 완료 callback까지
정상 수신됐다.
4.6 선제 대응
사용자가 묻기 전에 기기가 제안하거나 경고한다.
| trigger | 가능한 반응 |
|---|---|
| 공기질 악화 | “공기질이 나빠져서 청정을 시작할까요?” |
| 장시간 이동 실패 | “이동이 막힌 것 같습니다. 다시 시도할까요?” |
| 낮은 배터리 + 장기 workflow | “배터리가 낮아 먼저 스테이션으로 돌아가는 게 좋습니다” |
| 예약 작업 실행 시점 + 현재 busy | “예약 작업 시간이 됐지만 작업 중입니다. 끝나고 이어 할까요?” |
| 센서/맵 정보 부족 | “공간 정보를 다시 받아야 실행할 수 있습니다” |
이 영역은 proactive agent 후보지만, side effect는 confirmation policy와 연결해야 한다.
5. Route/step 사양 기준
| 흐름 | 의미 | 예시 |
|---|---|---|
DEF -> DEF |
일반 대화만 수행 | 오늘 뭐 할까? |
ODL -> DEF |
기기 상태를 읽어 설명만 수행 | 공기질 어때?, 너 어디 있어? |
DEF -> ODL |
대화/조건 판단 후 기기 실행 | 괜찮으면 청정해줘 |
ODL -> ODL |
순차 기기 workflow | 공간4 갔다가 공간1 청정해줘 |
SCH -> ODL |
예약 slot 생성 후 TaskManager 등록 | 내일 8시에 청정해줘 |
ODL -> SCH |
즉시 기능처럼 들리지만 시간/반복이 있어 예약으로 승격 | 매일 밤에 복귀해 |
ODL -> DEF -> ODL |
상태 설명 후 사용자 확인을 받아 실행 | 공기질 나쁘면 알아서 해줘 |
Planner는 이 흐름을 token 문자열이 아니라 capability, context, side-effect, schedule slot 기준으로 판단해야 한다.
6. TaskManager 지연 실행 API 목표
TaskManager schedule은 제품 예약 엔진이 아니라 일회성 task/workflow admission 예약 계약이다.
| API | 목적 |
|---|---|
scheduleTask |
단일 task 예약 |
scheduleWorkflow |
여러 subTask를 순서대로 실행하는 workflow 예약 |
getScheduledTasks |
예약 목록 조회 |
cancelScheduledTask |
예약 취소 |
runDueScheduledTasks |
실행 시점이 된 예약을 queue에 admission |
추가 정책 field도 필요하다.
| field | 의미 |
|---|---|
scheduleKind |
deferred_task 고정. 제품 반복 예약과 혼동 방지 |
triggerType |
relative_delay 또는 absolute_time |
triggerAtMs |
admission 기준 절대 시각 |
relativeDelayMs |
상대 시간 발화의 원래 의미를 audit용으로 보존 |
requireFreshDeviceContext |
실행 직전 context refresh 필요 |
blockWhenTaskManagerBusy |
이미 작업 중이면 admission 차단 |
requiresCloudDecision |
차단 시 Cloud replan 필요 |
missedRunPolicy |
예약 시점을 놓쳤을 때 skip/run_late/ask_user 결정 |
ownerSessionId |
예약을 만든 사용자/세션 추적 |
현재 MR6 TaskManager 구현은 triggerAtMs/scheduledAtMs, 파일 영속화, exact alarm 재등록, missed-run grace를 갖춘 일회성 scheduler다. 반복 rule 생성은 구현돼 있지 않으므로 매일, 평일, 주말 발화를 TaskManager 반복 예약으로 표시하면 안 된다.
6.1 조건부 실행 계약
조건부 실행은 특정 발화 문자열을 코드에 나열해서 처리하지 않는다. Planner가 현재 device_context에 근거할 수 있는 조건을 step metadata로 구조화하고, runtime은 그 조건을 평가한 뒤 같은 ODL bridge/task mapper를 계속 태운다.
예시 계약:
{
"id": "step_if_station_clean",
"route": "ODL",
"skill": "fixed_purify",
"purpose": "스테이션 조건 확인 후 고정 청정 시작",
"depends_on": [],
"condition": {
"type": "device_context",
"path": "location.is_on_station",
"operator": "is_true",
"on_false_tts": "현재 조건이 맞지 않아 작업을 실행하지 않았습니다."
}
}
지원하는 operator는 의미 단위로 제한한다. 발화 문자열을 코드에 직접 나열하지 않고, LLM이 선택한 path와 operator를 runtime이 평가한다.
| operator | 용도 |
|---|---|
is_true / is_false |
도킹, 스테이션 여부, 청정 실행 여부 같은 boolean 상태 |
equals / not_equals |
현재 room name, movement status 같은 named state |
greater_or_equal / less_or_equal |
배터리 퍼센트, 공기질 등급, CO2처럼 숫자 threshold가 있는 상태 |
exists |
값 존재 여부만 확인하는 상태 |
원칙:
| 항목 | 기준 |
|---|---|
| 조건 판단 주체 | Planner가 조건의 의미와 context path를 정한다 |
| 조건 평가 주체 | Cloud runtime이 device_context snapshot으로 평가한다 |
| 실행 주체 | 조건이 참이면 기존 ODL bridge와 TaskManager task mapper가 실행한다 |
| 거짓 처리 | 조건이 거짓이면 task dispatch를 만들지 않고 TTS-safe 설명만 반환한다 |
| 금지 | 스테이션에 있으면 같은 문구별 hardcode를 계속 늘리지 않는다 |
이 구조의 목적은 “스테이션에 있으면 청정 켜봐”, “작업 중 아니면 이동해”, “배터리 괜찮으면 복합 청정해” 같은 문장을 모두 같은 구조로 다루는 것이다. 발화별 분기를 늘리는 대신, condition path와 operator를 planner output contract로 일반화한다.
Planner에는 device_context 원본 전체를 그대로 넣지 않고 device_context_summary만 전달한다. 이 summary는 available_condition_paths, 현재 위치/도킹 여부, room name, TaskManager busy, 공기질 availability/grade 정도만 담는다. 따라서 LLM은 조건을 추론할 수 있지만, 사용자 TTS에 context, current_room_id, raw sensor key 같은 디버그 값을 노출하지 않아야 한다.
현재 runtime에서 열어둔 대표 condition path:
| path | 의미 |
|---|---|
location.is_on_station |
현재 스테이션 위치 여부 |
location.is_docked |
도킹 여부 |
location.current_room_name |
현재 room name |
movement.status |
이동 상태 |
cleaning.is_running |
청정 실행 여부 |
cleaning.is_paused |
청정 일시정지 여부 |
battery.percent |
배터리 퍼센트 |
battery.is_low |
배터리 부족 여부 |
air_quality.available |
공기질 데이터 수신 여부 |
air_quality.aq_level |
기기 계산 공기질 등급 |
air_quality.pm10 / air_quality.pm2_5 / air_quality.co2 |
정량 센서 값 |
task_manager.busy |
TaskManager 작업 진행 여부 |
2026-07-24 Cloud runtime 기준 focused 검증:
python3 -m pytest test/test_e2e_orchestrator_smoke.py test/test_orchestrator_task_plan.py -q
30 passed
python3 -m pytest \
test/test_frg_presenter_api.py \
test/test_e2e_orchestrator_smoke.py \
test/test_orchestrator_task_plan.py -q
35 passed
python3 -m pytest \
test/test_task_manager.py \
test/test_task_orchestration_roundtrip.py \
test/test_task_event_ingest.py \
test/test_task_event_contract_verifier.py \
test/test_device_task_mapper.py \
test/test_voice_task_scenario.py \
test/test_local_lambda_shim_tool.py -q
67 passed
python3 -m py_compile \
gemini/a2a/runtime/task_manager.py \
gemini/a2a/runtime/orchestrator.py \
gemini/a2a/agents/frg/presenter_api.py \
gemini/a2a/planner/main_router_api.py \
gemini/a2a/planner/preclassifier.py \
gemini/a2a/planner/flow_selection_core.py
python3 -m pytest test --ignore=test/A2A_TEST \
--ignore=test/gemini_rag_api_test.py \
--ignore=test/rag_judge_test.py \
--ignore=test/test_chat.py \
--ignore=test/test_flow_shadow_selector_schedule_priority.py -q
418 passed
검증한 케이스:
| 케이스 | 기대 |
|---|---|
배터리 괜찮아? + device_context.battery.percent=82 |
raw key 없이 자연어 배터리 상태 응답 |
지금 공기질 어때 + device_context.air_quality.aq_level=1 |
raw key 없이 자연어 공기질 판단 응답 |
condition.path=location.is_on_station, 값 true |
조건 통과 후 setAirCleanerOperation task dispatch 생성 |
condition.path=location.is_on_station, 값 false |
dispatch 없이 조건 불일치 응답 |
condition.path=air_quality.aq_level, operator=greater_or_equal, 값 true/false |
숫자 threshold 기반 dispatch/blocked 분기 |
| 동일 ODL route의 여러 step | planner normalization에서 단일 step으로 접지 않고 보존 |
안녕, 뭐야, 어떻게 할까 |
짧지만 즉답 가능한 대화는 DEF, 단순 길이만으로 STT_NULL 금지 |
코스피 얼마야 |
짧은 public finance lookup은 FRG, public live-state를 기기 live-state와 분리 |
FRG subagent 실행 전 planner가 질문이 아닌 안내문을 ask_follow_up=true로 반환 |
실제 질문형 문장이 아니면 waiting_user workflow를 열지 않고 FRG를 실행 |
FRG presenter가 질문이 아닌 응답에 there_is_question_mark=true를 반환 |
최종 응답문이 의문문이 아니면 false로 정규화 |
직함 단독 vs 대상+직함 public query |
직함 단독은 scope 확인 유지, 이름처럼 보이는 대상+직함은 target이 고정된 것으로 보고 불필요한 지역 확인을 줄임 |
라이브 orchestrator probe 결과:
| 발화 | 결과 |
|---|---|
배터리 괜찮아? |
ODL.ODL.device_context_summary, “현재 배터리는 82%입니다...” |
이재명대통령에 대해서 찾아보고, 이번주 뭐했는지 요약해서 설명해줄래? |
FRG.freshness_answer_composition, 실제 fresh 답변 생성, there_is_question_mark=false, active workflow 없음 |
너 지금 어디있어 |
ODL.ODL.device_context_summary, “현재 스테이션에 있습니다.” |
지금 공기질 어때 |
ODL.ODL.device_context_summary, 자연어 공기질 판단 |
스테이션에 있으면 청정 켜봐 |
native_conditioned_device_task, setAirCleanerOperation dispatch 생성 |
/device-text 안녕 |
ADB broadcast success, on-device /llm/invoke 200, DEF.default_conversation |
Text console/local shim 설정 주의:
| field | 권장값 | 이유 |
|---|---|---|
Local shim URL |
http://127.0.0.1:18080 |
public console을 같은 개발 PC 브라우저에서 열 때 브라우저가 호출하는 주소 |
On-device Cloud API URL |
http://127.0.0.1:18080 |
adb reverse tcp:18080 tcp:18080 기준으로 기기 내부에서 local shim을 다시 호출하는 주소 |
| shim bind | --host 127.0.0.1 |
같은 PC 브라우저 테스트 기본값. WSL IP로 접근하려면 --host 0.0.0.0 필요 |
GEMINI_API_KEY는 shim 프로세스 시작 시점에 환경변수로 들어가야 한다. 이미 떠 있는 shim에는 나중에 export한 값이 전파되지 않으므로, 키가 없던 shim은 종료 후 재시작해야 한다. 키 값은 command line이나 wiki에 남기지 않는다.
단, 2026-07-24 현재 route_turn은 ODL bridge shortcut을 먼저 타는 케이스가 있어 planner가 항상 직접 condition step을 생성하지는 않는다. runtime compiler의 조건부 bridge는 과도기 안전장치로 유지하되, 신규 기능은 planner가 condition metadata를 직접 내리는 방향으로 확장한다.
7. 현재 확인된 gap
| gap | 영향 | 방향 |
|---|---|---|
| TaskManager 조회는 실기기에서 검증됐지만 제품 scheduler와 결과 집계는 미연결 | 사용자 입장에서는 일부 예약만 보임 | 두 owner의 결과를 출처가 보이도록 집계 |
| owner 태그 이후 최종 dispatch adapter가 부분 연결 | deferred_task가 임시 app scheduler로 남거나 제품 예약과 섞일 수 있음 |
capability catalog 기반으로 scheduleTask/scheduleWorkflow 또는 제품 scheduler를 선택하고 저장소 간 복제 금지 |
| non-cleaning capability의 sequential task mapping이 부족 | 공간1로 가서 바이탈사인 켜줘가 이동 후 실행으로 안정화되지 않음 |
capability catalog -> TaskManager method adapter 확장 |
| 위치 context가 room name 없이 id만 보일 수 있음 | TTS가 부자연스럽거나 디버그 값 노출 | station/room name resolver 강화 |
| 공기질 응답이 raw key/value로 흐를 수 있음 | 사용자 경험 저하 | context summarizer를 자연어 등급/판단으로 제한 |
| callback 기반 replan 경계가 아직 부분 연결 | 실패/차단 후 자동 복구가 불안정 | requiresCloudDecision event만 Cloud replan으로 올리는 계약 고정 |
8. 우선순위
| 우선순위 | 작업 | 완료 기준 |
|---|---|---|
| P0 | 상태 Q&A 안정화 | 위치/작업/공기질 질문이 STT_NULL이 아니라 ODL context summary로 응답 |
| P0 | 통합 schedule query 연결 | 제품 예약과 TaskManager 지연 실행을 한 응답에서 자연어로 요약 |
| P0 | deferred workflow 등록 | 20분 뒤 공간4 갔다가 공간1 청정하고 복귀해줘가 scheduleWorkflow로 등록 |
| P1 | non-cleaning capability workflow화 | 이동 후 바이탈/모드/설정 실행이 같은 workflow 안에서 순차 수행 |
| P1 | admission/replan 정책 | busy, blocked, missed run에서 retry/ask/cancel 판단 |
| P2 | proactive 제안 | 공기질, 배터리, 이동 실패, 예약 충돌에 대한 선제 안내 |
9. 테스트 문장
| 범주 | 문장 | 기대 |
|---|---|---|
| 위치 | 너 지금 어디 있어? |
현재 공간/스테이션 응답 |
| 작업 상태 | 지금 작업 중이야? |
TaskManager 상태 응답 |
| 공기질 | 지금 공기질 어때? |
자연어 상태 판단 |
| 즉시 workflow | 공간4 갔다가 공간1로 가서 청정하고 스테이션 복귀해줘 |
submitWorkflow |
| 조건부 실행 | 스테이션에 있으면 청정 켜봐 |
context 확인 후 실행 또는 이유 응답 |
| 지연 task | 20분 뒤에 공간1 청정해줘 |
TaskManager deferred_task 등록 |
| 지연 workflow | 20분 뒤 공간4 갔다가 공간1 청정하고 복귀해줘 |
TaskManager deferred_task workflow 등록 |
| 반복 제품 예약 | 매일 밤 9시에 안방 청정해줘 |
제품 scheduler 등록 |
| 조건 연속 실행 | 청정 끝나면 복귀해 |
active workflow callback dependency |
| 예약 조회 | 예약된 작업 목록 보여줘 |
두 owner의 예약을 구분해 요약 |
| 작업 개입 | 그 작업 취소해 |
active task/workflow cancel |
10. 제품 효과
| 효과 | 설명 |
|---|---|
| 긴 작업 신뢰도 향상 | 이동/청정/복귀처럼 시간이 걸리는 작업을 queue와 callback으로 추적한다 |
| 자연스러운 상태 응답 | 사용자가 “어디 있어”, “뭐 하는 중이야”라고 물으면 기기 context로 답한다 |
| schedule 범위 확장 | 반복 제품 예약과 일회성 workflow 지연 실행을 충돌 없이 함께 제공한다 |
| 안전한 재계획 | 실패 시 prompt 우회가 아니라 reason/context 기반으로 재시도/취소/질문을 선택한다 |
| proactive 기반 확보 | 공기질/배터리/막힘/예약 충돌을 먼저 감지해 제안할 수 있다 |
11. 사양상 주의점
- schedule 단어만으로
SCH가 아니다. 시간/반복/등록/조회/수정/삭제/취소 의도가 있어야 한다. - 알람/모드/청정 “켜줘/꺼줘”는 즉시 제어면
ODL이고, 시간 조건이 붙으면SCH다. SCH는 저장소가 아니다. 반복 제품 예약은native_product, 일회성 지연 실행은deferred_task, 완료 조건은event_continuation으로 나눈다.- context summary는 기기 상태 조회지만 side effect가 없으므로 실행 task를 만들지 않는다.
- TaskManager는 자연어를 해석하지 않는다. Cloud가 method/subTask를 만들고 TaskManager는 lifecycle, queue, policy, event, reason을 관리한다.
- 정상 event마다 Cloud LLM을 호출하지 않는다. replan은 실패, 차단, 사용자 입력 필요, schedule admission conflict 같은 경계로 제한한다.
12. 검증 근거
- TaskManager Live Monitor: 이동 하드웨어를 제외한 복합 action, 조건, 예약, TaskManager 제어 60건의 단계별 개선 및 최종 shadow 검증 결과
- 2026-07-26 실기기 상대시간 예약:
relative_delay_seconds=3600에서relative_delay_ms=3600000,scheduleId=scheduled-4까지 전달 - 동일
request_id재전송:deduplicated=true, 기존scheduled-4반환, 활성 예약 수 증가 없음 - DeviceAgent 재부팅 후 조회:
scheduled-4복원, API envelope source와 record filter 분리 확인 - 검증 종료 후
scheduled-3,scheduled-4취소 및 활성 예약 0건 확인