Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions services/core/internal/api/session_model_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ func (h *Handler) resolveSessionExecution(ctx context.Context, input sessionRequ
provider, source = extension.ModelProvider, v1.ModelProviderSourceSession
}
}
// The guest daemon of a self_hosted Environment runs on the caller's
// machine, so a deployment key must not reach it until the Harness runs on
// an agent host.
if provider == nil && input.Environment.Type == "self_hosted" {
return "", nil, "", uuid.Nil, &modelProviderRequiredError{"self_hosted Sessions need a model provider for harness " + engine + ": pass x_agents_core.model_provider or use an Agent that has one saved."}
}
if provider == nil && input.deploymentDefaults != nil {
provider, source, revision = input.deploymentDefaults.Provider, v1.ModelProviderSourceDeployment, input.deploymentDefaults.Revision
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,22 @@ func TestDeploymentModelProvidersHTTP(t *testing.T) {
t.Fatal("a changed default reached an existing Session")
}

// Every Environment type accepts every source and freezes it.
// Every Environment type accepts every source and freezes it, except that
// a self_hosted guest never receives the deployment key.
agentID := text(call("POST", "/v1/agents", projectKey, `{"model":"agent-model","x_agents_core":{"model_provider":{"protocol":"responses","base_url":"https://agent.example/v1","api_key":"agent-canary"}}}`, 201)["id"])
for name, environment := range environments {
for _, tc := range []struct{ source, body, key string }{
{"session", `{"agent":{"model":"m"},` + environment + `,"x_agents_core":{"model_provider":{"protocol":"responses","base_url":"https://session.example/v1","api_key":"session-canary"}}}`, "session-canary"},
{"agent", `{"agent_id":"` + agentID + `",` + environment + `}`, "agent-canary"},
{"deployment", `{"agent":{"model":"m"},` + environment + `}`, "changed-canary"},
} {
if name == "self_hosted" && tc.source == "deployment" {
failure := call("POST", "/v1/agents/sessions", projectKey, tc.body, 400)
if !strings.Contains(string(failure["error"]), `"code":"model_provider_required","param":"x_agents_core.model_provider"`) {
t.Fatalf("self_hosted accepted the deployment default: %s", failure["error"])
}
continue
}
id := text(call("POST", "/v1/agents/sessions", projectKey, tc.body, 201)["id"])
projection, err := sessionAdapter(st).GetSessionExecutionConfiguration(t.Context(), tenant, id)
if providerOf(id) != tc.key || err != nil || projection.ModelProvider.Source != tc.source {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,16 @@ func TestUnifiedModelConfigurationHTTP(t *testing.T) {
{"explicit empty inline parameters", `{"agent":{"x_agents_core":{"harness_config":{}}},"environment":{"type":"openai_hosted"}}`, "model-replacement", "deployment", "deployment", "deployment-canary"},
{"explicit empty Session parameters", `{"agent":{},"environment":{"type":"openai_hosted"},"x_agents_core":{"harness_config":{}}}`, "model-replacement", "deployment", "deployment", "deployment-canary"},
} {
// self_hosted resolves deployment defaults exactly as openai_hosted does.
// self_hosted resolves native defaults exactly as openai_hosted does,
// but its guest never receives the deployment key.
for _, environment := range []string{`{"type":"openai_hosted"}`, `{"type":"self_hosted","workspace_directory":"/workspace"}`} {
t.Run(tc.name+" "+environment, func(t *testing.T) {
id := create(strings.Replace(tc.body, `{"type":"openai_hosted"}`, environment, 1), uuid.NewString())
body := strings.Replace(tc.body, `{"type":"openai_hosted"}`, environment, 1)
if strings.Contains(environment, "self_hosted") && tc.providerSource == "deployment" {
call("POST", "/v1/agents/sessions", token, body, uuid.NewString(), 400)
return
}
id := create(body, uuid.NewString())
assertSession(id, tc.model, `{}`, tc.modelSource, "session", tc.providerSource, tc.key)
})
}
Expand Down