Skip to content

Commit 9a27360

Browse files
committed
Refactor duplicated code
1 parent 52d6a4c commit 9a27360

File tree

1 file changed

+28
-45
lines changed

1 file changed

+28
-45
lines changed

pydantic_ai_slim/pydantic_ai/_agent_graph.py

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -826,50 +826,27 @@ async def process_tool_calls( # noqa: C901
826826

827827
# First, we handle output tool calls
828828
for call in tool_calls_by_kind['output']:
829-
if final_result:
830-
if final_result.tool_call_id == call.tool_call_id:
831-
part = _messages.ToolReturnPart(
832-
tool_name=call.tool_name,
833-
content='Final result processed.',
834-
tool_call_id=call.tool_call_id,
835-
)
836-
output_parts.append(part)
837-
# With early strategy, execute only the first output tool
838-
elif ctx.deps.end_strategy == 'early':
839-
yield _messages.FunctionToolCallEvent(call)
840-
part = _messages.ToolReturnPart(
841-
tool_name=call.tool_name,
842-
content='Output tool not used - a final result was already processed.',
843-
tool_call_id=call.tool_call_id,
844-
)
845-
yield _messages.FunctionToolResultEvent(part)
846-
output_parts.append(part)
847-
# With exhaustive strategy, execute all output tools
848-
elif ctx.deps.end_strategy == 'exhaustive':
849-
try:
850-
await tool_manager.handle_call(call)
851-
except exceptions.UnexpectedModelBehavior as e:
852-
ctx.state.increment_retries(
853-
ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
854-
)
855-
raise e # pragma: lax no cover
856-
except ToolRetryError as e:
857-
ctx.state.increment_retries(
858-
ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
859-
)
860-
yield _messages.FunctionToolCallEvent(call)
861-
output_parts.append(e.tool_retry)
862-
yield _messages.FunctionToolResultEvent(e.tool_retry)
863-
else:
864-
part = _messages.ToolReturnPart(
865-
tool_name=call.tool_name,
866-
content='Final result processed.',
867-
tool_call_id=call.tool_call_id,
868-
)
869-
output_parts.append(part)
870-
else:
871-
assert_never(ctx.deps.end_strategy)
872-
else:
829+
# In case we got two tool calls with the same ID
830+
if final_result and final_result.tool_call_id == call.tool_call_id:
831+
part = _messages.ToolReturnPart(
832+
tool_name=call.tool_name,
833+
content='Final result processed.',
834+
tool_call_id=call.tool_call_id,
835+
)
836+
output_parts.append(part)
837+
# Early strategy is chosen and final result is already set
838+
elif ctx.deps.end_strategy == 'early' and final_result:
839+
yield _messages.FunctionToolCallEvent(call)
840+
part = _messages.ToolReturnPart(
841+
tool_name=call.tool_name,
842+
content='Output tool not used - a final result was already processed.',
843+
tool_call_id=call.tool_call_id,
844+
)
845+
yield _messages.FunctionToolResultEvent(part)
846+
output_parts.append(part)
847+
# Early strategy is chosen and final result is not yet set
848+
# Or exhaustive strategy is chosen
849+
elif (ctx.deps.end_strategy == 'early' and not final_result) or ctx.deps.end_strategy == 'exhaustive':
873850
try:
874851
result_data = await tool_manager.handle_call(call)
875852
except exceptions.UnexpectedModelBehavior as e:
@@ -891,7 +868,13 @@ async def process_tool_calls( # noqa: C901
891868
tool_call_id=call.tool_call_id,
892869
)
893870
output_parts.append(part)
894-
final_result = result.FinalResult(result_data, call.tool_name, call.tool_call_id)
871+
872+
# Even in exhaustive mode, use the first output tool's result as the final result
873+
if not final_result:
874+
final_result = result.FinalResult(result_data, call.tool_name, call.tool_call_id)
875+
# Unknown strategy or invalid state
876+
else:
877+
assert_never(ctx.deps.end_strategy)
895878

896879
# Then, we handle function tool calls
897880
calls_to_run: list[_messages.ToolCallPart] = []

0 commit comments

Comments
 (0)