DeviceAgent TaskManager API Contract
이 페이지는 SoC/DeviceAgent 업체가 맞춰야 하는 TaskManager API와 event payload 계약을 현재 소스 기준으로 정리한다.
System App에서 이 계약을 직접 Bundle로 조립하지 않고 호출하려면 TaskManagerClient AAR API Specification을 사용한다.
기준 소스:
~/work/1.A1_SoC_new/SoC/a1-packages-mr6/apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskManager.java
~/work/1.A1_SoC_new/SoC/a1-packages-mr6/apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskEventListener.java
~/work/1.A1_SoC_new/SoC/a1-packages-mr6/apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskReasonContract.java
~/work/1.A1_SoC_new/SoC/a1-packages-mr6/apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/DevicePlanningContextProvider.java
~/work/1.A1_SoC_new/SoC/a1-packages-mr6/apps/DeviceAgent/app/src/main/java/com/sk/airbot/deviceagent/task/TaskIngressClassifier.java
1. Control Method 목록
TaskManager.handleControlMethod(...)가 처리하는 method다.
| Method | 목적 | 주요 입력 | 주요 출력 |
|---|---|---|---|
submitTask |
단일 task 등록 | taskMethod, task params, source, cloud trace fields |
accepted, taskId, taskState, summary |
submitWorkflow |
여러 subtask workflow 등록 | workflowName, subTasks, source |
accepted, workflow taskId, subtask states |
getTaskStatus |
task 상세 조회 | taskId |
task summary/detail |
listTasks |
task 목록 조회 | filter fields | task list |
getQueueStatus |
queue 상태 조회 | optional filter | queue summary |
updateTaskProgress |
progress/status 갱신 | taskId, progress/status/stage/message |
updated summary |
cancelTask |
task 취소 | taskId, reason |
cancelled summary |
clearPendingTasks |
queue의 대기 task 비우기 | queue |
cleared, clearedCount |
cancelQueue |
queue 단위 task 취소 | queue, includeRunning |
cancelled, cancelledCount |
getTaskManagerStatus |
manager 상태 조회 | none | enabled/queue/metric 상태 |
getDevicePlanningContext |
Cloud plan 전 기기 context 조회 | none | device_context.v1 snapshot |
classifyTaskIngress |
method가 task/control/event인지 분류 | method, optional signalType |
signal type, action, reason |
2. submitTask 처리 순서
현재 submitTask(...)는 아래 순서로 처리된다.
enabled check
-> taskMethod 필수 확인
-> TaskBundleValidator.validateSubmitTask
-> TaskPolicyRegistry.resolve
-> caller policy check
-> state condition check
-> resource policy check
-> TaskCommandFactory로 command 생성
-> executionMode에 따라 DIRECT / QUEUED_WAIT / ASYNC 처리
중요한 reject code:
| Code | 의미 |
|---|---|
taskmanager_disabled |
TaskManager 비활성 |
missing_task_method |
taskMethod 누락 |
| validator error | submit task schema/parameter 불일치 |
missing_task_command |
실행 가능한 command 생성 실패 |
3. submitWorkflow 처리 순서
submitWorkflow(...)는 subTasks를 순차 실행하고, parallelGroup도 처리할 수 있다.
입력 구조:
workflowName
subTasks: ArrayList<Bundle>
source
cloud_workflow_id / cloudWorkflowId
cloud_plan_id / cloudPlanId
preemptPolicy
subtask 실행 흐름:
for each subTask:
validateWorkflowSubTask
currentStepIndex/currentStepMethod 갱신
WORKFLOW_STEP_STARTED event
command.run()
WORKFLOW_STEP_COMPLETED event
parallelGroup 흐름:
type = parallelGroup
groupId
joinPolicy = all_success
failurePolicy = fail_parent | partial_success | continue_on_failure
tasks = child task list
3.1 Submit 전 기존 task 정리 정책
Cloud/IoT가 새 task 또는 workflow를 넣을 때 기존 queue를 먼저 정리해야 하는 경우 submitTask와 submitWorkflow 입력에 preemptPolicy를 넣을 수 있다. 이 처리는 TaskManager 내부에서 새 task 등록 전에 수행되어, 외부에서 clear와 submit을 별도 호출할 때 생길 수 있는 순서 꼬임을 줄인다.
preemptPolicy |
의미 |
|---|---|
append 또는 미지정 |
기존 task를 유지하고 새 task를 queue에 추가한다. |
clear_pending |
같은 queue의 PENDING task만 CANCELLED로 정리한다. 실행 중 task는 유지한다. |
cancel_running |
같은 queue의 실행/대기 task를 취소 대상으로 처리한다. |
replace_queue |
같은 queue의 기존 실행/대기 task를 취소한 뒤 새 task/workflow를 등록한다. |
replace_all |
모든 queue의 실행/대기 task를 취소한 뒤 새 task/workflow를 등록한다. 테스트/관리자 목적에 한정해 사용한다. |
replace_queue 예시:
method = submitWorkflow
queue = workflow
workflowName = bedroom_livingroom_clean_return
preemptPolicy = replace_queue
subTasks = [...]
처리 결과에서 기존 task가 취소되면 preemptCancelledCount가 응답에 포함된다.
3.2 외부 제어 API
명시적 운영 제어가 필요한 경우 아래 control method를 직접 호출할 수 있다. 이 method들은 새 task를 생성하지 않는 TaskManager 제어 명령이다.
| Method | 입력 | 처리 |
|---|---|---|
cancelTask |
taskId |
특정 task를 취소한다. workflow parent 취소 시 실행 중 child도 취소 대상으로 처리한다. |
clearPendingTasks |
queue |
해당 queue의 PENDING task만 취소 상태로 정리한다. |
cancelQueue |
queue, includeRunning |
해당 queue의 task를 취소한다. includeRunning=true일 때 실행 중 task도 cancel method를 거친다. |
Cloudflare Task Monitor Worker의 command gateway는 cancelTask, clearPendingTasks, cancelQueue를 allowlist에 포함하고, DeviceAgent TaskMonitorCommandBridge는 이 명령들을 submitTask로 감싸지 않고 TaskManager control method로 전달한다.
CANCELLED state 기록만으로 executor가 정지했다고 판단하면 안 된다.
실행 중 movement workflow를 취소할 때는 parent와 active child에 cancel을
전파하고, legacy movement command에도 물리 정지 요청이 전달돼야 한다.
제품 검증은 task state와 실제 모터 정지를 함께 확인한다.
4. Execution Mode 의미
| Mode | 의미 |
|---|---|
DIRECT |
TaskManager queue를 거치지 않고 즉시 실행한다. |
QUEUED_WAIT |
queue에 넣고 완료까지 기다린 뒤 결과를 반환한다. |
ASYNC |
queue에 넣고 즉시 accepted/task summary를 반환한다. |
Cloud/온디바이스 관점에서는 복합 device workflow가 길어질 수 있으므로 ASYNC 또는 workflow queue 기반 event callback이 중요하다.
5. Task Event Payload
notifyTaskEvent(...)는 record.writeSummaryTo(eventData) 후 아래 필드를 추가한다.
method = onTaskEvent
eventName = event name
writeSummaryTo(...)가 넣는 핵심 필드:
| Field | 의미 |
|---|---|
taskId, task_id |
task id snake/camel 호환 |
taskMethod, task_method |
실제 task method |
taskQueue |
queue key |
taskState, status |
현재 상태 |
executionMode |
DIRECT/QUEUED_WAIT/ASYNC |
priority |
task priority |
source |
task source |
cancellable |
취소 가능 여부 |
retryCount |
retry 횟수 |
progress |
진행률 |
stage |
현재 stage |
message |
상태 메시지 |
currentStepIndex |
workflow 현재 step index |
currentStepMethod |
workflow 현재 step method |
workflowName |
workflow 이름 |
taskErrorCode |
실패 error code |
taskReason |
실패 reason |
reason_code, reasonCode |
구조화된 reason code |
reason_params, reasonParams |
구조화된 reason params |
recoverability |
복구 가능성 |
suggested_action, suggestedAction |
권장 후속 행동 |
requires_cloud_decision, requiresCloudDecision |
Cloud 재판단 필요 여부 |
Cloud trace alias:
| snake_case | camelCase |
|---|---|
cloud_workflow_id |
cloudWorkflowId |
workflow_id |
workflowId |
cloud_step_id |
cloudStepId |
step_id |
stepId |
cloud_plan_id |
cloudPlanId |
plan_id |
planId |
cloud_output_key |
cloudOutputKey |
output_key |
outputKey |
6. Reason Code Contract
TaskReasonContract는 error code를 Cloud가 이해할 수 있는 reason code로 정규화한다.
| 입력 error 계열 | reason_code |
|---|---|
TIMEOUT, TASK_TIMEOUT |
TIMEOUT |
INTERRUPTED |
INTERRUPTED |
CANCELLED, USER_CANCELLED |
USER_CANCELLED |
QUEUE_FULL, RESOURCE_BUSY, BUSY, DEVICE_BUSY |
DEVICE_BUSY |
CPU_LIMIT, RAM_LIMIT, THERMAL_LIMIT |
RESOURCE_LIMIT |
STATE_CONDITION_FAILED, BLOCKED_BY_STATE, CONDITION_FAILED |
STATE_CONDITION_FAILED |
VALIDATION_FAILED, MISSING_TASK_METHOD, MISSING_TASK_COMMAND |
CAPABILITY_UNAVAILABLE |
PATH_BLOCKED, PATH_BLOCKED_BY_OBSTACLE, NAVIGATION_PATH_BLOCKED |
PATH_BLOCKED |
ROOM_NOT_FOUND, POSITION_NOT_FOUND, LOCATION_NOT_FOUND, TARGET_NOT_FOUND |
ROOM_NOT_FOUND |
LOW_BATTERY, BATTERY_LOW |
LOW_BATTERY |
SENSOR_ERROR, SENSOR_FAILURE |
SENSOR_ERROR |
requires_cloud_decision은 LOW_BATTERY, DEVICE_BUSY, RESOURCE_LIMIT을 제외한 구조화 reason에서 대체로 true가 된다.
7. Device Planning Context
getDevicePlanningContext는 DevicePlanningContextProvider.snapshot(...)을 통해 Cloud plan 전 context를 제공한다.
최상위 필드:
schema_version = device_context.v1
snapshot_ts
updated_at_ms
main_state
battery
map
location
air_quality
cleaning
movement
network
voice_llm
security
task_manager
semantic_observations
capabilities
하위 구조:
| 필드 | 포함 정보 |
|---|---|
battery |
available, percent, is_low, is_charging, raw_capacity |
map |
available, editable, rooms |
location |
current_room_id, current_room_name, is_on_station |
cleaning |
is_running, is_paused, last_action, area_info |
movement |
moving_status, is_moving, is_paused, blocked |
task_manager |
device-task-manager-context.v1, queue_status, busy, running_tasks, queue_summary, active_tasks, recent_terminal |
capabilities |
movement, room_cleaning, return_to_station, tts, schedule |
active_tasks와 recent_terminal은 각각 최대 4건이다. TaskManager의
TaskRecord가 상태 권위이며 별도 상태 저장소를 만들지 않는다.
- active: task/workflow/step ID, method, queue, state, progress, stage, update timestamp
- terminal: 위 식별 정보와 terminal state, reason code, recoverability, suggested action, cloud decision 필요 여부, finish timestamp
- 제외: raw input/result, user-facing message, conditions, reason parameters
is_charging은 상수가 아니라 BatteryManager의 현재 값을 boolean으로
변환해야 한다. 또한 capability의 지원 가능과 현재 상태에서의
실행 가능은 서로 다른 필드로 제공해야 한다.
8. Ingress Classification
classifyTaskIngress는 method가 TaskManager control인지, 일반 command task인지, event/status 성격인지 분류한다.
| Signal type | creates task | action |
|---|---|---|
COMMAND_TASK |
true | submit_task |
TASK_CONTROL |
false | task_manager_api |
PROGRESS_UPDATE |
false | update_task_progress |
RESULT_UPDATE |
false | update_task_result |
SENSOR_DATA |
false | state_or_resource_update |
TRIGGER |
false | policy_trigger |
EVENT_CALLBACK |
false | event_callback |
UNKNOWN |
false | reject |
9. 전송 보안과 외부 모듈 경계
- TaskManager 제어 권한은 transport에서 인증한 caller와 Binder 권한으로 결정한다.
forceTaskManager,source,executorDryRun같은 payload 필드는 인증을 우회하지 못한다.- PUI, IoT, Launcher와 Cloud bridge는 동일 control API를 사용하되 각 source의 caller policy를 적용한다.
requestId와traceId로 중복 제출과 callback 상관관계를 관리한다.- 외부 모듈은 Task 상태만 보고 물리 완료를 추정하지 않고 terminal evidence를 기다린다.
- HTTP·MQTT test gateway는 운영망 노출, allowlist, replay와 secret 보관을 별도 검토한다.
10. 업체 구현 체크포인트
| 체크포인트 | 확인 방법 |
|---|---|
submitTask가 accepted/task summary를 반환하는가 |
단일 task unit test |
submitWorkflow가 subtask state를 남기는가 |
workflow unit/instrumented test |
WORKFLOW_STEP_STARTED/COMPLETED event가 올라오는가 |
event listener test |
실패 시 reason_code, reason_params가 채워지는가 |
failure injection test |
| Cloud trace alias가 event에 남는가 | logcat/artifact validator |
getDevicePlanningContext가 stale/empty 없이 반환되는가 |
context snapshot test |
cancelTask가 running/pending task를 정리하는가 |
cancellation test |
11. Cloud 연동 관점에서 중요한 결론
COMPLETED,WORKFLOW_STEP_COMPLETED,WORKFLOW_COMPLETED는 기본적으로 정상 진행 event다.- Cloud workflow reducer는 대기 중인 동일
cloud_step_id에 대해COMPLETED와WORKFLOW_STEP_COMPLETED를 동일한 단계 완료 의미로 처리하되 원래 event 이름은 보존한다. - 단계 완료는
step_results기록과 dependency 해제를 의미하고,WORKFLOW_COMPLETED만 전체 workflow terminal을 의미한다. - Cloud LLM은 정상 event마다 다시 돌 필요가 없다.
FAILED,BLOCKED,PAUSED,NEEDS_USER_INPUT계열에서requires_cloud_decision=true일 때 replan 후보가 된다.- 자연어
taskReason만으로는 부족하다.reason_code와reason_params가 필수다. - Cloud trace field는 task lifecycle 내내 보존되어야 한다.