@@ -139,6 +139,62 @@ def validate(
139139 and returns a boolean.
140140 error_message: An optional custom error message for the `UnsupportedOperationError`.
141141 If None, the string representation of the expression will be used.
142+
143+ Examples:
144+ Demonstrating with an async method:
145+ >>> import asyncio
146+ >>> from a2a.utils.errors import ServerError
147+ >>>
148+ >>> class MyAgent:
149+ ... def __init__(self, streaming_enabled: bool):
150+ ... self.streaming_enabled = streaming_enabled
151+ ...
152+ ... @validate(
153+ ... lambda self: self.streaming_enabled,
154+ ... 'Streaming is not enabled for this agent',
155+ ... )
156+ ... async def stream_response(self, message: str):
157+ ... return f'Streaming: {message}'
158+ >>>
159+ >>> async def run_async_test():
160+ ... # Successful call
161+ ... agent_ok = MyAgent(streaming_enabled=True)
162+ ... result = await agent_ok.stream_response('hello')
163+ ... print(result)
164+ ...
165+ ... # Call that fails validation
166+ ... agent_fail = MyAgent(streaming_enabled=False)
167+ ... try:
168+ ... await agent_fail.stream_response('world')
169+ ... except ServerError as e:
170+ ... print(e.error.message)
171+ >>>
172+ >>> asyncio.run(run_async_test())
173+ Streaming: hello
174+ Streaming is not enabled for this agent
175+
176+ Demonstrating with a sync method:
177+ >>> class SecureAgent:
178+ ... def __init__(self):
179+ ... self.auth_enabled = False
180+ ...
181+ ... @validate(
182+ ... lambda self: self.auth_enabled,
183+ ... 'Authentication must be enabled for this operation',
184+ ... )
185+ ... def secure_operation(self, data: str):
186+ ... return f'Processing secure data: {data}'
187+ >>>
188+ >>> # Error case example
189+ >>> agent = SecureAgent()
190+ >>> try:
191+ ... agent.secure_operation('secret')
192+ ... except ServerError as e:
193+ ... print(e.error.message)
194+ Authentication must be enabled for this operation
195+
196+ Note:
197+ This decorator works with both sync and async methods automatically.
142198 """
143199
144200 def decorator (function : Callable ) -> Callable :
@@ -174,7 +230,7 @@ def sync_wrapper(self: Any, *args, **kwargs) -> Any:
174230def validate_async_generator (
175231 expression : Callable [[Any ], bool ], error_message : str | None = None
176232):
177- """Decorator that validates if a given expression evaluates to True.
233+ """Decorator that validates if a given expression evaluates to True for async generators .
178234
179235 Typically used on class methods to check capabilities or configuration
180236 before executing the method's logic. If the expression is False,
@@ -185,6 +241,60 @@ def validate_async_generator(
185241 and returns a boolean.
186242 error_message: An optional custom error message for the `UnsupportedOperationError`.
187243 If None, the string representation of the expression will be used.
244+
245+ Examples:
246+ Streaming capability validation with success case:
247+ >>> import asyncio
248+ >>> from a2a.utils.errors import ServerError
249+ >>>
250+ >>> class StreamingAgent:
251+ ... def __init__(self, streaming_enabled: bool):
252+ ... self.streaming_enabled = streaming_enabled
253+ ...
254+ ... @validate_async_generator(
255+ ... lambda self: self.streaming_enabled,
256+ ... 'Streaming is not supported by this agent',
257+ ... )
258+ ... async def stream_messages(self, count: int):
259+ ... for i in range(count):
260+ ... yield f'Message {i}'
261+ >>>
262+ >>> async def run_streaming_test():
263+ ... # Successful streaming
264+ ... agent = StreamingAgent(streaming_enabled=True)
265+ ... async for msg in agent.stream_messages(2):
266+ ... print(msg)
267+ >>>
268+ >>> asyncio.run(run_streaming_test())
269+ Message 0
270+ Message 1
271+
272+ Error case - validation fails:
273+ >>> class FeatureAgent:
274+ ... def __init__(self):
275+ ... self.features = {'real_time': False}
276+ ...
277+ ... @validate_async_generator(
278+ ... lambda self: self.features.get('real_time', False),
279+ ... 'Real-time feature must be enabled to stream updates',
280+ ... )
281+ ... async def real_time_updates(self):
282+ ... yield 'This should not be yielded'
283+ >>>
284+ >>> async def run_error_test():
285+ ... agent = FeatureAgent()
286+ ... try:
287+ ... async for _ in agent.real_time_updates():
288+ ... pass
289+ ... except ServerError as e:
290+ ... print(e.error.message)
291+ >>>
292+ >>> asyncio.run(run_error_test())
293+ Real-time feature must be enabled to stream updates
294+
295+ Note:
296+ This decorator is specifically for async generator methods (async def with yield).
297+ The validation happens before the generator starts yielding values.
188298 """
189299
190300 def decorator (function ):
0 commit comments