Skip to content

Commit 9158a1d

Browse files
simonrosenbergDebug Agent
andauthored
feat(sdk): split AgentSettings into LLM/ACP discriminated union (#2861)
Co-authored-by: Debug Agent <debug@example.com>
1 parent 5f06907 commit 9158a1d

File tree

7 files changed

+789
-181
lines changed

7 files changed

+789
-181
lines changed

examples/01_standalone_sdk/46_agent_settings.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
"""Create, serialize, and deserialize AgentSettings, then build a working agent.
1+
"""Create, serialize, and deserialize LLMAgentSettings, then build a working agent.
22
33
Demonstrates:
4-
1. Configuring an agent entirely through AgentSettings (LLM, tools, condenser).
4+
1. Configuring an agent entirely through LLMAgentSettings (LLM, tools, condenser).
55
2. Serializing settings to JSON and restoring them.
66
3. Building an Agent from settings via ``create_agent()``.
77
4. Running a short conversation to prove the settings take effect.
@@ -13,7 +13,7 @@
1313

1414
from pydantic import SecretStr
1515

16-
from openhands.sdk import LLM, AgentSettings, Conversation, Tool
16+
from openhands.sdk import LLM, Conversation, LLMAgentSettings, Tool
1717
from openhands.sdk.settings import CondenserSettings
1818
from openhands.tools.file_editor import FileEditorTool
1919
from openhands.tools.terminal import TerminalTool
@@ -23,7 +23,7 @@
2323
api_key = os.getenv("LLM_API_KEY")
2424
assert api_key is not None, "LLM_API_KEY environment variable is not set."
2525

26-
settings = AgentSettings(
26+
settings = LLMAgentSettings(
2727
llm=LLM(
2828
model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
2929
api_key=SecretStr(api_key),
@@ -42,7 +42,7 @@
4242
print(json.dumps(payload, indent=2, default=str)[:800], "…")
4343
print()
4444

45-
restored = AgentSettings.model_validate(payload)
45+
restored = LLMAgentSettings.model_validate(payload)
4646
assert restored.condenser.enabled is True
4747
assert restored.condenser.max_size == 50
4848
assert len(restored.tools) == 2
@@ -73,7 +73,7 @@
7373

7474
# ── 4. Different settings → different behavior ───────────────────────────
7575
# Now create settings with ONLY the terminal tool and condenser disabled.
76-
terminal_only_settings = AgentSettings(
76+
terminal_only_settings = LLMAgentSettings(
7777
llm=settings.llm,
7878
tools=[Tool(name=TerminalTool.name)],
7979
condenser=CondenserSettings(enabled=False),

openhands-agent-server/openhands/agent_server/settings_router.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22

33
from fastapi import APIRouter
44

5-
from openhands.sdk.settings import AgentSettings, ConversationSettings, SettingsSchema
5+
from openhands.sdk.settings import (
6+
ConversationSettings,
7+
SettingsSchema,
8+
export_agent_settings_schema,
9+
)
610

711

812
settings_router = APIRouter(prefix="/settings", tags=["Settings"])
913

1014

1115
@lru_cache(maxsize=1)
1216
def _get_agent_settings_schema() -> SettingsSchema:
13-
return AgentSettings.export_schema()
17+
# ``AgentSettings`` is now a discriminated union over
18+
# ``LLMAgentSettings`` and ``ACPAgentSettings``; the combined
19+
# schema tags sections with a ``variant`` so the frontend can
20+
# show LLM-only or ACP-only sections based on the active
21+
# ``agent_kind`` value.
22+
return export_agent_settings_schema()
1423

1524

1625
@lru_cache(maxsize=1)

openhands-sdk/openhands/sdk/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,21 @@
4545
)
4646
from openhands.sdk.plugin import Plugin
4747
from openhands.sdk.settings import (
48+
ACPAgentSettings,
4849
AgentSettings,
50+
AgentSettingsConfig,
4951
CondenserSettings,
5052
ConversationSettings,
53+
LLMAgentSettings,
5154
SettingsChoice,
5255
SettingsFieldSchema,
5356
SettingsSchema,
5457
SettingsSectionSchema,
5558
VerificationSettings,
59+
default_agent_settings,
60+
export_agent_settings_schema,
5661
export_settings_schema,
62+
validate_agent_settings,
5763
)
5864
from openhands.sdk.settings.metadata import (
5965
SettingProminence,
@@ -140,7 +146,13 @@
140146
"CondenserSettings",
141147
"ConversationSettings",
142148
"VerificationSettings",
149+
"ACPAgentSettings",
143150
"AgentSettings",
151+
"AgentSettingsConfig",
152+
"LLMAgentSettings",
153+
"default_agent_settings",
154+
"export_agent_settings_schema",
155+
"validate_agent_settings",
144156
"SettingsChoice",
145157
"SettingProminence",
146158
"SettingsFieldMetadata",

openhands-sdk/openhands/sdk/settings/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,57 @@
1616
from .model import (
1717
AGENT_SETTINGS_SCHEMA_VERSION,
1818
CONVERSATION_SETTINGS_SCHEMA_VERSION,
19+
ACPAgentSettings,
20+
AgentKind,
1921
AgentSettings,
22+
AgentSettingsConfig,
2023
CondenserSettings,
2124
ConversationSettings,
25+
LLMAgentSettings,
2226
SettingsChoice,
2327
SettingsFieldSchema,
2428
SettingsSchema,
2529
SettingsSectionSchema,
2630
VerificationSettings,
31+
create_agent_from_settings,
32+
default_agent_settings,
33+
export_agent_settings_schema,
2734
export_settings_schema,
35+
validate_agent_settings,
2836
)
2937

3038
_MODEL_EXPORTS = {
3139
"AGENT_SETTINGS_SCHEMA_VERSION",
3240
"CONVERSATION_SETTINGS_SCHEMA_VERSION",
41+
"ACPAgentSettings",
42+
"AgentKind",
3343
"AgentSettings",
44+
"AgentSettingsConfig",
3445
"CondenserSettings",
3546
"ConversationSettings",
47+
"LLMAgentSettings",
3648
"SettingsChoice",
3749
"SettingsFieldSchema",
3850
"SettingsSchema",
3951
"SettingsSectionSchema",
4052
"VerificationSettings",
53+
"create_agent_from_settings",
54+
"default_agent_settings",
55+
"export_agent_settings_schema",
4156
"export_settings_schema",
57+
"validate_agent_settings",
4258
}
4359

4460
__all__ = [
4561
"AGENT_SETTINGS_SCHEMA_VERSION",
4662
"CONVERSATION_SETTINGS_SCHEMA_VERSION",
63+
"ACPAgentSettings",
64+
"AgentKind",
4765
"AgentSettings",
66+
"AgentSettingsConfig",
4867
"CondenserSettings",
4968
"ConversationSettings",
69+
"LLMAgentSettings",
5070
"SETTINGS_METADATA_KEY",
5171
"SETTINGS_SECTION_METADATA_KEY",
5272
"SettingProminence",
@@ -57,8 +77,12 @@
5777
"SettingsSectionMetadata",
5878
"SettingsSectionSchema",
5979
"VerificationSettings",
80+
"create_agent_from_settings",
81+
"default_agent_settings",
82+
"export_agent_settings_schema",
6083
"export_settings_schema",
6184
"field_meta",
85+
"validate_agent_settings",
6286
]
6387

6488

openhands-sdk/openhands/sdk/settings/metadata.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ class SettingProminence(str, Enum):
1919
class SettingsSectionMetadata(BaseModel):
2020
key: str
2121
label: str | None = None
22+
variant: str | None = None
2223

2324

2425
class SettingsFieldMetadata(BaseModel):
2526
label: str | None = None
2627
prominence: SettingProminence = SettingProminence.MINOR
2728
depends_on: tuple[str, ...] = ()
29+
variant: str | None = None
30+
"""When set, the field only applies to the named ``AgentSettings``
31+
variant (``"llm"`` or ``"acp"``). Fields with ``variant=None`` are
32+
shown regardless of the active ``agent_kind``."""
2833

2934

3035
def field_meta(

0 commit comments

Comments
 (0)