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

Code before:
            instructions_iterable = (instructions_value,)
        elif callable(instructions_value):
            instructions_iterable = (instructions_value,)
        else:
            instructions_iterable = instructions_value

        for instruction in instructions_iterable:
            if isinstance(instruction, str):
                literal_parts.append(instruction)
            elif callable(instruction):
                functions.append(_system_prompt.SystemPromptRunner[AgentDepsT](instruction))
            else:  # pragma: no cover
                raise ValueError(f'Invalid instruction: {instruction}')

        literal = '\n'.join(literal_parts).strip() or None
        return literal, functions

    def _append_instruction(self, instruction: _system_prompt.SystemPromptFunc[AgentDepsT]) -> None:
        if self._instructions is None:
            instructions_list: list[str | _system_prompt.SystemPromptFunc[AgentDepsT]] = [instruction]
        elif isinstance(self._instructions, str):
            instructions_list = [self._instructions, instruction]
        elif callable(self._instructions):
            instructions_list = [self._instructions, instruction]
        else:
            instructions_list = [*self._instructions, instruction]  # pragma: no cover

        self._instructions = instructions_list

    @staticmethod
    def instrument_all(instrument: InstrumentationSettings | bool = True) -> None:
        """Set the instrumentation options for all agents where `instrument` is not set."""
        Agent._instrument_default = instrument

    @property
    def model(self) -> models.Model | models.KnownModelName | str | None:
        """The default model configured for this agent."""
        return self._model

    @model.setter
    def model(self, value: models.Model | models.KnownModelName | str | None) -> None:
        """Set the default model configured for this agent.

        We allow `str` here since the actual list of allowed models changes frequently.
        """
        self._model = value

    @property
    def name(self) -> str | None:
        """The name of the agent, used for logging.


Review comment (refactor):
Sorry for continuing to come up with more ways to refactor this, but what do you think about making `self._instructions` and `self._override_instructions` always hold a `list[str | _system_prompt.SystemPromptFunc[AgentDepsT]]`, and change `__init__` and `override` to store `list(instructions)` so that any single items automatically get wrapped in a list, and this method and the one above can be much simpler?

Code after:
        """Set the default model configured for this agent.

        We allow `str` here since the actual list of allowed models changes frequently.
        """
        self._model = value

    @property
    def name(self) -> str | None:
        """The name of the agent, used for logging.

        If `None`, we try to infer the agent name from the call frame when the agent is first run.
        """
        return self._name

    @name.setter
    def name(self, value: str | None) -> None:
        """Set the name of the agent, used for logging."""
        self._name = value

    @property
    def deps_type(self) -> type:
        """The type of dependencies used by the agent."""
        return self._deps_type

    @property
    def output_type(self) -> OutputSpec[OutputDataT]:
        """The type of data output by agent runs, used to validate the data returned by the model, defaults to `str`."""
        return self._output_type

    @property
    def event_stream_handler(self) -> EventStreamHandler[AgentDepsT] | None:
        """Optional handler for events from the model's streaming response and the agent's execution of tools."""
        return self._event_stream_handler

    def __repr__(self) -> str:
        return f'{type(self).__name__}(model={self.model!r}, name={self.name!r}, end_strategy={self.end_strategy!r}, model_settings={self.model_settings!r}, output_type={self.output_type!r}, instrument={self.instrument!r})'

    @overload
    def iter(
        self,
        user_prompt: str | Sequence[_messages.UserContent] | None = None,
        *,
        output_type: None = None,
        message_history: list[_messages.ModelMessage] | None = None,
        deferred_tool_results: DeferredToolResults | None = None,
        model: models.Model | models.KnownModelName | str | None = None,
        deps: AgentDepsT = None,
        model_settings: ModelSettings | None = None,
        usage_limits: _usage.UsageLimits | None = None,
        usage: _usage.RunUsage | None = None,
        infer_name: bool = True,