Skip to content

Commit ca0804e

Browse files
authored
Update agent.py
1 parent bda36ee commit ca0804e

File tree

1 file changed

+58
-39
lines changed

1 file changed

+58
-39
lines changed

src/agents/realtime/agent.py

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
"""
2+
Realtime agent module providing RealtimeAgent class with Pydantic validation.
3+
4+
This module implements realtime-specific agent functionality with strong type validation
5+
and configuration management for voice-enabled agents.
6+
"""
7+
18
from __future__ import annotations
29

3-
import dataclasses
410
import inspect
511
from collections.abc import Awaitable
6-
from dataclasses import dataclass, field
712
from typing import Any, Callable, Generic, cast
813

14+
from pydantic import ConfigDict, Field
15+
916
from ..agent import AgentBase
1017
from ..handoffs import Handoff
1118
from ..lifecycle import AgentHooksBase, RunHooksBase
@@ -20,62 +27,70 @@
2027
"""Run hooks for `RealtimeAgent`s."""
2128

2229

23-
@dataclass
2430
class RealtimeAgent(AgentBase, Generic[TContext]):
25-
"""A specialized agent instance that is meant to be used within a `RealtimeSession` to build
31+
"""
32+
A specialized agent instance that is meant to be used within a `RealtimeSession` to build
2633
voice agents. Due to the nature of this agent, some configuration options are not supported
27-
that are supported by regular `Agent` instances. For example:
28-
- `model` choice is not supported, as all RealtimeAgents will be handled by the same model
29-
within a `RealtimeSession`.
30-
- `modelSettings` is not supported, as all RealtimeAgents will be handled by the same model
31-
within a `RealtimeSession`.
32-
- `outputType` is not supported, as RealtimeAgents do not support structured outputs.
33-
- `toolUseBehavior` is not supported, as all RealtimeAgents will be handled by the same model
34-
within a `RealtimeSession`.
35-
- `voice` can be configured on an `Agent` level; however, it cannot be changed after the first
36-
agent within a `RealtimeSession` has spoken.
37-
38-
See `AgentBase` for base parameters that are shared with `Agent`s.
34+
that are supported by regular `Agent` instances.
35+
36+
Attributes:
37+
instructions: Agent instructions/system prompt
38+
handoffs: List of sub-agents for delegation
39+
hooks: Lifecycle event callbacks
3940
"""
4041

42+
model_config = ConfigDict(
43+
arbitrary_types_allowed=True,
44+
validate_assignment=True,
45+
extra="forbid",
46+
frozen=True,
47+
defer_build=True,
48+
)
49+
4150
instructions: (
4251
str
4352
| Callable[
4453
[RunContextWrapper[TContext], RealtimeAgent[TContext]],
4554
MaybeAwaitable[str],
4655
]
4756
| None
48-
) = None
49-
"""The instructions for the agent. Will be used as the "system prompt" when this agent is
50-
invoked. Describes what the agent should do, and how it responds.
51-
52-
Can either be a string, or a function that dynamically generates instructions for the agent. If
53-
you provide a function, it will be called with the context and the agent instance. It must
54-
return a string.
55-
"""
57+
) = Field(
58+
default=None,
59+
description="The instructions for the agent. Will be used as the 'system prompt' "
60+
"when this agent is invoked.",
61+
)
5662

57-
handoffs: list[RealtimeAgent[Any] | Handoff[TContext, RealtimeAgent[Any]]] = field(
58-
default_factory=list
63+
handoffs: list[RealtimeAgent[Any] | Handoff[TContext, RealtimeAgent[Any]]] = Field(
64+
default_factory=list, description="Handoffs are sub-agents that the agent can delegate to."
5965
)
60-
"""Handoffs are sub-agents that the agent can delegate to. You can provide a list of handoffs,
61-
and the agent can choose to delegate to them if relevant. Allows for separation of concerns and
62-
modularity.
63-
"""
6466

65-
hooks: RealtimeAgentHooks | None = None
66-
"""A class that receives callbacks on various lifecycle events for this agent.
67-
"""
67+
hooks: RealtimeAgentHooks | None = Field(
68+
default=None,
69+
description="A class that receives callbacks on various lifecycle events for this agent.",
70+
)
6871

6972
def clone(self, **kwargs: Any) -> RealtimeAgent[TContext]:
70-
"""Make a copy of the agent, with the given arguments changed. For example, you could do:
71-
```
72-
new_agent = agent.clone(instructions="New instructions")
73-
```
7473
"""
75-
return dataclasses.replace(self, **kwargs)
74+
Make a copy of the agent, with the given arguments changed.
75+
76+
Args:
77+
**kwargs: Fields to override in the new instance
78+
79+
Returns:
80+
RealtimeAgent[TContext]: New agent instance with specified changes
81+
"""
82+
return self.model_copy(update=kwargs)
7683

7784
async def get_system_prompt(self, run_context: RunContextWrapper[TContext]) -> str | None:
78-
"""Get the system prompt for the agent."""
85+
"""
86+
Get the system prompt for the agent.
87+
88+
Args:
89+
run_context: Current run context
90+
91+
Returns:
92+
str | None: System prompt if available
93+
"""
7994
if isinstance(self.instructions, str):
8095
return self.instructions
8196
elif callable(self.instructions):
@@ -87,3 +102,7 @@ async def get_system_prompt(self, run_context: RunContextWrapper[TContext]) -> s
87102
logger.error(f"Instructions must be a string or a function, got {self.instructions}")
88103

89104
return None
105+
106+
107+
# Rebuild models after all definitions
108+
RealtimeAgent.model_rebuild()

0 commit comments

Comments
 (0)