A2A Contract Matrix
이 페이지는 Cloud A2A, 온디바이스 Bridge, DeviceAgent TaskManager 사이에 오가는 주요 계약을 한 표로 정리한다.
Contract Overview
| 계약 | From | To | 목적 |
|---|---|---|---|
voice_context |
On-device | Cloud | 현재 발화, 세션, workflow, memory, device context 전달 |
router_result |
Cloud Planner | Cloud Runtime | route family, owner, step plan 전달 |
session_state |
Cloud Runtime | On-device | 다음 turn에 필요한 compact state 전달 |
device_task_requests |
Cloud Runtime | On-device | device 실행 요청 전달 |
device_intent_step |
Cloud Runtime | On-device Workflow Runner | tokenized device workflow step 전달 |
submitTask |
On-device | DeviceAgent TaskManager | 단일 실행 task 등록 |
submitWorkflow |
On-device | DeviceAgent TaskManager | 복수 task workflow 등록 |
onTaskEvent |
DeviceAgent | On-device | task 상태/완료/실패 callback |
task_event |
On-device | Cloud | task event를 Cloud workflow state로 전달 |
memory_snapshot |
On-device | Cloud | memory context 전달 |
memory_update |
Cloud | On-device | memory/session/workflow 갱신안 전달 |
Planner Output Contract
turn_mode
selected_routes
selected_flow_id
owner_selection
steps
missing_slots
stt_null_*
Multi-step step의 필수 축:
id
route
purpose
execution_target
depends_on
input_from
wait_policy
token_text
원칙:
- semantic dependency는
input_from으로 표현한다. - physical device ordering은
depends_on과wait_policy=completed|event로 표현한다. token_text는 추측 금지다.
Device Task Request Contract
| 형태 | 조건 | 주요 필드 |
|---|---|---|
device_intent_step |
token_text 기반 workflow | task_type, token_text, cloud_*, depends_on, wait_policy |
| legacy task request | ODL bridge taskMethod 기반 | taskMethod, params, cloud_*, executionMode |
| IoT MQTT command task | MQTT 명령을 단일 DeviceAgent task로 등록 | method=submitTask, taskMethod, source=iot, traceId, correlationId, replyTo |
| PUI command task | SKMLauncher 명령을 단일 DeviceAgent task로 등록 | method=submitTask, taskMethod, source=pui, traceId, correlationId |
| OnDevice command task | OnDeviceAI Agent 명령을 단일 DeviceAgent task로 등록 | method=submitTask, taskMethod, source=ondevice, traceId, correlationId |
| SoC internal task | DeviceAgent 내부/SoC 자체 소비 task | taskMethod, source=internal 또는 명시 source, legacy_queue 정책 |
Trace 필드:
cloud_workflow_id
cloud_step_id
cloud_plan_id
cloud_output_key
이 네 필드는 Cloud, 온디바이스, DeviceAgent, logcat, artifact validator를 연결하는 핵심이다.
IoT MQTT To TaskManager Contract
IoTAgent가 MQTT 명령을 수신한 경우 기본 경로는 복합 workflow가 아니라 단일 submitTask이다.
virtual MQTT command
-> IotAgent command Bundle
-> method=submitTask, taskMethod=<legacy DeviceAgent method>, source=iot
-> DeviceAgent sendModuleCommand
-> MainApi
-> TaskManager
-> fake or real executor for taskMethod
단일 task로 취급하는 MQTT 명령:
- moveTo/station 이동 명령.
- clean start/pause/resume/next/option 명령.
- mapping 시작/제어 명령.
- comeback 명령.
- config/control 명령.
- reset, master version, firmware/part request 등 IoT request 명령.
- setMap/downloadMap/deleteMap/editMap 등 map 변경 명령.
- event 기반 gps/setup wizard/bluetooth/registration/call cancel/map edit 명령.
- schedule add/update/delete 및 재부팅 후 schedule 재적용 명령.
- outdoor weather/address 설정 명령.
- AQM sync mode on/off 명령.
직접 DeviceAgent 호출을 유지하는 경로:
getAirCleanerOperation처럼 다음 IoT task를 구성하기 위한 내부 조회.get...Response계열처럼 외부 응답 payload를 DeviceAgent 캐시/상태에 반영하는 경로.getschedule,getAQMList,getAQMAirQuality처럼 response snapshot을 전달하거나 telemetry를 반영하는 경로.- on-device 내부 map import 경로처럼 MQTT ingress가 아닌 내부 경로.
submitWorkflow는 여러 task의 순서, dependency, 보상, 대기 조건을 TaskManager가 직접 관리해야 할 때만 사용한다. 예를 들어 복귀, 충전 상태 확인, 청소 시작, 완료 보고를 하나의 원자적 절차로 묶어야 하면 workflow가 된다.
검증은 실제 MQTT broker와 실제 이동/청소 동작을 쓰지 않고, 가상 MQTT envelope와 fake executor로 TaskManager 연동성을 확인한다. 이 테스트는 taskMethod가 기존 DeviceAgent method로 복원되고, source=iot, traceId/correlationId, replyTo, 기존 command parameter가 executor 입력까지 보존되는지를 확인해야 한다.
SoC Ingress To TaskManager Contract
TaskManager로 들어오는 SoC 입력부는 다음 네 종류로 구분한다.
| 입력부 | source | 적용 위치 | 라우팅 원칙 |
|---|---|---|---|
| 앱 -> 서버 -> MQTT -> SoC | iot |
IotAgent MQTT topic handler | MQTT command 성격은 단일 submitTask; response/cache/telemetry 성격은 직접 반영 |
| PUI 런처 -> SoC | pui |
SKMLauncher DeviceControlResolver, simulator direct path |
set* 등 command/update 성격은 단일 submitTask; get/is/check/request* 조회는 직접 호출 |
| OnDeviceAI Agent -> SoC | ondevice |
OnDeviceAI DeviceCommunicator |
command/update 성격은 단일 submitTask; 조회는 직접 호출 |
| SoC -> SoC 자체 소비 | internal 또는 명시 source |
DeviceAgent MainApi -> TaskManager.executeLegacy |
persist.sys.deviceagent.taskmanager.legacy_queue=true일 때 non-direct legacy command를 내부 task로 큐잉 |
DeviceAgent TaskSource는 IOT, PUI, ONDEVICE, API, INTERNAL을 명시 source로 보존해야 한다. source가 enum에 없으면 TaskManager event/status에서 UNKNOWN으로 떨어져 vendor 분석과 logcat trace가 끊긴다.
Cloud/음성 Agent가 SoC TaskManager를 사용하는 폐루프 구조는 Voice Agent To SoC TaskManager Closed Loop에 별도로 정리한다. 핵심은 Cloud device_task_requests[]가 submitTask로 변환되고, TaskManager event의 requires_cloud_decision, cloud_workflow_id, cloud_step_id, cloud_plan_id, cloud_output_key가 다시 Cloud 판단 입력으로 돌아간다는 점이다.
2026-07-10 실기기 검증:
TaskManagerInstrumentedTest#submitTask_virtualIotTopicCommands_onAndroidRuntime_shouldReachFakeExecutor: 대표 IoT taskMethod들이 fake executor까지 도달.TaskManagerCommandBridgeInstrumentedTest: PUI command는submitTask/source=pui로 wrapping, query는 직접 유지.DeviceTaskManagerBridgeInstrumentedTest: OnDevice command는submitTask/source=ondevice로 wrapping, query는 직접 유지.TaskManagerInstrumentedTest#submitTask_knownIngressSources_onAndroidRuntime_shouldPreserveSourceNames:pui,ondevice,apisource가 DeviceAgent runtime에서 각각PUI,ONDEVICE,API로 보존.
2026-07-10 SoC TaskManager Ingress Integration Evidence
적용 범위:
| 영역 | 주요 파일 | 적용 내용 |
|---|---|---|
| IotAgent | CmdTopic.java, IotTaskManagerBridge.java |
MQTT command bundle을 submitTask/source=iot/taskMethod=<legacy method> envelope로 변환 |
| SKMLauncher | TaskManagerCommandBridge.java, DeviceControlResolver.java, SimulatorActivator.java |
PUI command/update 호출은 submitTask/source=pui, 조회성 호출은 직접 호출 유지 |
| OnDeviceAI Agent | DeviceTaskManagerBridge.kt, DeviceCommunicator.kt |
OnDevice command/update 호출은 submitTask/source=ondevice, 조회성 호출은 직접 호출 유지 |
| DeviceAgent | TaskSource.java, TaskManagerTest.java, TaskManagerInstrumentedTest.java |
PUI, ONDEVICE, API source enum 추가 및 source preservation 검증 |
보드 적용 결과:
| Package | System path | 확인 결과 |
|---|---|---|
com.sk.airbot.deviceagent |
/system/priv-app/DeviceAgent/DeviceAgent.apk |
system uid 1000, platform signature, persistent service 유지 |
com.sk.airbot.iotagent |
/system/priv-app/IotAgent/IotAgent.apk |
system priv-app 등록 |
com.sk.airbot.skmlauncher |
/system/priv-app/SKMLauncher/SKMLauncher.apk |
system uid 1000, platform signature |
com.skmagic.ondeviceai.agent |
/system/priv-app/SKOnDevice/SKOnDevice.apk |
system uid 1000, platform signature |
APK 교체 전 백업:
/data/local/tmp/agent-apk-backup/SKMLauncher.apk.20260710125814
/data/local/tmp/agent-apk-backup/SKOnDevice.apk.20260710125814
/data/local/tmp/agent-apk-backup/DeviceAgent.apk.20260710130702
검증 명령과 결과:
apps/DeviceAgent ./gradlew testDebugUnitTest --tests com.sk.airbot.deviceagent.task.TaskManagerTest
-> BUILD SUCCESSFUL
apps/IotAgent ./gradlew assembleDevDebug assembleDevDebugAndroidTest
-> BUILD SUCCESSFUL
apps/SKMLauncher ./gradlew assembleDebug assembleDebugAndroidTest
-> BUILD SUCCESSFUL
skmagic_ondeviceai_agent ./gradlew assembleDebug assembleDebugAndroidTest
-> BUILD SUCCESSFUL
실기기 instrumentation:
com.sk.airbot.iotagent.mqtt.topic.IotTaskManagerBridgeInstrumentedTest
-> OK (1 test)
com.sk.airbot.deviceagent.task.TaskManagerInstrumentedTest#submitTask_virtualIotTopicCommands_onAndroidRuntime_shouldReachFakeExecutor
-> OK (1 test)
com.sk.airbot.deviceagent.task.TaskManagerInstrumentedTest#submitTask_knownIngressSources_onAndroidRuntime_shouldPreserveSourceNames
-> OK (1 test)
com.sk.airbot.skmlauncher.data.common.TaskManagerCommandBridgeInstrumentedTest
-> OK (2 tests)
com.skmagic.ondeviceai.agent.service.DeviceTaskManagerBridgeInstrumentedTest
-> OK (2 tests)
관찰된 주의 사항:
- IotAgent instrumentation 첫 실행에서 test install/service stop 타이밍에
WifiMonitor.stopMonitoring()의NetworkCallback was not registered예외가 1회 발생했다. 동일 테스트 재실행은OK (1 test)였고, TaskManager bridge 자체 실패는 아니었다. - 마지막 logcat 확인 시
FATAL EXCEPTION,SQLiteException,Cant downgrade,ClassNotFoundException,DeadObjectException패턴은 최근 500줄 기준 검출되지 않았다. - OnDeviceAI Agent는 system priv-app으로 설치되어 package 등록은 확인됐으나, 마지막 상태 확인 시 프로세스는 상주하지 않았다. bridge routing 검증은 instrumentation에서 완료했다.
Task Event Contract
정상 event:
QUEUED
RUNNING
PROGRESS
COMPLETED
WORKFLOW_COMPLETED
재판단 후보 event:
FAILED
BLOCKED
TIMEOUT
PAUSED
NEEDS_USER_INPUT
필수 event 필드:
eventName/status
cloud_workflow_id
cloud_step_id
task_id
taskMethod
requires_cloud_decision
reason_code
reason_params
Failure Smells
| 증상 | 의심 영역 |
|---|---|
| final response는 있는데 기기 실행 없음 | device_task_requests 누락 |
| task는 실행됐지만 다음 step이 안 열림 | cloud_step_id 또는 COMPLETED callback 누락 |
| workflow가 끝났는데 계속 active | WORKFLOW_COMPLETED 누락 |
| 실패했는데 Cloud가 아무 반응 없음 | requires_cloud_decision 또는 reason_code 누락 |
| logcat validator 실패 | trace field 또는 log format 누락 |
| planner가 device step을 Cloud step처럼 처리 | execution_target/wait_policy 누락 |