# host-agent-protocol Specification ## Purpose Define the authenticated outbound protocol used by Device Host Agents to synchronize devices, claim leased work, execute it locally, and report results. ## Requirements ### Requirement: Host identity is authenticated and bound to one host id Except for the bootstrap enrollment operation authenticated by a configured one-time enrollment credential, the internal Host Agent API SHALL require a host-scoped bearer principal and SHALL reject any request that attempts to act for a `host_id` different from the authenticated principal's bound host. #### Scenario: Host authenticates as itself - **WHEN** a Host Agent presents valid static or dynamically enrolled credentials bound to its requested `host_id` - **THEN** the internal API authorizes permitted device enrollment, heartbeat, claim, renewal, and result operations #### Scenario: Host attempts to impersonate another host - **WHEN** valid credentials bound to host A are used on a request for host B - **THEN** the internal API rejects the request without reading or modifying host B's state #### Scenario: Unknown Host credential is presented - **WHEN** a caller presents a bearer credential that is neither statically configured nor bound to a non-revoked enrolled Host - **THEN** the internal API rejects the request without exposing whether a Host ID exists ### Requirement: Host Agent synchronizes heartbeat and complete device snapshots The Host Agent SHALL periodically submit its complete local device snapshot to the control plane, and the control plane SHALL atomically refresh the host heartbeat and replace only that host's pooled-device records. Enrollment-managed Hosts SHALL report the cloud device IDs assigned through device enrollment. #### Scenario: Managed Host reports enrolled devices - **WHEN** an enrollment-managed Host Agent submits a valid heartbeat containing cloud device IDs enrolled to that Host - **THEN** the control plane updates the host's last-seen time and exposes the submitted devices through the aggregated pool #### Scenario: Managed Host reports an unknown device ID - **WHEN** an enrollment-managed Host reports a device ID not enrolled to that Host or a driver type that conflicts with its enrollment - **THEN** the control plane rejects the entire snapshot without changing the previous heartbeat or pooled-device state #### Scenario: Legacy Host reports devices - **WHEN** a statically configured legacy Host submits a valid device snapshot - **THEN** the control plane retains the existing compatible snapshot and ownership-conflict behavior #### Scenario: Host reports no devices - **WHEN** a previously populated Host submits an empty device snapshot - **THEN** only that Host's prior pooled-device records are removed while durable enrollment records and devices owned by other Hosts remain unchanged ### Requirement: Host Agent receives work through outbound long-polling The Host Agent SHALL request assigned work for its own host through a configurable long-poll endpoint, and the control plane SHALL return at most one atomically claimable assignment per response or an empty timeout response. #### Scenario: Assigned work is available - **WHEN** a Host Agent long-polls and an unclaimed assignment exists for its host - **THEN** the control plane atomically transitions the assignment to dispatched and returns its task, device, attempt, lease, and execution payload #### Scenario: No work becomes available - **WHEN** no assignment for the host becomes available before the configured poll timeout - **THEN** the endpoint returns a normal empty response and the Host Agent may poll again with backoff ### Requirement: Active execution renews its lease The Host Agent SHALL renew the active assignment lease before expiry while execution continues, and SHALL treat loss or rejection of the lease as a stop condition for further planned actions where interruption is possible. #### Scenario: Lease renewal succeeds - **WHEN** the owning Host Agent renews an unexpired active lease - **THEN** the control plane extends its expiry without changing the task attempt or device assignment #### Scenario: Lease is stale or foreign - **WHEN** a Host Agent attempts to renew an expired, replaced, or differently owned lease - **THEN** the control plane returns a conflict and does not revive or alter the current attempt ### Requirement: Host Agent reports execution progress alongside lease renewal The Host Agent SHALL optionally include a bounded, screenshot-free progress summary (current step index, step status, and a short plain-text summary) in its periodic lease-renewal request for an active assignment, and the control plane SHALL accept and store only the most recent such summary per active assignment. #### Scenario: Progress is available at renewal time - **WHEN** the Host Agent renews the lease for an in-progress assignment and has a current step index, status, and summary available - **THEN** the renewal request includes that progress summary and the control plane overwrites any previously stored progress for that assignment with it #### Scenario: Progress is not available at renewal time - **WHEN** the Host Agent renews a lease without a progress summary available (for example, before the first step completes) - **THEN** the renewal request omits the progress field and any previously stored progress for that assignment is left unchanged #### Scenario: Assignment reaches a terminal state - **WHEN** an assignment's terminal result is recorded - **THEN** the control plane's stored progress for that assignment is no longer treated as current and is not exposed as an in-progress status ### Requirement: Progress reports exclude screenshot and scene payloads The control plane SHALL reject or ignore any progress field on a renewal request that includes screenshot, scene, or other bulk payload data beyond the bounded step index, status, and short text summary. #### Scenario: Renewal request includes an oversized or non-text summary - **WHEN** a Host Agent submits a progress summary exceeding the configured length bound - **THEN** the control plane truncates or rejects the oversized field without failing the underlying lease renewal ### Requirement: Host execution composes existing Runtime and workflow runners The Host Agent SHALL execute goal assignments through the existing `TaskRunner` and workflow assignments through the existing `WorkflowRunner`, using its local `DeviceManager` and Runtime configuration rather than reimplementing execution behavior. #### Scenario: Execute a goal assignment - **WHEN** the Host Agent claims a goal-based assignment for a connected local device - **THEN** it runs a `Task` through the configured Runtime Planner/Executor loop and captures the terminal status and failure reason #### Scenario: Execute a workflow assignment - **WHEN** the Host Agent claims an assignment referencing an available workflow definition - **THEN** it invokes the existing workflow runner for the assigned device and captures the terminal workflow outcome ### Requirement: Terminal result reporting is idempotent The Host Agent SHALL report a terminal result using the task, attempt, and lease identifiers, and repeating the same report SHALL return the already recorded outcome without duplicating state transitions. #### Scenario: Report a successful result - **WHEN** the active lease owner reports successful completion - **THEN** the control plane marks the scheduled task done, releases the device reservation, and records the result metadata #### Scenario: Retry a result after response loss - **WHEN** the Host Agent repeats the identical terminal report for an already completed active lease - **THEN** the control plane returns the recorded terminal result without creating a new attempt or error #### Scenario: Stale attempt reports after requeue - **WHEN** an expired earlier attempt reports after a newer attempt has been created - **THEN** the control plane rejects the stale report and preserves the newer attempt's state ### Requirement: Host operation requires no inbound cloud connection The Host Agent SHALL perform synchronization, work retrieval, lease renewal, and result reporting using outbound requests only. #### Scenario: Host is behind NAT - **WHEN** the Host Agent can reach the control-plane URL but exposes no inbound listener - **THEN** it can register devices and execute cloud assignments through the complete protocol ### Requirement: Managed Host startup enrolls before normal protocol loops The Host Agent SHALL resolve its Host identity and cloud device mappings before starting heartbeat synchronization or assignment long-polling. #### Scenario: New managed Host starts - **WHEN** the Host Agent has an enrollment token but no completed local Host identity - **THEN** it performs idempotent Host enrollment, enrolls configured local devices, constructs its `DeviceManager` with cloud device IDs, and only then starts heartbeat and claim loops #### Scenario: Explicit legacy credentials are configured - **WHEN** both `HOST_AGENT_HOST_ID` and `HOST_AGENT_TOKEN` are explicitly supplied - **THEN** the Host Agent skips bootstrap enrollment and preserves existing local device ID behavior