Skip to content

Commit dc3c9e9

Browse files
Let agent name be overridden contextually (#3094)
1 parent d263b7a commit dc3c9e9

File tree

6 files changed

+36
-6
lines changed

6 files changed

+36
-6
lines changed

pydantic_ai_slim/pydantic_ai/agent/__init__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ def __init__(
344344

345345
self._event_stream_handler = event_stream_handler
346346

347+
self._override_name: ContextVar[_utils.Option[str]] = ContextVar('_override_name', default=None)
347348
self._override_deps: ContextVar[_utils.Option[AgentDepsT]] = ContextVar('_override_deps', default=None)
348349
self._override_model: ContextVar[_utils.Option[models.Model]] = ContextVar('_override_model', default=None)
349350
self._override_toolsets: ContextVar[_utils.Option[Sequence[AbstractToolset[AgentDepsT]]]] = ContextVar(
@@ -384,7 +385,8 @@ def name(self) -> str | None:
384385
385386
If `None`, we try to infer the agent name from the call frame when the agent is first run.
386387
"""
387-
return self._name
388+
name_ = self._override_name.get()
389+
return name_.value if name_ else self._name
388390

389391
@name.setter
390392
def name(self, value: str | None) -> None:
@@ -712,24 +714,31 @@ def _run_span_end_attributes(
712714
def override(
713715
self,
714716
*,
717+
name: str | _utils.Unset = _utils.UNSET,
715718
deps: AgentDepsT | _utils.Unset = _utils.UNSET,
716719
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
717720
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
718721
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
719722
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
720723
) -> Iterator[None]:
721-
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
724+
"""Context manager to temporarily override agent name, dependencies, model, toolsets, tools, or instructions.
722725
723726
This is particularly useful when testing.
724727
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
725728
726729
Args:
730+
name: The name to use instead of the name passed to the agent constructor and agent run.
727731
deps: The dependencies to use instead of the dependencies passed to the agent run.
728732
model: The model to use instead of the model passed to the agent run.
729733
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
730734
tools: The tools to use instead of the tools registered with the agent.
731735
instructions: The instructions to use instead of the instructions registered with the agent.
732736
"""
737+
if _utils.is_set(name):
738+
name_token = self._override_name.set(_utils.Some(name))
739+
else:
740+
name_token = None
741+
733742
if _utils.is_set(deps):
734743
deps_token = self._override_deps.set(_utils.Some(deps))
735744
else:
@@ -759,6 +768,8 @@ def override(
759768
try:
760769
yield
761770
finally:
771+
if name_token is not None:
772+
self._override_name.reset(name_token)
762773
if deps_token is not None:
763774
self._override_deps.reset(deps_token)
764775
if model_token is not None:

pydantic_ai_slim/pydantic_ai/agent/abstract.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,18 +854,20 @@ async def main():
854854
def override(
855855
self,
856856
*,
857+
name: str | _utils.Unset = _utils.UNSET,
857858
deps: AgentDepsT | _utils.Unset = _utils.UNSET,
858859
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
859860
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
860861
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
861862
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
862863
) -> Iterator[None]:
863-
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
864+
"""Context manager to temporarily override agent name, dependencies, model, toolsets, tools, or instructions.
864865
865866
This is particularly useful when testing.
866867
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
867868
868869
Args:
870+
name: The name to use instead of the name passed to the agent constructor and agent run.
869871
deps: The dependencies to use instead of the dependencies passed to the agent run.
870872
model: The model to use instead of the model passed to the agent run.
871873
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.

pydantic_ai_slim/pydantic_ai/agent/wrapper.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,25 +210,28 @@ async def main():
210210
def override(
211211
self,
212212
*,
213+
name: str | _utils.Unset = _utils.UNSET,
213214
deps: AgentDepsT | _utils.Unset = _utils.UNSET,
214215
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
215216
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
216217
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
217218
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
218219
) -> Iterator[None]:
219-
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
220+
"""Context manager to temporarily override agent name, dependencies, model, toolsets, tools, or instructions.
220221
221222
This is particularly useful when testing.
222223
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
223224
224225
Args:
226+
name: The name to use instead of the name passed to the agent constructor and agent run.
225227
deps: The dependencies to use instead of the dependencies passed to the agent run.
226228
model: The model to use instead of the model passed to the agent run.
227229
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
228230
tools: The tools to use instead of the tools registered with the agent.
229231
instructions: The instructions to use instead of the instructions registered with the agent.
230232
"""
231233
with self.wrapped.override(
234+
name=name,
232235
deps=deps,
233236
model=model,
234237
toolsets=toolsets,

pydantic_ai_slim/pydantic_ai/durable_exec/dbos/_agent.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,18 +804,20 @@ async def main():
804804
def override(
805805
self,
806806
*,
807+
name: str | _utils.Unset = _utils.UNSET,
807808
deps: AgentDepsT | _utils.Unset = _utils.UNSET,
808809
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
809810
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
810811
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
811812
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
812813
) -> Iterator[None]:
813-
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
814+
"""Context manager to temporarily override agent name, dependencies, model, toolsets, tools, or instructions.
814815
815816
This is particularly useful when testing.
816817
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
817818
818819
Args:
820+
name: The name to use instead of the name passed to the agent constructor and agent run.
819821
deps: The dependencies to use instead of the dependencies passed to the agent run.
820822
model: The model to use instead of the model passed to the agent run.
821823
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
@@ -828,6 +830,7 @@ def override(
828830
)
829831

830832
with super().override(
833+
name=name,
831834
deps=deps,
832835
model=model,
833836
toolsets=toolsets,

pydantic_ai_slim/pydantic_ai/durable_exec/temporal/_agent.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,18 +862,20 @@ async def main():
862862
def override(
863863
self,
864864
*,
865+
name: str | _utils.Unset = _utils.UNSET,
865866
deps: AgentDepsT | _utils.Unset = _utils.UNSET,
866867
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
867868
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
868869
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
869870
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
870871
) -> Iterator[None]:
871-
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
872+
"""Context manager to temporarily override agent name, dependencies, model, toolsets, tools, or instructions.
872873
873874
This is particularly useful when testing.
874875
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
875876
876877
Args:
878+
name: The name to use instead of the name passed to the agent constructor and agent run.
877879
deps: The dependencies to use instead of the dependencies passed to the agent run.
878880
model: The model to use instead of the model passed to the agent run.
879881
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
@@ -895,6 +897,7 @@ def override(
895897
)
896898

897899
with super().override(
900+
name=name,
898901
deps=deps,
899902
model=model,
900903
toolsets=toolsets,

tests/test_agent.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2537,6 +2537,14 @@ async def test_agent_name_changes():
25372537
assert new_agent.name == 'my_agent'
25382538

25392539

2540+
def test_agent_name_override():
2541+
agent = Agent('test', name='custom_name')
2542+
2543+
with agent.override(name='overridden_name'):
2544+
agent.run_sync('Hello')
2545+
assert agent.name == 'overridden_name'
2546+
2547+
25402548
def test_name_from_global(create_module: Callable[[str], Any]):
25412549
module_code = """
25422550
from pydantic_ai import Agent

0 commit comments

Comments
 (0)