agno 2.3.13__py3-none-any.whl → 2.3.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. agno/agent/agent.py +1131 -1402
  2. agno/eval/__init__.py +21 -8
  3. agno/knowledge/embedder/azure_openai.py +0 -1
  4. agno/knowledge/embedder/google.py +1 -1
  5. agno/models/anthropic/claude.py +4 -1
  6. agno/models/base.py +8 -4
  7. agno/models/openai/responses.py +2 -2
  8. agno/os/app.py +39 -0
  9. agno/os/interfaces/a2a/router.py +619 -9
  10. agno/os/interfaces/a2a/utils.py +31 -32
  11. agno/os/middleware/jwt.py +5 -5
  12. agno/os/routers/agents/schema.py +14 -1
  13. agno/os/routers/teams/schema.py +14 -1
  14. agno/os/utils.py +61 -53
  15. agno/reasoning/anthropic.py +85 -1
  16. agno/reasoning/azure_ai_foundry.py +93 -1
  17. agno/reasoning/deepseek.py +91 -1
  18. agno/reasoning/gemini.py +81 -1
  19. agno/reasoning/groq.py +103 -1
  20. agno/reasoning/manager.py +1244 -0
  21. agno/reasoning/ollama.py +93 -1
  22. agno/reasoning/openai.py +113 -1
  23. agno/reasoning/vertexai.py +85 -1
  24. agno/run/agent.py +11 -0
  25. agno/run/base.py +1 -1
  26. agno/run/team.py +11 -0
  27. agno/session/team.py +0 -3
  28. agno/team/team.py +1201 -1445
  29. agno/utils/events.py +69 -2
  30. agno/utils/hooks.py +4 -10
  31. agno/utils/print_response/agent.py +26 -0
  32. agno/utils/print_response/team.py +11 -0
  33. agno/utils/prompts.py +8 -6
  34. agno/utils/string.py +46 -0
  35. agno/utils/team.py +1 -1
  36. agno/vectordb/milvus/milvus.py +32 -3
  37. {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/METADATA +3 -2
  38. {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/RECORD +41 -40
  39. {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/WHEEL +0 -0
  40. {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/licenses/LICENSE +0 -0
  41. {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -65,3 +65,95 @@ async def aget_ai_foundry_reasoning(reasoning_agent: "Agent", messages: List[Mes
65
65
  return Message(
66
66
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
67
67
  )
68
+
69
+
70
+ def get_ai_foundry_reasoning_stream(
71
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
72
+ messages: List[Message],
73
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
74
+ """
75
+ Stream reasoning content from Azure AI Foundry model.
76
+
77
+ For DeepSeek-R1 models, we use the main content output as reasoning content.
78
+
79
+ Yields:
80
+ Tuple of (reasoning_content_delta, final_message)
81
+ - During streaming: (reasoning_content_delta, None)
82
+ - At the end: (None, final_message)
83
+ """
84
+ from agno.run.agent import RunEvent
85
+
86
+ reasoning_content: str = ""
87
+
88
+ try:
89
+ for event in reasoning_agent.run(input=messages, stream=True, stream_intermediate_steps=True):
90
+ if hasattr(event, "event"):
91
+ if event.event == RunEvent.run_content:
92
+ # Check for reasoning_content attribute first (native reasoning)
93
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
94
+ reasoning_content += event.reasoning_content
95
+ yield (event.reasoning_content, None)
96
+ # Use the main content as reasoning content
97
+ elif hasattr(event, "content") and event.content:
98
+ reasoning_content += event.content
99
+ yield (event.content, None)
100
+ elif event.event == RunEvent.run_completed:
101
+ pass
102
+ except Exception as e:
103
+ logger.warning(f"Reasoning error: {e}")
104
+ return
105
+
106
+ # Yield final message
107
+ if reasoning_content:
108
+ final_message = Message(
109
+ role="assistant",
110
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
111
+ reasoning_content=reasoning_content,
112
+ )
113
+ yield (None, final_message)
114
+
115
+
116
+ async def aget_ai_foundry_reasoning_stream(
117
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
118
+ messages: List[Message],
119
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
120
+ """
121
+ Stream reasoning content from Azure AI Foundry model asynchronously.
122
+
123
+ For DeepSeek-R1 models, we use the main content output as reasoning content.
124
+
125
+ Yields:
126
+ Tuple of (reasoning_content_delta, final_message)
127
+ - During streaming: (reasoning_content_delta, None)
128
+ - At the end: (None, final_message)
129
+ """
130
+ from agno.run.agent import RunEvent
131
+
132
+ reasoning_content: str = ""
133
+
134
+ try:
135
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_intermediate_steps=True):
136
+ if hasattr(event, "event"):
137
+ if event.event == RunEvent.run_content:
138
+ # Check for reasoning_content attribute first (native reasoning)
139
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
140
+ reasoning_content += event.reasoning_content
141
+ yield (event.reasoning_content, None)
142
+ # Use the main content as reasoning content
143
+ elif hasattr(event, "content") and event.content:
144
+ reasoning_content += event.content
145
+ yield (event.content, None)
146
+ elif event.event == RunEvent.run_completed:
147
+ pass
148
+ except Exception as e:
149
+ logger.warning(f"Reasoning error: {e}")
150
+ return
151
+
152
+ # Yield final message
153
+ if reasoning_content:
154
+ final_message = Message(
155
+ role="assistant",
156
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
157
+ reasoning_content=reasoning_content,
158
+ )
159
+ yield (None, final_message)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -37,6 +37,51 @@ def get_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Message]) ->
37
37
  )
38
38
 
39
39
 
40
+ def get_deepseek_reasoning_stream(
41
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
42
+ messages: List[Message],
43
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
44
+ """
45
+ Stream reasoning content from DeepSeek model.
46
+
47
+ Yields:
48
+ Tuple of (reasoning_content_delta, final_message)
49
+ - During streaming: (reasoning_content_delta, None)
50
+ - At the end: (None, final_message)
51
+ """
52
+ from agno.run.agent import RunEvent
53
+
54
+ # Update system message role to "system"
55
+ for message in messages:
56
+ if message.role == "developer":
57
+ message.role = "system"
58
+
59
+ reasoning_content: str = ""
60
+
61
+ try:
62
+ for event in reasoning_agent.run(input=messages, stream=True, stream_intermediate_steps=True):
63
+ if hasattr(event, "event"):
64
+ if event.event == RunEvent.run_content:
65
+ # Stream reasoning content as it arrives
66
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
67
+ reasoning_content += event.reasoning_content
68
+ yield (event.reasoning_content, None)
69
+ elif event.event == RunEvent.run_completed:
70
+ pass
71
+ except Exception as e:
72
+ logger.warning(f"Reasoning error: {e}")
73
+ return
74
+
75
+ # Yield final message
76
+ if reasoning_content:
77
+ final_message = Message(
78
+ role="assistant",
79
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
80
+ reasoning_content=reasoning_content,
81
+ )
82
+ yield (None, final_message)
83
+
84
+
40
85
  async def aget_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> Optional[Message]: # type: ignore # noqa: F821
41
86
  from agno.run.agent import RunOutput
42
87
 
@@ -61,3 +106,48 @@ async def aget_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Messa
61
106
  return Message(
62
107
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
63
108
  )
109
+
110
+
111
+ async def aget_deepseek_reasoning_stream(
112
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
113
+ messages: List[Message],
114
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
115
+ """
116
+ Stream reasoning content from DeepSeek model asynchronously.
117
+
118
+ Yields:
119
+ Tuple of (reasoning_content_delta, final_message)
120
+ - During streaming: (reasoning_content_delta, None)
121
+ - At the end: (None, final_message)
122
+ """
123
+ from agno.run.agent import RunEvent
124
+
125
+ # Update system message role to "system"
126
+ for message in messages:
127
+ if message.role == "developer":
128
+ message.role = "system"
129
+
130
+ reasoning_content: str = ""
131
+
132
+ try:
133
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_intermediate_steps=True):
134
+ if hasattr(event, "event"):
135
+ if event.event == RunEvent.run_content:
136
+ # Stream reasoning content as it arrives
137
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
138
+ reasoning_content += event.reasoning_content
139
+ yield (event.reasoning_content, None)
140
+ elif event.event == RunEvent.run_completed:
141
+ pass
142
+ except Exception as e:
143
+ logger.warning(f"Reasoning error: {e}")
144
+ return
145
+
146
+ # Yield final message
147
+ if reasoning_content:
148
+ final_message = Message(
149
+ role="assistant",
150
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
151
+ reasoning_content=reasoning_content,
152
+ )
153
+ yield (None, final_message)
agno/reasoning/gemini.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -71,3 +71,83 @@ async def aget_gemini_reasoning(reasoning_agent: "Agent", messages: List[Message
71
71
  return Message(
72
72
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
73
73
  )
74
+
75
+
76
+ def get_gemini_reasoning_stream(
77
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
78
+ messages: List[Message],
79
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
80
+ """
81
+ Stream reasoning content from Gemini model.
82
+
83
+ Yields:
84
+ Tuple of (reasoning_content_delta, final_message)
85
+ - During streaming: (reasoning_content_delta, None)
86
+ - At the end: (None, final_message)
87
+ """
88
+ from agno.run.agent import RunEvent
89
+
90
+ reasoning_content: str = ""
91
+
92
+ try:
93
+ for event in reasoning_agent.run(input=messages, stream=True, stream_intermediate_steps=True):
94
+ if hasattr(event, "event"):
95
+ if event.event == RunEvent.run_content:
96
+ # Stream reasoning content as it arrives
97
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
98
+ reasoning_content += event.reasoning_content
99
+ yield (event.reasoning_content, None)
100
+ elif event.event == RunEvent.run_completed:
101
+ pass
102
+ except Exception as e:
103
+ logger.warning(f"Reasoning error: {e}")
104
+ return
105
+
106
+ # Yield final message
107
+ if reasoning_content:
108
+ final_message = Message(
109
+ role="assistant",
110
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
111
+ reasoning_content=reasoning_content,
112
+ )
113
+ yield (None, final_message)
114
+
115
+
116
+ async def aget_gemini_reasoning_stream(
117
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
118
+ messages: List[Message],
119
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
120
+ """
121
+ Stream reasoning content from Gemini model asynchronously.
122
+
123
+ Yields:
124
+ Tuple of (reasoning_content_delta, final_message)
125
+ - During streaming: (reasoning_content_delta, None)
126
+ - At the end: (None, final_message)
127
+ """
128
+ from agno.run.agent import RunEvent
129
+
130
+ reasoning_content: str = ""
131
+
132
+ try:
133
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_intermediate_steps=True):
134
+ if hasattr(event, "event"):
135
+ if event.event == RunEvent.run_content:
136
+ # Stream reasoning content as it arrives
137
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
138
+ reasoning_content += event.reasoning_content
139
+ yield (event.reasoning_content, None)
140
+ elif event.event == RunEvent.run_completed:
141
+ pass
142
+ except Exception as e:
143
+ logger.warning(f"Reasoning error: {e}")
144
+ return
145
+
146
+ # Yield final message
147
+ if reasoning_content:
148
+ final_message = Message(
149
+ role="assistant",
150
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
151
+ reasoning_content=reasoning_content,
152
+ )
153
+ yield (None, final_message)
agno/reasoning/groq.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -69,3 +69,105 @@ async def aget_groq_reasoning(reasoning_agent: "Agent", messages: List[Message])
69
69
  return Message(
70
70
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
71
71
  )
72
+
73
+
74
+ def get_groq_reasoning_stream(
75
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
76
+ messages: List[Message],
77
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
78
+ """
79
+ Stream reasoning content from Groq model.
80
+
81
+ For DeepSeek models on Groq, we use the main content output as reasoning content.
82
+
83
+ Yields:
84
+ Tuple of (reasoning_content_delta, final_message)
85
+ - During streaming: (reasoning_content_delta, None)
86
+ - At the end: (None, final_message)
87
+ """
88
+ from agno.run.agent import RunEvent
89
+
90
+ # Update system message role to "system"
91
+ for message in messages:
92
+ if message.role == "developer":
93
+ message.role = "system"
94
+
95
+ reasoning_content: str = ""
96
+
97
+ try:
98
+ for event in reasoning_agent.run(input=messages, stream=True, stream_intermediate_steps=True):
99
+ if hasattr(event, "event"):
100
+ if event.event == RunEvent.run_content:
101
+ # Check for reasoning_content attribute first (native reasoning)
102
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
103
+ reasoning_content += event.reasoning_content
104
+ yield (event.reasoning_content, None)
105
+ # Use the main content as reasoning content
106
+ elif hasattr(event, "content") and event.content:
107
+ reasoning_content += event.content
108
+ yield (event.content, None)
109
+ elif event.event == RunEvent.run_completed:
110
+ pass
111
+ except Exception as e:
112
+ logger.warning(f"Reasoning error: {e}")
113
+ return
114
+
115
+ # Yield final message
116
+ if reasoning_content:
117
+ final_message = Message(
118
+ role="assistant",
119
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
120
+ reasoning_content=reasoning_content,
121
+ )
122
+ yield (None, final_message)
123
+
124
+
125
+ async def aget_groq_reasoning_stream(
126
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
127
+ messages: List[Message],
128
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
129
+ """
130
+ Stream reasoning content from Groq model asynchronously.
131
+
132
+ For DeepSeek models on Groq, we use the main content output as reasoning content.
133
+
134
+ Yields:
135
+ Tuple of (reasoning_content_delta, final_message)
136
+ - During streaming: (reasoning_content_delta, None)
137
+ - At the end: (None, final_message)
138
+ """
139
+ from agno.run.agent import RunEvent
140
+
141
+ # Update system message role to "system"
142
+ for message in messages:
143
+ if message.role == "developer":
144
+ message.role = "system"
145
+
146
+ reasoning_content: str = ""
147
+
148
+ try:
149
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_intermediate_steps=True):
150
+ if hasattr(event, "event"):
151
+ if event.event == RunEvent.run_content:
152
+ # Check for reasoning_content attribute first (native reasoning)
153
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
154
+ reasoning_content += event.reasoning_content
155
+ yield (event.reasoning_content, None)
156
+ # Use the main content as reasoning content
157
+ elif hasattr(event, "content") and event.content:
158
+ reasoning_content += event.content
159
+ yield (event.content, None)
160
+ elif event.event == RunEvent.run_completed:
161
+ pass
162
+ except Exception as e:
163
+ logger.warning(f"Reasoning error: {e}")
164
+ return
165
+
166
+ # Yield final message
167
+ if reasoning_content:
168
+ final_message = Message(
169
+ role="assistant",
170
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
171
+ reasoning_content=reasoning_content,
172
+ )
173
+ yield (None, final_message)