Repository: pydantic/pydantic-ai
File: pydantic_ai_slim/pydantic_ai/agent/__init__.py (Python)

Code before:
            return '\n\n'.join(parts).strip()

        if isinstance(model_used, InstrumentedModel):
            instrumentation_settings = model_used.instrumentation_settings
            tracer = model_used.instrumentation_settings.tracer
        else:
            instrumentation_settings = None
            tracer = NoOpTracer()

        graph_deps = _agent_graph.GraphAgentDeps[AgentDepsT, RunOutputDataT](
            user_deps=deps,
            prompt=user_prompt,
            new_message_index=len(message_history) if message_history else 0,
            model=model_used,
            model_settings=model_settings,
            usage_limits=usage_limits,
            max_result_retries=self._max_result_retries,
            end_strategy=self.end_strategy,
            output_schema=output_schema,
            output_validators=output_validators,
            history_processors=self.history_processors,
            builtin_tools=list(
                {
                    **({type(tool): tool for tool in self._builtin_tools or []}),
                    **({type(tool): tool for tool in builtin_tools or []}),
                }.values()
            ),
            tool_manager=tool_manager,
            tracer=tracer,
            get_instructions=get_instructions,
            instrumentation_settings=instrumentation_settings,
        )

        start_node = _agent_graph.UserPromptNode[AgentDepsT](
            user_prompt=user_prompt,
            deferred_tool_results=deferred_tool_results,
            instructions=instructions_literal,
            instructions_functions=instructions_functions,
            system_prompts=self._system_prompts,
            system_prompt_functions=self._system_prompt_functions,
            system_prompt_dynamic_functions=self._system_prompt_dynamic_functions,
        )

        agent_name = self.name or 'agent'
        instrumentation_names = InstrumentationNames.for_version(
            instrumentation_settings.version if instrumentation_settings else DEFAULT_INSTRUMENTATION_VERSION
        )

        run_span = tracer.start_span(
            instrumentation_names.get_agent_run_span_name(agent_name),
            attributes={

Review comment (refactor):
@safina57 I suggest moving this to a variable further up, with a comment explaining what it does. Like:

```py
if builtin_tools:
    # Deduplicate builtin tools passed to the agent and the run based on type
    builtin_tools = list(
        {
            **({type(tool): tool for tool in self._builtin_tools or []}),
            **({type(tool): tool for tool in builtin_tools}),
        }.values()
    )
else:
    builtin_tools = self._builtin_tools
```

I like it a bit better than the 10-line method because this is still sufficiently clear to someone familiar with Python, and much more concise. The separate method makes it seem like something complicated is going on, while it's really just deduplication.

We could also do it like this if you think it's more clear:

```py
if builtin_tools:
    if self.builtin_tools:
        builtin_tool_types = [type(tool) for tool in builtin_tools]
        builtin_tools.extend([tool for tool in self._builtin_tools if type(tool) not in builtin_tool_types])
else:
    builtin_tools = self._builtin_tools
```

Code after:
            if not parts:
                return None
            return '\n\n'.join(parts).strip()

        if isinstance(model_used, InstrumentedModel):
            instrumentation_settings = model_used.instrumentation_settings
            tracer = model_used.instrumentation_settings.tracer
        else:
            instrumentation_settings = None
            tracer = NoOpTracer()
        if builtin_tools:
            # Deduplicate builtin tools passed to the agent and the run based on type
            builtin_tools = list(
                {
                    **({type(tool): tool for tool in self._builtin_tools or []}),
                    **({type(tool): tool for tool in builtin_tools}),
                }.values()
            )
        else:
            builtin_tools = list(self._builtin_tools)
        graph_deps = _agent_graph.GraphAgentDeps[AgentDepsT, RunOutputDataT](
            user_deps=deps,
            prompt=user_prompt,
            new_message_index=len(message_history) if message_history else 0,
            model=model_used,
            model_settings=model_settings,
            usage_limits=usage_limits,
            max_result_retries=self._max_result_retries,
            end_strategy=self.end_strategy,
            output_schema=output_schema,
            output_validators=output_validators,
            history_processors=self.history_processors,
            builtin_tools=builtin_tools,
            tool_manager=tool_manager,
            tracer=tracer,
            get_instructions=get_instructions,
            instrumentation_settings=instrumentation_settings,
        )

        start_node = _agent_graph.UserPromptNode[AgentDepsT](
            user_prompt=user_prompt,
            deferred_tool_results=deferred_tool_results,
            instructions=instructions_literal,
            instructions_functions=instructions_functions,
            system_prompts=self._system_prompts,
            system_prompt_functions=self._system_prompt_functions,
            system_prompt_dynamic_functions=self._system_prompt_dynamic_functions,
        )

        agent_name = self.name or 'agent'
        instrumentation_names = InstrumentationNames.for_version(