Repository navigation
Give deployment default model providers one home and close the self-hosted model gap - #140
Merged
Merged
Conversation
…osted and self-hosted Sessions Model credentials get one visible home and the self-hosted model gap from the fc19bd5 acceptance (D2, D3) is closed. - Deployment default model providers are a runtime setting: one complete bundle per harness in PostgreSQL (migration 000075), sealed with a new harness-bound credential purpose, managed only with the Core key through GET /core/v1/harnesses and GET/PUT/DELETE /core/v1/harnesses/{harness}/model-provider. Reads return the safe view (api_key_configured, updated_at), never the key. Writes are audited as deployment-wide admin_audit_log entries with a null tenant/project scope. - Provider precedence stays Session, saved Agent, deployment default. The default applies to openai_hosted and none Sessions and is frozen through the existing encrypted Session snapshot; later edits never reach existing Sessions. self_hosted Sessions now accept Session and Agent bundles, delivered over the existing daemon connection, and never use the deployment default. - openai_hosted and self_hosted Sessions without a bundle are rejected at creation with 400 model_provider_required. Legacy rows without a snapshot are rejected at message admission and at dispatch instead of falling back to a built-in endpoint. deploy/install/model_provider_sessions.py counts them read-only before an upgrade. - AGENTS_API_EXECUTION_OPTIONS_FILE is retired and stops startup with the replacement named. Historical snapshots keep their frozen native options. The execution-configuration read shows the safe view of new deployment selections. - packages/agents-client: listHarnesses, retrieveHarnessModelProvider, setHarnessModelProvider, deleteHarnessModelProvider, CoreHarness, HarnessModelProvider; audit entries may have project_id null. - Contracts, docs and the Core OpenAPI are updated. Tests that create hosted or self-hosted Sessions use shared provider fixtures instead of relaxing the check.
The error for AGENTS_API_EXECUTION_OPTIONS_FILE now says to remove the setting
and set deployment default model providers in Web (System) or with
PUT /core/v1/harnesses/{harness}/model-provider. The import command it named
does not exist yet; the import work adds it back.
…ess review P2-1: A same-key retry of a none Session conflicted after the deployment default changed, because the resolved provider fed the retry hash while caller intent was recorded only for openai_hosted. Caller intent is now recorded whenever the deployment default may apply (openai_hosted and none), and a provider key enters any stored hash only as a fingerprint keyed by the credential key (new Cipher.Fingerprint), never directly. Without the key, an intent lookup cannot match and creation reports the missing key. none Sessions now compare caller intent on retry, like hosted ones; rows without recorded intent keep the resolved-equivalence rule. Review follow-ups: - Input reserved before providers were required fails with model_provider_required (new environment_input_reservations.failure_code, migration 000075) instead of waiting for its deadline, and the Session reports that reason. - The 000075 down migration also refuses while deployment model providers exist. - Scope wording: the deployment default applies to openai_hosted and none, never to self_hosted, in the public API guide, the self_hosted 400 message, the client JSDoc and related docs. - Tests: none retry after the default is rotated and removed; a self-hosted preparation carries the frozen provider only to the bound executor; legacy reservations settle as failed. - Docs: a saved Agent's provider key reaches every self_hosted executor created with that Agent in the Project; legacy none Sessions run with the device's own environment and are not counted by the pre-upgrade check.
The vault intent unit test assumed a none Session without Vaults records no caller intent. none and openai_hosted now always record it; the unrelated inline identity case moves to self_hosted, where the default never applies.
…l-providers # Conflicts: # contracts/agents-api/v1/model_provider_admission.go # packages/agents-client/src/execution-configuration-projection.ts
Main's public URL binding (#138) took 000075.
…l-providers # Conflicts: # contracts/agents-api/core.openapi.yaml # docs/api/README.md # packages/agents-client/src/admin-client.ts # packages/agents-client/src/admin-projection.ts # services/agents-api/HOSTED-RELEASE.md # services/agents-api/cmd/server/process_configuration.go
P2-1: Recording raw caller intent for none Sessions broke the documented retry equivalence (omitted, null and explicit medium verbosity). none keeps the resolved-request rule again; caller intent stays hosted-only as before. The resolved hash now leaves out a deployment-sourced provider bundle and its configuration marker, so setting, rotating or removing the default does not change a none Session's retry identity. The earlier test edits for the intent-for-none rule are reverted. Review follow-ups: - withoutProviderKey fails closed: an intent whose extension or provider cannot be read is rejected, and the provider is re-encoded from its typed value with the key replaced by its keyed fingerprint. - Cipher.Fingerprint rejects a NUL in the purpose. - New test: the same request under two credential keys gets different request_hash and creation_request_hash; an unreadable provider intent is rejected. - The legacy test again asserts that a rejected submit queues nothing. - The none retry test also retries with a spelled-out default verbosity. - model-execution.md notes that key-bearing retries first sent before this release, or after a credential key change, conflict once.
This was referenced Sep 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 PR A of the new-user install work. Model credentials get one visible home, and the self-hosted model gap found in the boundary release acceptance is closed.
GET /core/v1/harnesseslists the harnesses withenabled,defaultand each harness's deployment provider (safe view).GET/PUT/DELETE /core/v1/harnesses/{harness}/model-provider: the PUT body is exactlyx_agents_core.model_provider.project_id: null).000076_deployment_model_providersadds the table and the nullable audit scope.openai_hostedand to Sessions without an environment, never toself_hosted.AGENTS_API_EXECUTION_OPTIONS_FILEis retired. Setting it, even empty, stops Core at startup and points to Web (System) orPUT /core/v1/harnesses/{harness}/model-provider.self_hostedSessions may carry caller model credentials, in the request or on a saved Agent. They go only to that Session's bound executor, over the existing daemon channel.openai_hostedorself_hostedSession with no resolvable provider returns 400model_provider_required, paramx_agents_core.model_provider. Before, it silently fell back to Codex's built-in provider and hung. Pending input from before the upgrade settles as failed withmodel_provider_requiredinstead of looping.listHarnesses,retrieveHarnessModelProvider,setHarnessModelProvider,deleteHarnessModelProvider,CoreHarnessandHarnessModelProvider, with strict projections.deploy/install/model_provider_sessions.pyis a read-only count of legacy hosted and self-hosted Sessions that have no frozen provider.Review
e72acdd2, verified by tests, the native verifier and the gate.Verification
2cc35bed(the exact head, including main31b64e38): passed. Playwright browser cases were skipped on the server (Chrome unavailable; approved skip).native-defaultretries return the original Session after the default is rotated and after it is removed. The test needs one local edit because of an unrelated breakage on main since Use the colocated daemon as the V1 user-managed executor #8; that is tracked separately.Compatibility and ops
AGENTS_API_EXECUTION_OPTIONS_FILEmust remove it and set deployment defaults in Web or with the new route. A one-time import throughparsar applyfollows with phase 1b.Need help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.