Skip to content

Commit f8bd111

Browse files
committed
update
1 parent f22586f commit f8bd111

File tree

2 files changed

+55
-36
lines changed

2 files changed

+55
-36
lines changed

openhands-sdk/openhands/sdk/subagent/registry.py

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -57,40 +57,6 @@ class AgentFactory(NamedTuple):
5757
_registry_lock = RLock()
5858

5959

60-
def _definition_from_factory(
61-
name: str,
62-
factory_func: Callable[["LLM"], "Agent"],
63-
description: str,
64-
) -> AgentDefinition:
65-
"""Introspect *factory_func* with a dummy LLM to build a full AgentDefinition.
66-
67-
This lets register_agent() accept just (name, factory_func, description)
68-
while still producing a complete definition (tools, system_prompt, model)
69-
that can be forwarded to a remote server. Falls back to a minimal
70-
definition if the factory raises.
71-
"""
72-
_model_placeholder = "__introspect__"
73-
try:
74-
from openhands.sdk.llm.llm import LLM as _LLM
75-
76-
agent = factory_func(_LLM(model=_model_placeholder, api_key=SecretStr("n/a")))
77-
tools = [t.name for t in agent.tools]
78-
system_prompt = ""
79-
if agent.agent_context and agent.agent_context.system_message_suffix:
80-
system_prompt = agent.agent_context.system_message_suffix
81-
model = agent.llm.model if agent.llm.model != _model_placeholder else "inherit"
82-
return AgentDefinition(
83-
name=name,
84-
description=description,
85-
tools=tools,
86-
system_prompt=system_prompt,
87-
model=model,
88-
)
89-
except Exception:
90-
logger.debug(f"Could not introspect factory for agent '{name}'")
91-
return AgentDefinition(name=name, description=description)
92-
93-
9460
def register_agent(
9561
name: str,
9662
factory_func: Callable[["LLM"], "Agent"],
@@ -107,13 +73,28 @@ def register_agent(
10773
Raises:
10874
ValueError: If an agent with the same name already exists
10975
"""
76+
try:
77+
from openhands.sdk.llm.llm import LLM as _LLM
78+
79+
_model_placeholder = "__introspect__"
80+
agent = factory_func(_LLM(model=_model_placeholder, api_key=SecretStr("n/a")))
81+
definition = AgentDefinition.from_agent(
82+
agent, name=name, description=description
83+
)
84+
# If the model was our placeholder, the factory didn't set one explicitly
85+
if definition.model == _model_placeholder:
86+
definition = definition.model_copy(update={"model": "inherit"})
87+
except Exception:
88+
logger.debug(f"Could not introspect factory for agent '{name}'")
89+
definition = AgentDefinition(name=name, description=description)
90+
11091
with _registry_lock:
11192
if name in _agent_factories:
11293
raise ValueError(f"Agent '{name}' already registered")
11394

11495
_agent_factories[name] = AgentFactory(
11596
factory_func=factory_func,
116-
definition=_definition_from_factory(name, factory_func, description),
97+
definition=definition,
11798
)
11899

119100

openhands-sdk/openhands/sdk/subagent/schema.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44

55
import re
66
from pathlib import Path
7-
from typing import Any
7+
from typing import TYPE_CHECKING, Any
88

99
import frontmatter
1010
from pydantic import BaseModel, Field
1111

1212

13+
if TYPE_CHECKING:
14+
from openhands.sdk.agent.base import AgentBase
15+
16+
1317
def _extract_examples(description: str) -> list[str]:
1418
"""Extract <example> tags from description for agent triggering."""
1519
pattern = r"<example>(.*?)</example>"
@@ -111,3 +115,37 @@ def load(cls, agent_path: Path) -> AgentDefinition:
111115
when_to_use_examples=when_to_use_examples,
112116
metadata=metadata,
113117
)
118+
119+
@classmethod
120+
def from_agent(
121+
cls,
122+
agent: AgentBase,
123+
name: str,
124+
description: str,
125+
) -> AgentDefinition:
126+
"""Build an AgentDefinition by introspecting a live Agent instance.
127+
128+
Args:
129+
agent: The agent to extract configuration from.
130+
name: Name for the agent definition.
131+
description: Human-readable description of the agent.
132+
133+
Returns:
134+
A fully populated AgentDefinition.
135+
"""
136+
tools = [t.name for t in agent.tools]
137+
138+
if agent.agent_context and agent.agent_context.system_message_suffix:
139+
system_prompt = agent.agent_context.system_message_suffix
140+
else:
141+
system_prompt = ""
142+
143+
model = agent.llm.model if agent.llm.model else "inherit"
144+
145+
return cls(
146+
name=name,
147+
description=description,
148+
tools=tools,
149+
system_prompt=system_prompt,
150+
model=model,
151+
)

0 commit comments

Comments
 (0)