This commit is contained in:
@@ -36,8 +36,8 @@ which raises the stakes on where its provider credentials live.
|
||||
- Reuse existing Host<->Cloud authentication and existing provider
|
||||
wire-format code; add no new auth scope and no duplicated Anthropic/OpenAI
|
||||
translation logic.
|
||||
- Preserve today's direct-to-provider path as a fully supported, still-default
|
||||
option, so existing Host Agent deployments with local keys are unaffected.
|
||||
- Preserve the direct-to-provider path as a fully supported explicit opt-out
|
||||
for Host Agent deployments that require local provider keys.
|
||||
|
||||
**Non-Goals:**
|
||||
- Not moving prompt construction (`runtime/planner_prompts.py`, Scene
|
||||
@@ -74,13 +74,12 @@ must stay in lockstep with the Host Agent's local transport as providers'
|
||||
APIs evolve.
|
||||
|
||||
### D2: New transport axis, orthogonal to provider selection
|
||||
Host Agent config gains `AI_PLANNER_TRANSPORT` (`direct` default | `cloud`),
|
||||
independent of `AI_PLANNER_PROVIDER`. `direct` is today's behavior
|
||||
unchanged (Host Agent builds the SDK client itself). `cloud` builds a new
|
||||
Host Agent config gains `AI_PLANNER_TRANSPORT` (`cloud` default | `direct`),
|
||||
independent of `AI_PLANNER_PROVIDER`. `cloud` builds a new
|
||||
`CloudProxyToolCallingClient` instead; provider/model selection and
|
||||
credentials for that path live in the Cloud API's own
|
||||
`AI_PLANNER_PROVIDER`/`AI_PLANNER_MODEL`/`ANTHROPIC_API_KEY`/`OPENAI_API_KEY`
|
||||
configuration, not the Host Agent's.
|
||||
active Provider profile, not the Host Agent's. `direct` remains an explicit
|
||||
opt-out that builds the provider SDK client locally.
|
||||
|
||||
Alternative considered: overload `AI_PLANNER_PROVIDER=cloud` as a third
|
||||
provider value. Rejected: provider and transport are different axes (a
|
||||
@@ -158,9 +157,9 @@ proposal does not change that risk profile, only where the call happens.
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Risk] Cloud Control Plane is now in the hot path of every planning
|
||||
step for hosts on the `cloud` transport** -> Mitigation: `direct`
|
||||
transport remains the default and fully supported; operators who need
|
||||
offline/low-latency operation simply don't opt in. Bounded by the
|
||||
step by default** -> Mitigation: `direct` transport remains fully
|
||||
supported as an explicit opt-out for operators who need offline or
|
||||
low-latency operation. Bounded by the
|
||||
existing `AI_PLANNER_TIMEOUT_SECONDS`, same as today.
|
||||
- **[Risk] Cloud Control Plane outage now stalls planning (not just new
|
||||
task assignment) for opted-in hosts** -> Mitigation: same
|
||||
@@ -195,20 +194,17 @@ proposal does not change that risk profile, only where the call happens.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add Cloud API configuration (`AI_PLANNER_PROVIDER`/`AI_PLANNER_MODEL`/
|
||||
`AI_PLANNER_TIMEOUT_SECONDS`/provider API keys) and the new internal
|
||||
route, guarded by the existing host-scoped auth. Off by default in the
|
||||
sense that no Host Agent calls it until configured to use `cloud`
|
||||
transport.
|
||||
2. Add the Host Agent's `AI_PLANNER_TRANSPORT` setting (default `direct`)
|
||||
and `CloudProxyToolCallingClient`. Existing deployments are unaffected
|
||||
until an operator sets `AI_PLANNER_TRANSPORT=cloud` and removes the
|
||||
local provider key.
|
||||
1. Add Cloud API Provider profile management and the new internal route,
|
||||
guarded by the existing host-scoped auth. Configure and activate a
|
||||
Cloud-held Provider key before running a Host Agent.
|
||||
2. Add the Host Agent's `AI_PLANNER_TRANSPORT` setting (default `cloud`)
|
||||
and `CloudProxyToolCallingClient`. Existing deployments that require a
|
||||
local provider key set `AI_PLANNER_TRANSPORT=direct` explicitly.
|
||||
3. Update `docs/CLOUD_DEPLOYMENT.md` with the proxy configuration path and
|
||||
its trade-offs (latency, availability coupling, data-path expansion).
|
||||
4. Rollback is setting `AI_PLANNER_TRANSPORT=direct` (or unsetting it) on
|
||||
affected hosts and restoring their local provider key; the Cloud API
|
||||
route can remain deployed but unused.
|
||||
4. Rollback is setting `AI_PLANNER_TRANSPORT=direct` on affected Hosts and
|
||||
restoring their local provider key; the Cloud API route can remain
|
||||
deployed but unused.
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
@@ -22,12 +22,11 @@ provider/model or rotate a key without touching any Host.
|
||||
- Cloud API owns `AI_PLANNER_PROVIDER`/`AI_PLANNER_MODEL`/provider API keys
|
||||
as its own configuration; these are no longer required on the Host Agent
|
||||
when the new proxy transport is used.
|
||||
- Host Agent gains a new opt-in transport setting (proxy vs. direct-to-provider)
|
||||
- Host Agent gains a transport setting (cloud-proxy vs. direct-to-provider)
|
||||
and a new `ToolCallingClient` implementation that calls the cloud endpoint
|
||||
instead of constructing a local Anthropic/OpenAI SDK client. The existing
|
||||
direct-to-provider transport remains fully supported and is the default,
|
||||
so hosts that already run with a local provider key keep working
|
||||
unchanged.
|
||||
instead of constructing a local Anthropic/OpenAI SDK client. Cloud-proxy is
|
||||
the default; the existing direct-to-provider transport remains fully
|
||||
supported as an explicit opt-out for hosts with local provider keys.
|
||||
- Reuse the existing Host-scoped bearer credential (already used for
|
||||
heartbeat/claim/renew/result) for the new endpoint; no new auth scope.
|
||||
- Cloud API does not durably persist screenshot bytes or full prompt text
|
||||
|
||||
@@ -31,10 +31,15 @@ to `AIPlanner`'s own decision logic.
|
||||
transport, and its own decision logic is unchanged regardless of which
|
||||
transport is in effect
|
||||
|
||||
#### Scenario: Direct transport remains available and default
|
||||
#### Scenario: Cloud-proxy transport is the default
|
||||
- **WHEN** no transport is explicitly configured
|
||||
- **THEN** the AI Planner uses the direct-to-provider transport, matching
|
||||
its behavior before the cloud-proxy transport existed
|
||||
- **THEN** the AI Planner uses the cloud-proxy transport and the Cloud
|
||||
Control Plane's planner-decision endpoint
|
||||
|
||||
#### Scenario: Direct transport remains available by explicit configuration
|
||||
- **WHEN** the Host Agent is configured with the direct transport
|
||||
- **THEN** the AI Planner uses the direct-to-provider transport with locally
|
||||
configured credentials
|
||||
|
||||
#### Scenario: Cloud-proxy transport resolves a decision without a local provider client
|
||||
- **WHEN** the Host Agent is configured with the cloud-proxy transport
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
## 3. Host Agent: cloud-proxy transport
|
||||
|
||||
- [x] 3.1 Add `AI_PLANNER_TRANSPORT` (`direct` default | `cloud`) to
|
||||
- [x] 3.1 Add `AI_PLANNER_TRANSPORT` (`cloud` default | `direct`) to
|
||||
`apps/device-host-agent/host_agent/config.py`.
|
||||
Done: `HostAgentConfig.ai_planner_transport` +
|
||||
`_parse_ai_planner_transport`.
|
||||
@@ -70,11 +70,10 @@
|
||||
|
||||
- [x] 4.1 Update `apps/device-host-agent/host_agent/execution.py`'s
|
||||
`_host_agent_planner_config()`/`create_task_runner()` so that when
|
||||
`AI_PLANNER_TRANSPORT=cloud`, the constructed `TaskRunner`'s
|
||||
`AI_PLANNER_TRANSPORT` is unset or set to `cloud`, the constructed `TaskRunner`'s
|
||||
`AIPlanner` is built with a `CloudProxyToolCallingClient` instead of
|
||||
the default local provider client, while leaving the existing
|
||||
default-enabled/direct-transport behavior unchanged when
|
||||
`AI_PLANNER_TRANSPORT` is unset or `direct`.
|
||||
the local provider client, while `AI_PLANNER_TRANSPORT=direct` remains
|
||||
an explicit direct-to-provider fallback.
|
||||
Done: new `_host_agent_planner()` helper + `host_agent_config` param
|
||||
threaded through `create_execution_factories()` from
|
||||
`app.py::create_application()`. Manually verified both transports
|
||||
@@ -106,11 +105,10 @@
|
||||
(7 tests, using `httpx.MockTransport` -- success, screenshot
|
||||
base64-encoding, network error, structured 502 error, unstructured
|
||||
error response, and client-ownership on `close()`).
|
||||
- [x] 5.4 Unit tests for Host Agent wiring: `AI_PLANNER_TRANSPORT=cloud`
|
||||
constructs an `AIPlanner` using `CloudProxyToolCallingClient`;
|
||||
`AI_PLANNER_TRANSPORT` unset or `direct` preserves existing
|
||||
direct-to-provider construction (no regression to the
|
||||
already-implemented default-enabled behavior).
|
||||
- [x] 5.4 Unit tests for Host Agent wiring: `AI_PLANNER_TRANSPORT` unset or
|
||||
set to `cloud` constructs an `AIPlanner` using
|
||||
`CloudProxyToolCallingClient`; explicit `direct` preserves local
|
||||
provider construction.
|
||||
Done: added to `apps/device-host-agent/tests/test_execution.py`
|
||||
(2 new tests, one parametrized over `None`/`"direct"`).
|
||||
- [x] 5.5 Full non-integration suite (`uv run --all-packages pytest -m
|
||||
@@ -136,3 +134,9 @@
|
||||
full non-integration suite (492 passed); `python -m compileall` clean
|
||||
for `packages/cloud-platform/cloud`, `apps/cloud-api`,
|
||||
`apps/device-host-agent`.
|
||||
|
||||
## 8. Default transport amendment
|
||||
|
||||
- [x] 8.1 Make `cloud` the Host Agent default for
|
||||
`AI_PLANNER_TRANSPORT`, retain `direct` as an explicit fallback, and
|
||||
update the runtime contract, deployment guidance, and regression tests.
|
||||
|
||||
Reference in New Issue
Block a user