Repository navigation
feat(sdk): compose local agents with Desktop and Workstation - #222
Conversation
|
bugbot run |
|
bugbot run |
…t.local() Hand-written runtime management lives outside the generated package, so a codegen sync cannot wipe it. Local clients are built with Client.local() and AsyncClient.local(), keeping the generated constructors and their typing.
HTTP(S)_PROXY no longer receives the local runtime bearer token.
Every request to a local runtime carries a fresh X-Hai-Runtime-Challenge, and every response must carry X-Hai-Runtime-Proof, the HMAC-SHA256 of the challenge keyed by the runtime token. Unproven responses raise LocalRuntimeError, so a server squatting the runtime port never receives the bearer token and its commands never reach a device bridge. /health is proven before any bearer-authenticated request, both when spawning and when attaching.
…to charlie/placement-sdk-pins # Conflicts: # src/hai_agents_local/runtime/manifest.py
|
Pushed review fixes directly (as agreed).
Tests: 228 passed, 12 skipped. The release gate was checked both ways: it fails on the 0.1.8 pin and passes against a runtime that serves the shared recipe. Needs a runtime release with identity proofs plus a pin bump before this can ship. |
…to charlie/placement-sdk-pins
|
Folded #223 into this PR (fast-forward, no other changes). Merge order unchanged. |
…s, validates, dumps
|
Simplification pass (6 commits, net -139 lines, no behavior change)
Tests
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f4659fd. Configure here.

What
Expose local agent execution through the existing Python Agent API client, composed with local Desktop or remote Workstation environments. Own the local runtime lifecycle, authenticated attachment, command interruption and session resources; keep the hosted client default unchanged. Permission prompts run on the main thread.
Why
Each product currently has to manage its own local agent process and device bridge. The SDK should own that lifecycle behind the existing session interface.
How
Add Client(mode="local"), await AsyncClient.local(), and local runtime/process ownership, authenticated attachment, session resources and interruption through existing device bridges. Execute OS permission preflight on the main thread.
Validation and dependencies
P4; depends on P1/P2 HAI contracts/drivers/runtime and the matching P3 generation overlays. Runtime manifest defaults are preserved from the existing release, so this PR MUST NOT publish or merge until a verified compatible runtime and dependency floors are pinned. Explicit candidate overrides are for QA only.
Validation: 225 non-integration SDK tests pass, 12 skipped, on current main with the review runtime sources. Prior live QA covered local and cloud environments, file round trips, follow-ups and owned-command Stop. SDK workstation work already merged in #220 is excluded from this diff.
QA scope: real local-agent/local-environment and local-agent/cloud-environment runs cover files, follow-ups, Stop and reuse. Candidate hosted-agent combinations and packaged visual parity remain unverified. HoloWork integration is deferred.
Stack navigation: P1 contract → P2 runtime; P3 generation + P4 SDK; P5 checks: runtime, generation, SDK pins; P6 CLI. P7 duplicate pin cleanup follows only after P6 ships. HoloWork integration is subsequent work.
Review guide: intent, architecture, service tradeoffs and merge order.
CI dependency constraint: the published hai-drivers dependency lacks DesktopCommandRunner, so the real SDK/driver Stop regression fails collection in hosted CI until the compatible driver is available. It passes with candidate drivers locally; it has not been skipped to hide the dependency. Changed Python files pass Ruff lint and format.
Lifecycle refinements from review: downloads run outside the per-port spawn lock; idle probes close their HTTP pools; failed cancellation retains the exit retry; startup cleanup preserves the original error; credential cleanup uses the startup lock; asynchronous startup has an awaited, cancellation-safe factory. Regression tests exercise these boundaries.
Note
High Risk
New local runtime spawn, verified downloads, token files, and authenticated loopback attachment are security- and lifecycle-sensitive; bridge/session stop and concurrent startup locking affect long-running agent sessions.
Overview
Adds
Client.local()/AsyncClient.local()so agents run against a loopback hai-agent-runtime while reusing the existing sessions API; hostedClient()behavior is unchanged. Clients can start or attach to a runtime, optionally wire self-hosted inference, and close tears down bridged sessions and stops an owned runtime when idle.Introduces
hai_agents_local.runtime: pinned sha256-verified binary download/install, spawn/health checks, owner-only token/pid state, startup locking, and HMAC challenge–response so HTTP clients reject the wrong process on the port.scripts/bump_runtime.pyandpin.jsonmaintain the manifest; publish CI gains a macOSruntime-pingate before PyPI.Local sessions now track owned bridges, cancel/stop more reliably (including 410 channel closed as clean exit), run macOS permission preflight on the main thread before async bridge startup, and interrupt drivers when Stop is requested. README documents local-agent usage.
Reviewed by Cursor Bugbot for commit 89a992e. Bugbot is set up for automated code reviews on this repo. Configure here.