Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ def workflow_output_types(self) -> list[type[Any]]:
return [AgentRunResponse]
return []

@property
def description(self) -> str | None:
"""Get the description of the underlying agent."""
return self._agent.description

@handler
async def run(
self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse]
Expand Down
761 changes: 511 additions & 250 deletions python/packages/core/agent_framework/_workflows/_handoff.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,13 @@ def wrap_participant(participant: AgentProtocol | Executor, *, executor_id: str
"""Represent `participant` as an `Executor`."""
if isinstance(participant, Executor):
return participant

if not isinstance(participant, AgentProtocol):
raise TypeError(
f"Participants must implement AgentProtocol or be Executor instances. Got {type(participant).__name__}."
)
name = getattr(participant, "name", None)
if executor_id is None:
if not name:
raise ValueError("Agent participants must expose a stable 'name' attribute.")
executor_id = str(name)

executor_id = executor_id or participant.display_name
return AgentExecutor(participant, id=executor_id)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def register_participants(
"Cannot mix .participants([...]) and .register_participants() in the same builder instance."
)

if self._participant_factories:
raise ValueError("register_participants() has already been called on this builder instance.")

if not participant_factories:
raise ValueError("participant_factories cannot be empty")

Expand All @@ -171,6 +174,9 @@ def participants(self, participants: Sequence[AgentProtocol | Executor]) -> "Seq
"Cannot mix .participants([...]) and .register_participants() in the same builder instance."
)

if self._participants:
raise ValueError("participants() has already been called on this builder instance.")

if not participants:
raise ValueError("participants cannot be empty")

Expand Down
3 changes: 3 additions & 0 deletions python/packages/core/agent_framework/openai/_chat_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ def _prepare_options(self, messages: MutableSequence[ChatMessage], chat_options:
exclude={
"type",
"instructions", # included as system message
"allow_multiple_tool_calls", # handled separately
}
)

Expand All @@ -174,6 +175,8 @@ def _prepare_options(self, messages: MutableSequence[ChatMessage], chat_options:
if web_search_options:
options_dict["web_search_options"] = web_search_options
options_dict["tools"] = self._chat_to_tool_spec(chat_options.tools)
if chat_options.allow_multiple_tool_calls is not None:
options_dict["parallel_tool_calls"] = chat_options.allow_multiple_tool_calls
if not options_dict.get("tools", None):
options_dict.pop("tools", None)
options_dict.pop("parallel_tool_calls", None)
Expand Down
Loading
Loading