agno 2.2.6__py3-none-any.whl → 2.2.8__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.
@@ -14,6 +14,7 @@ from agno.models.message import Message
14
14
  from agno.models.metrics import Metrics
15
15
  from agno.models.response import ModelResponse
16
16
  from agno.run.agent import RunOutput
17
+ from agno.run.team import TeamRunOutput
17
18
  from agno.utils.log import log_debug, log_error, log_warning
18
19
  from agno.utils.openai import _format_file_for_message, audio_to_message, images_to_message
19
20
  from agno.utils.reasoning import extract_thinking_content
@@ -168,7 +169,7 @@ class OpenAIChat(Model):
168
169
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
169
170
  tools: Optional[List[Dict[str, Any]]] = None,
170
171
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
171
- run_response: Optional[RunOutput] = None,
172
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
172
173
  ) -> Dict[str, Any]:
173
174
  """
174
175
  Returns keyword arguments for API requests.
@@ -355,7 +356,7 @@ class OpenAIChat(Model):
355
356
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
356
357
  tools: Optional[List[Dict[str, Any]]] = None,
357
358
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
358
- run_response: Optional[RunOutput] = None,
359
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
359
360
  ) -> ModelResponse:
360
361
  """
361
362
  Send a chat completion request to the OpenAI API and parse the response.
@@ -435,7 +436,7 @@ class OpenAIChat(Model):
435
436
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
436
437
  tools: Optional[List[Dict[str, Any]]] = None,
437
438
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
438
- run_response: Optional[RunOutput] = None,
439
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
439
440
  ) -> ModelResponse:
440
441
  """
441
442
  Sends an asynchronous chat completion request to the OpenAI API.
@@ -514,7 +515,7 @@ class OpenAIChat(Model):
514
515
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
515
516
  tools: Optional[List[Dict[str, Any]]] = None,
516
517
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
517
- run_response: Optional[RunOutput] = None,
518
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
518
519
  ) -> Iterator[ModelResponse]:
519
520
  """
520
521
  Send a streaming chat completion request to the OpenAI API.
@@ -590,7 +591,7 @@ class OpenAIChat(Model):
590
591
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
591
592
  tools: Optional[List[Dict[str, Any]]] = None,
592
593
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
593
- run_response: Optional[RunOutput] = None,
594
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
594
595
  ) -> AsyncIterator[ModelResponse]:
595
596
  """
596
597
  Sends an asynchronous streaming chat completion request to the OpenAI API.
@@ -8,7 +8,7 @@ from typing_extensions import Literal
8
8
 
9
9
  from agno.exceptions import ModelProviderError
10
10
  from agno.media import File
11
- from agno.models.base import MessageData, Model
11
+ from agno.models.base import Model
12
12
  from agno.models.message import Citations, Message, UrlCitation
13
13
  from agno.models.metrics import Metrics
14
14
  from agno.models.response import ModelResponse
@@ -810,63 +810,6 @@ class OpenAIResponses(Model):
810
810
  _fc_message.tool_call_id = tool_call_ids[_fc_message_index]
811
811
  messages.append(_fc_message)
812
812
 
813
- def process_response_stream(
814
- self,
815
- messages: List[Message],
816
- assistant_message: Message,
817
- stream_data: MessageData,
818
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
819
- tools: Optional[List[Dict[str, Any]]] = None,
820
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
821
- run_response: Optional[RunOutput] = None,
822
- ) -> Iterator[ModelResponse]:
823
- """Process the synchronous response stream."""
824
- for model_response_delta in self.invoke_stream(
825
- messages=messages,
826
- assistant_message=assistant_message,
827
- tools=tools,
828
- response_format=response_format,
829
- tool_choice=tool_choice,
830
- run_response=run_response,
831
- ):
832
- yield from self._populate_stream_data_and_assistant_message(
833
- stream_data=stream_data,
834
- assistant_message=assistant_message,
835
- model_response_delta=model_response_delta,
836
- )
837
-
838
- # Add final metrics to assistant message
839
- self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
840
-
841
- async def aprocess_response_stream(
842
- self,
843
- messages: List[Message],
844
- assistant_message: Message,
845
- stream_data: MessageData,
846
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
847
- tools: Optional[List[Dict[str, Any]]] = None,
848
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
849
- run_response: Optional[RunOutput] = None,
850
- ) -> AsyncIterator[ModelResponse]:
851
- """Process the asynchronous response stream."""
852
- async for model_response_delta in self.ainvoke_stream(
853
- messages=messages,
854
- assistant_message=assistant_message,
855
- tools=tools,
856
- response_format=response_format,
857
- tool_choice=tool_choice,
858
- run_response=run_response,
859
- ):
860
- for model_response in self._populate_stream_data_and_assistant_message(
861
- stream_data=stream_data,
862
- assistant_message=assistant_message,
863
- model_response_delta=model_response_delta,
864
- ):
865
- yield model_response
866
-
867
- # Add final metrics to assistant message
868
- self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
869
-
870
813
  def _parse_provider_response(self, response: Response, **kwargs) -> ModelResponse:
871
814
  """
872
815
  Parse the OpenAI response into a ModelResponse.
@@ -6,6 +6,7 @@ from pydantic import BaseModel
6
6
 
7
7
  from agno.models.openai.like import OpenAILike
8
8
  from agno.run.agent import RunOutput
9
+ from agno.run.team import TeamRunOutput
9
10
 
10
11
 
11
12
  @dataclass
@@ -34,9 +35,11 @@ class Requesty(OpenAILike):
34
35
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
35
36
  tools: Optional[List[Dict[str, Any]]] = None,
36
37
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
37
- run_response: Optional[RunOutput] = None,
38
+ run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
38
39
  ) -> Dict[str, Any]:
39
- params = super().get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice)
40
+ params = super().get_request_params(
41
+ response_format=response_format, tools=tools, tool_choice=tool_choice, run_response=run_response
42
+ )
40
43
 
41
44
  if "extra_body" not in params:
42
45
  params["extra_body"] = {}
agno/os/app.py CHANGED
@@ -46,7 +46,7 @@ from agno.os.utils import (
46
46
  update_cors_middleware,
47
47
  )
48
48
  from agno.team.team import Team
49
- from agno.utils.log import logger
49
+ from agno.utils.log import log_debug, log_error, log_warning
50
50
  from agno.utils.string import generate_id, generate_id_from_name
51
51
  from agno.workflow.workflow import Workflow
52
52
 
@@ -454,21 +454,22 @@ class AgentOS:
454
454
 
455
455
  @fastapi_app.exception_handler(HTTPException)
456
456
  async def http_exception_handler(_, exc: HTTPException) -> JSONResponse:
457
+ log_error(f"HTTP exception: {exc.status_code} {exc.detail}")
457
458
  return JSONResponse(
458
459
  status_code=exc.status_code,
459
460
  content={"detail": str(exc.detail)},
460
461
  )
461
462
 
462
- async def general_exception_handler(request: Request, call_next):
463
- try:
464
- return await call_next(request)
465
- except Exception as e:
466
- return JSONResponse(
467
- status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
468
- content={"detail": str(e)},
469
- )
463
+ @fastapi_app.exception_handler(Exception)
464
+ async def general_exception_handler(_: Request, exc: Exception) -> JSONResponse:
465
+ import traceback
466
+
467
+ log_error(f"Unhandled exception:\n{traceback.format_exc(limit=5)}")
470
468
 
471
- fastapi_app.middleware("http")(general_exception_handler)
469
+ return JSONResponse(
470
+ status_code=getattr(exc, "status_code", 500),
471
+ content={"detail": str(exc)},
472
+ )
472
473
 
473
474
  # Update CORS middleware
474
475
  update_cors_middleware(fastapi_app, self.settings.cors_origin_list) # type: ignore
@@ -500,7 +501,7 @@ class AgentOS:
500
501
  # Skip conflicting AgentOS routes, prefer user's existing routes
501
502
  for conflict in conflicts:
502
503
  methods_str = ", ".join(conflict["methods"]) # type: ignore
503
- logger.debug(
504
+ log_debug(
504
505
  f"Skipping conflicting AgentOS route: {methods_str} {conflict['path']} - "
505
506
  f"Using existing custom route instead"
506
507
  )
@@ -519,7 +520,7 @@ class AgentOS:
519
520
  # Log warnings but still add all routes (AgentOS routes will override)
520
521
  for conflict in conflicts:
521
522
  methods_str = ", ".join(conflict["methods"]) # type: ignore
522
- logger.warning(
523
+ log_warning(
523
524
  f"Route conflict detected: {methods_str} {conflict['path']} - "
524
525
  f"AgentOS route will override existing custom route"
525
526
  )
agno/os/schema.py CHANGED
@@ -19,6 +19,7 @@ from agno.os.utils import (
19
19
  get_team_input_schema_dict,
20
20
  get_workflow_input_schema_dict,
21
21
  )
22
+ from agno.run import RunContext
22
23
  from agno.run.agent import RunOutput
23
24
  from agno.run.team import TeamRunOutput
24
25
  from agno.session import AgentSession, TeamSession, WorkflowSession
@@ -186,9 +187,6 @@ class AgentResponse(BaseModel):
186
187
  metadata: Optional[Dict[str, Any]] = None
187
188
  input_schema: Optional[Dict[str, Any]] = None
188
189
 
189
- class Config:
190
- exclude_none = True
191
-
192
190
  @classmethod
193
191
  async def from_agent(cls, agent: Agent) -> "AgentResponse":
194
192
  def filter_meaningful_config(d: Dict[str, Any], defaults: Dict[str, Any]) -> Optional[Dict[str, Any]]:
@@ -250,9 +248,12 @@ class AgentResponse(BaseModel):
250
248
  "stream_intermediate_steps": False,
251
249
  }
252
250
 
251
+ session_id = str(uuid4())
252
+ run_id = str(uuid4())
253
253
  agent_tools = await agent.aget_tools(
254
- session=AgentSession(session_id=str(uuid4()), session_data={}),
255
- run_response=RunOutput(run_id=str(uuid4())),
254
+ session=AgentSession(session_id=session_id, session_data={}),
255
+ run_response=RunOutput(run_id=run_id, session_id=session_id),
256
+ run_context=RunContext(run_id=run_id, session_id=session_id, user_id=agent.user_id),
256
257
  check_mcp_tools=False,
257
258
  )
258
259
  formatted_tools = format_tools(agent_tools) if agent_tools else None
@@ -474,12 +475,14 @@ class TeamResponse(BaseModel):
474
475
  "stream_member_events": False,
475
476
  }
476
477
 
478
+ run_id = str(uuid4())
479
+ session_id = str(uuid4())
477
480
  _tools = team._determine_tools_for_model(
478
481
  model=team.model, # type: ignore
479
- session=TeamSession(session_id=str(uuid4()), session_data={}),
480
- run_response=TeamRunOutput(run_id=str(uuid4())),
482
+ session=TeamSession(session_id=session_id, session_data={}),
483
+ run_response=TeamRunOutput(run_id=run_id),
484
+ run_context=RunContext(run_id=run_id, session_id=session_id, session_state={}),
481
485
  async_mode=True,
482
- session_state={},
483
486
  team_run_context={},
484
487
  check_mcp_tools=False,
485
488
  )
agno/run/__init__.py CHANGED
@@ -0,0 +1,6 @@
1
+ from agno.run.base import RunContext, RunStatus
2
+
3
+ __all__ = [
4
+ "RunContext",
5
+ "RunStatus",
6
+ ]
agno/run/base.py CHANGED
@@ -7,11 +7,22 @@ from pydantic import BaseModel
7
7
  from agno.media import Audio, Image, Video
8
8
  from agno.models.message import Citations, Message, MessageReferences
9
9
  from agno.models.metrics import Metrics
10
- from agno.models.response import ToolExecution
11
10
  from agno.reasoning.step import ReasoningStep
12
11
  from agno.utils.log import log_error
13
12
 
14
13
 
14
+ @dataclass
15
+ class RunContext:
16
+ run_id: str
17
+ session_id: str
18
+ user_id: Optional[str] = None
19
+
20
+ dependencies: Optional[Dict[str, Any]] = None
21
+ knowledge_filters: Optional[Dict[str, Any]] = None
22
+ metadata: Optional[Dict[str, Any]] = None
23
+ session_state: Optional[Dict[str, Any]] = None
24
+
25
+
15
26
  @dataclass
16
27
  class BaseRunOutputEvent:
17
28
  def to_dict(self) -> Dict[str, Any]:
@@ -98,6 +109,8 @@ class BaseRunOutputEvent:
98
109
  _dict["content"] = self.content.model_dump(exclude_none=True)
99
110
 
100
111
  if hasattr(self, "tools") and self.tools is not None:
112
+ from agno.models.response import ToolExecution
113
+
101
114
  _dict["tools"] = []
102
115
  for tool in self.tools:
103
116
  if isinstance(tool, ToolExecution):
@@ -106,6 +119,8 @@ class BaseRunOutputEvent:
106
119
  _dict["tools"].append(tool)
107
120
 
108
121
  if hasattr(self, "tool") and self.tool is not None:
122
+ from agno.models.response import ToolExecution
123
+
109
124
  if isinstance(self.tool, ToolExecution):
110
125
  _dict["tool"] = self.tool.to_dict()
111
126
  else:
@@ -139,6 +154,8 @@ class BaseRunOutputEvent:
139
154
  def from_dict(cls, data: Dict[str, Any]):
140
155
  tool = data.pop("tool", None)
141
156
  if tool:
157
+ from agno.models.response import ToolExecution
158
+
142
159
  data["tool"] = ToolExecution.from_dict(tool)
143
160
 
144
161
  images = data.pop("images", None)
agno/run/team.py CHANGED
@@ -469,8 +469,19 @@ def team_run_output_event_from_dict(data: dict) -> BaseTeamRunEvent:
469
469
  class TeamRunOutput:
470
470
  """Response returned by Team.run() functions"""
471
471
 
472
+ run_id: Optional[str] = None
473
+ team_id: Optional[str] = None
474
+ team_name: Optional[str] = None
475
+ session_id: Optional[str] = None
476
+ parent_run_id: Optional[str] = None
477
+ user_id: Optional[str] = None
478
+
479
+ # Input media and messages from user
480
+ input: Optional[TeamRunInput] = None
481
+
472
482
  content: Optional[Any] = None
473
483
  content_type: str = "str"
484
+
474
485
  messages: Optional[List[Message]] = None
475
486
  metrics: Optional[Metrics] = None
476
487
  model: Optional[str] = None
@@ -478,12 +489,6 @@ class TeamRunOutput:
478
489
 
479
490
  member_responses: List[Union["TeamRunOutput", RunOutput]] = field(default_factory=list)
480
491
 
481
- run_id: Optional[str] = None
482
- team_id: Optional[str] = None
483
- team_name: Optional[str] = None
484
- session_id: Optional[str] = None
485
- parent_run_id: Optional[str] = None
486
-
487
492
  tools: Optional[List[ToolExecution]] = None
488
493
 
489
494
  images: Optional[List[Image]] = None # Images from member runs
@@ -493,9 +498,6 @@ class TeamRunOutput:
493
498
 
494
499
  response_audio: Optional[Audio] = None # Model audio response
495
500
 
496
- # Input media and messages from user
497
- input: Optional[TeamRunInput] = None
498
-
499
501
  reasoning_content: Optional[str] = None
500
502
 
501
503
  citations: Optional[Citations] = None