Skip to content

Commit 2dfcc0f

Browse files
chore: fix_schema-is-broken-in-workforce (#3170)
Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
1 parent 9d6a91e commit 2dfcc0f

File tree

2 files changed

+48
-17
lines changed

2 files changed

+48
-17
lines changed

camel/agents/chat_agent.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,6 @@ async def _astep_non_streaming_task(
16871687
return self._step_terminate(
16881688
e.args[1], tool_call_records, "max_tokens_exceeded"
16891689
)
1690-
16911690
response = await self._aget_model_response(
16921691
openai_messages,
16931692
num_tokens=num_tokens,
@@ -3770,7 +3769,7 @@ def clone(self, with_memory: bool = False) -> ChatAgent:
37703769
self.memory.get_context_creator(), "token_limit", None
37713770
),
37723771
output_language=self._output_language,
3773-
tools=cloned_tools,
3772+
tools=cast(List[Union[FunctionTool, Callable]], cloned_tools),
37743773
toolkits_to_register_agent=toolkits_to_register,
37753774
external_tools=[
37763775
schema for schema in self._external_tool_schemas.values()
@@ -3799,9 +3798,7 @@ def clone(self, with_memory: bool = False) -> ChatAgent:
37993798

38003799
def _clone_tools(
38013800
self,
3802-
) -> Tuple[
3803-
List[Union[FunctionTool, Callable]], List[RegisteredAgentToolkit]
3804-
]:
3801+
) -> Tuple[List[FunctionTool], List[RegisteredAgentToolkit]]:
38053802
r"""Clone tools and return toolkits that need agent registration.
38063803
38073804
This method handles stateful toolkits by cloning them if they have
@@ -3858,13 +3855,45 @@ def _clone_tools(
38583855
method_name = tool.func.__name__
38593856
if hasattr(toolkit, method_name):
38603857
new_method = getattr(toolkit, method_name)
3861-
cloned_tools.append(new_method)
3858+
# Wrap cloned method into a new FunctionTool,
3859+
# preserving schema
3860+
try:
3861+
new_tool = FunctionTool(
3862+
func=new_method,
3863+
openai_tool_schema=tool.get_openai_tool_schema(),
3864+
)
3865+
cloned_tools.append(new_tool)
3866+
except Exception as e:
3867+
# If wrapping fails, fallback to wrapping the original
3868+
# function with its schema to maintain consistency
3869+
logger.warning(
3870+
f"Failed to wrap cloned toolkit "
3871+
f"method '{method_name}' "
3872+
f"with FunctionTool: {e}. Using original "
3873+
f"function with preserved schema instead."
3874+
)
3875+
cloned_tools.append(
3876+
FunctionTool(
3877+
func=tool.func,
3878+
openai_tool_schema=tool.get_openai_tool_schema(),
3879+
)
3880+
)
38623881
else:
3863-
# Fallback to original function
3864-
cloned_tools.append(tool.func)
3882+
# Fallback to original function wrapped in FunctionTool
3883+
cloned_tools.append(
3884+
FunctionTool(
3885+
func=tool.func,
3886+
openai_tool_schema=tool.get_openai_tool_schema(),
3887+
)
3888+
)
38653889
else:
3866-
# Not a toolkit method, just use the original function
3867-
cloned_tools.append(tool.func)
3890+
# Not a toolkit method, preserve FunctionTool schema directly
3891+
cloned_tools.append(
3892+
FunctionTool(
3893+
func=tool.func,
3894+
openai_tool_schema=tool.get_openai_tool_schema(),
3895+
)
3896+
)
38683897

38693898
return cloned_tools, toolkits_to_register
38703899

camel/societies/workforce/workforce.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from enum import Enum
2424
from typing import (
2525
Any,
26+
Callable,
2627
Coroutine,
2728
Deque,
2829
Dict,
@@ -32,6 +33,7 @@
3233
Set,
3334
Tuple,
3435
Union,
36+
cast,
3537
)
3638

3739
from colorama import Fore
@@ -71,6 +73,7 @@
7173
)
7274
from camel.toolkits import (
7375
CodeExecutionToolkit,
76+
FunctionTool,
7477
SearchToolkit,
7578
TaskPlanningToolkit,
7679
ThinkingToolkit,
@@ -345,10 +348,7 @@ def __init__(
345348
None,
346349
),
347350
output_language=coordinator_agent.output_language,
348-
tools=[
349-
tool.func
350-
for tool in coordinator_agent._internal_tools.values()
351-
],
351+
tools=list(coordinator_agent._internal_tools.values()),
352352
external_tools=[
353353
schema
354354
for schema in coordinator_agent._external_tool_schemas.values() # noqa: E501
@@ -398,9 +398,11 @@ def __init__(
398398

399399
# Since ChatAgent constructor uses a dictionary with
400400
# function names as keys, we don't need to manually deduplicate.
401-
combined_tools = [
402-
tool.func for tool in task_agent._internal_tools.values()
403-
] + [tool.func for tool in task_planning_tools]
401+
combined_tools: List[Union[FunctionTool, Callable]] = cast(
402+
List[Union[FunctionTool, Callable]],
403+
list(task_agent._internal_tools.values())
404+
+ task_planning_tools,
405+
)
404406

405407
# Create a new agent with the provided agent's configuration
406408
# but with the combined system message and tools

0 commit comments

Comments
 (0)