Skip to content

Commit ed6fd5e

Browse files
stainless-app[bot]alvinkam2001declan-scaleclaude
authored
release: 0.10.4 (#338)
Co-authored-by: alvinkam2001 <alvin.kam@scale.com> Co-authored-by: Declan Brady <declan.brady@scale.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent f17ad00 commit ed6fd5e

7 files changed

Lines changed: 108 additions & 9 deletions

File tree

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.10.3"
2+
".": "0.10.4"
33
}

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 0.10.4 (2026-05-04)
4+
5+
Full Changelog: [v0.10.3...v0.10.4](https://github.com/scaleapi/scale-agentex-python/compare/v0.10.3...v0.10.4)
6+
7+
### Features
8+
9+
* add service account id option for registering agentex agents ([8365771](https://github.com/scaleapi/scale-agentex-python/commit/83657710ddb95d61bb5173ca881fe602344ff495))
10+
311
## 0.10.3 (2026-04-30)
412

513
Full Changelog: [v0.10.2...v0.10.3](https://github.com/scaleapi/scale-agentex-python/compare/v0.10.2...v0.10.3)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "agentex-sdk"
3-
version = "0.10.3"
3+
version = "0.10.4"
44
description = "The official Python library for the agentex API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/agentex/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "agentex"
4-
__version__ = "0.10.3" # x-release-please-version
4+
__version__ = "0.10.4" # x-release-please-version

src/agentex/lib/sdk/config/environment_config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ def get_configs_for_env(self, env_target: str) -> dict[str, AgentEnvironmentConf
165165
account_id: 6887f093600ecd59bbbd3095
166166
helm_overrides:
167167
168+
The principal must contain exactly one of `user_id` or `service_account_id`.
169+
Use `service_account_id` to register an agent under a service account
170+
instead of a personal user identity:
171+
dev:
172+
kubernetes:
173+
namespace: "sgp-000-hello-acp"
174+
auth:
175+
principal:
176+
service_account_id: a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d
177+
account_id: 6887f093600ecd59bbbd3095
178+
168179
if the environment field is not explicitly set, we assume its the same as
169180
the name of the environment
170181
Args:

src/agentex/lib/sdk/config/validation.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,14 @@ def _validate_single_environment_config(env_name: str, env_config: AgentEnvironm
103103

104104
# Validate auth principal
105105
principal = env_config.auth.principal
106-
if not principal.get("user_id"):
107-
raise ValueError("Auth principal must contain non-empty 'user_id'")
106+
user_id = principal.get("user_id")
107+
service_account_id = principal.get("service_account_id")
108+
if not user_id and not service_account_id:
109+
raise ValueError("Auth principal must contain non-empty 'user_id' or 'service_account_id'")
110+
if user_id and service_account_id:
111+
raise ValueError("Auth principal must contain only one of 'user_id' or 'service_account_id', not both")
108112

109113
# Check for environment-specific user_id patterns
110-
user_id = principal["user_id"]
111114
if isinstance(user_id, str):
112115
if not any(env_name.lower() in user_id.lower() for env_name in ["dev", "prod", "staging", env_name]):
113116
logger.warning(
@@ -233,11 +236,12 @@ def generate_helpful_error_message(error: Exception, context: str = "") -> str:
233236
"1. Check file location: should be next to manifest.yaml\n"
234237
"2. Verify file permissions"
235238
)
236-
elif "user_id" in base_msg.lower():
239+
elif "user_id" in base_msg.lower() or "service_account_id" in base_msg.lower():
237240
base_msg += (
238241
"\n\n💡 Auth Principal Tips:\n"
239-
"- user_id should be unique per environment\n"
240-
"- Include environment name (e.g., 'dev_my_agent')\n"
242+
"- Set exactly one of 'user_id' or 'service_account_id'\n"
243+
"- The id should be unique per environment\n"
244+
"- For user_id, include environment name (e.g., 'dev_my_agent')\n"
241245
"- Use consistent naming convention across agents"
242246
)
243247
elif "namespace" in base_msg.lower():

tests/lib/cli/test_validation.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Tests for the auth-principal portion of the environments.yaml validator.
2+
3+
Covers the rule that an env config's principal must carry exactly one of
4+
`user_id` or `service_account_id` — the same shape that downstream services
5+
(agentex-auth, SGP) expect on the wire.
6+
"""
7+
8+
import pytest
9+
10+
from agentex.lib.sdk.config.validation import (
11+
EnvironmentsValidationError,
12+
validate_environments_config,
13+
)
14+
from agentex.lib.sdk.config.environment_config import (
15+
AgentAuthConfig,
16+
AgentKubernetesConfig,
17+
AgentEnvironmentConfig,
18+
AgentEnvironmentsConfig,
19+
)
20+
21+
22+
def _config_with_principal(principal: dict) -> AgentEnvironmentsConfig:
23+
return AgentEnvironmentsConfig(
24+
schema_version="v1",
25+
environments={
26+
"dev": AgentEnvironmentConfig(
27+
kubernetes=AgentKubernetesConfig(namespace="dev-ns"),
28+
auth=AgentAuthConfig(principal=principal),
29+
)
30+
},
31+
)
32+
33+
34+
def test_user_only_principal_passes():
35+
"""Existing user_id-only configs continue to validate (backwards compat)."""
36+
config = _config_with_principal({"user_id": "73d0c8bd-4726-434c-9686-eb627d89f078", "account_id": "acct-1"})
37+
38+
validate_environments_config(config)
39+
40+
41+
def test_service_account_only_principal_passes():
42+
"""New service_account_id-only configs validate."""
43+
config = _config_with_principal(
44+
{"service_account_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "account_id": "acct-1"}
45+
)
46+
47+
validate_environments_config(config)
48+
49+
50+
def test_principal_with_neither_id_is_rejected():
51+
"""A principal with no identity id fails fast with a clear error."""
52+
config = _config_with_principal({"account_id": "acct-1"})
53+
54+
with pytest.raises(EnvironmentsValidationError) as exc_info:
55+
validate_environments_config(config)
56+
57+
msg = str(exc_info.value)
58+
assert "user_id" in msg
59+
assert "service_account_id" in msg
60+
61+
62+
def test_principal_with_both_ids_is_rejected():
63+
"""Setting both ids is a config error — the principal must commit to one identity type."""
64+
config = _config_with_principal(
65+
{
66+
"user_id": "73d0c8bd-4726-434c-9686-eb627d89f078",
67+
"service_account_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
68+
"account_id": "acct-1",
69+
}
70+
)
71+
72+
with pytest.raises(EnvironmentsValidationError) as exc_info:
73+
validate_environments_config(config)
74+
75+
msg = str(exc_info.value)
76+
assert "only one of" in msg.lower() or "not both" in msg.lower()

0 commit comments

Comments
 (0)