Skip to content

ref(agno): Make agno use new integrations API#132

Merged
Abhijeet Prasad (AbhiPrasad) merged 1 commit intomainfrom
abhi-agno-migrate
Mar 24, 2026
Merged

ref(agno): Make agno use new integrations API#132
Abhijeet Prasad (AbhiPrasad) merged 1 commit intomainfrom
abhi-agno-migrate

Conversation

@AbhiPrasad
Copy link
Member

@AbhiPrasad Abhijeet Prasad (AbhiPrasad) commented Mar 24, 2026

ref #116

Convert the Agno instrumentation from the legacy wrappers pattern to the new integrations API introduced in #118.

I also heavily edited the agent skills with some of the learnings I made while doing this. Should become much more effective now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stamp

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are many classes that are created and have the same attributes names, what about using a factory function?

diff --git a/py/src/braintrust/integrations/agno/patchers.py b/py/src/braintrust/integrations/agno/patchers.py
index 112c947..5228d49 100644
--- a/py/src/braintrust/integrations/agno/patchers.py
+++ b/py/src/braintrust/integrations/agno/patchers.py
@@ -1,4 +1,4 @@
-from typing import Any, ClassVar
+from typing import Any
 
 from braintrust.integrations.base import CompositeFunctionWrapperPatcher, FunctionWrapperPatcher
 
@@ -34,66 +34,63 @@ from .tracing import (
 )
 
 
+def _patcher(
+    name: str,
+    target_module: str,
+    target_path: str,
+    wrapper: Any,
+    *,
+    priority: int = 100,
+    superseded_by: tuple = (),
+) -> type[FunctionWrapperPatcher]:
+    """Create a FunctionWrapperPatcher subclass from plain data."""
+    attrs: dict[str, Any] = {
+        "name": name,
+        "target_module": target_module,
+        "target_path": target_path,
+        "wrapper": wrapper,
+    }
+    if priority != 100:
+        attrs["priority"] = priority
+    if superseded_by:
+        attrs["superseded_by"] = superseded_by
+    return type(f"_{name}", (FunctionWrapperPatcher,), attrs)  # type: ignore[return-value]
+
+
 # ---------------------------------------------------------------------------
 # Agent patchers
 # ---------------------------------------------------------------------------
 
 # Private methods have higher priority (lower number) so they are tried first.
-# The public fallback patchers override applies() to yield when the private
+# The public fallback patchers use superseded_by to yield when the private
 # variant exists.
 
-
-class _AgentRunPrivatePatcher(FunctionWrapperPatcher):
-    name = "agno.agent.run.private"
-    target_module = "agno.agent"
-    target_path = "Agent._run"
-    wrapper = _agent_run_private_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _AgentRunPublicPatcher(FunctionWrapperPatcher):
-    """Fallback: wrap ``Agent.run`` only when ``Agent._run`` does not exist."""
-
-    name = "agno.agent.run.public"
-    target_module = "agno.agent"
-    target_path = "Agent.run"
-    wrapper = _agent_run_public_wrapper
-    priority: ClassVar[int] = 100
-    superseded_by = (_AgentRunPrivatePatcher,)
-
-
-class _AgentArunPrivatePatcher(FunctionWrapperPatcher):
-    name = "agno.agent.arun.private"
-    target_module = "agno.agent"
-    target_path = "Agent._arun"
-    wrapper = _agent_arun_private_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _AgentRunStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.agent.run_stream"
-    target_module = "agno.agent"
-    target_path = "Agent._run_stream"
-    wrapper = _agent_run_stream_wrapper
-
-
-class _AgentArunStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.agent.arun_stream"
-    target_module = "agno.agent"
-    target_path = "Agent._arun_stream"
-    wrapper = _agent_arun_stream_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _AgentArunPublicPatcher(FunctionWrapperPatcher):
-    """Fallback: wrap ``Agent.arun`` only when neither ``_arun`` nor ``_arun_stream`` exist."""
-
-    name = "agno.agent.arun.public"
-    target_module = "agno.agent"
-    target_path = "Agent.arun"
-    wrapper = _agent_arun_public_wrapper
-    priority: ClassVar[int] = 100
-    superseded_by = (_AgentArunPrivatePatcher, _AgentArunStreamPatcher)
+_AgentRunPrivatePatcher = _patcher(
+    "agno.agent.run.private", "agno.agent", "Agent._run", _agent_run_private_wrapper, priority=50
+)
+_AgentRunPublicPatcher = _patcher(
+    "agno.agent.run.public",
+    "agno.agent",
+    "Agent.run",
+    _agent_run_public_wrapper,
+    superseded_by=(_AgentRunPrivatePatcher,),
+)
+_AgentArunPrivatePatcher = _patcher(
+    "agno.agent.arun.private", "agno.agent", "Agent._arun", _agent_arun_private_wrapper, priority=50
+)
+_AgentRunStreamPatcher = _patcher(
+    "agno.agent.run_stream", "agno.agent", "Agent._run_stream", _agent_run_stream_wrapper
+)
+_AgentArunStreamPatcher = _patcher(
+    "agno.agent.arun_stream", "agno.agent", "Agent._arun_stream", _agent_arun_stream_wrapper, priority=50
+)
+_AgentArunPublicPatcher = _patcher(
+    "agno.agent.arun.public",
+    "agno.agent",
+    "Agent.arun",
+    _agent_arun_public_wrapper,
+    superseded_by=(_AgentArunPrivatePatcher, _AgentArunStreamPatcher),
+)
 class AgentPatcher(CompositeFunctionWrapperPatcher):
@@ -114,58 +111,26 @@ class AgentPatcher(CompositeFunctionWrapperPatcher):
 # Team patchers
 # ---------------------------------------------------------------------------
 
-
-class _TeamRunPrivatePatcher(FunctionWrapperPatcher):
-    name = "agno.team.run.private"
-    target_module = "agno.team"
-    target_path = "Team._run"
-    wrapper = _team_run_private_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _TeamRunPublicPatcher(FunctionWrapperPatcher):
-    """Fallback: wrap ``Team.run`` only when ``Team._run`` does not exist."""
-
-    name = "agno.team.run.public"
-    target_module = "agno.team"
-    target_path = "Team.run"
-    wrapper = _team_run_public_wrapper
-    priority: ClassVar[int] = 100
-    superseded_by = (_TeamRunPrivatePatcher,)
-
-
-class _TeamArunPrivatePatcher(FunctionWrapperPatcher):
-    name = "agno.team.arun.private"
-    target_module = "agno.team"
-    target_path = "Team._arun"
-    wrapper = _team_arun_private_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _TeamRunStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.team.run_stream"
-    target_module = "agno.team"
-    target_path = "Team._run_stream"
-    wrapper = _team_run_stream_wrapper
-
-
-class _TeamArunStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.team.arun_stream"
-    target_module = "agno.team"
-    target_path = "Team._arun_stream"
-    wrapper = _team_arun_stream_wrapper
-    priority: ClassVar[int] = 50
-
-
-class _TeamArunPublicPatcher(FunctionWrapperPatcher):
-    """Fallback: wrap ``Team.arun`` only when neither ``_arun`` nor ``_arun_stream`` exist."""
-
-    name = "agno.team.arun.public"
-    target_module = "agno.team"
-    target_path = "Team.arun"
-    wrapper = _team_arun_public_wrapper
-    priority: ClassVar[int] = 100
-    superseded_by = (_TeamArunPrivatePatcher, _TeamArunStreamPatcher)
+_TeamRunPrivatePatcher = _patcher(
+    "agno.team.run.private", "agno.team", "Team._run", _team_run_private_wrapper, priority=50
+)
+_TeamRunPublicPatcher = _patcher(
+    "agno.team.run.public", "agno.team", "Team.run", _team_run_public_wrapper, superseded_by=(_TeamRunPrivatePatcher,)
+)
+_TeamArunPrivatePatcher = _patcher(
+    "agno.team.arun.private", "agno.team", "Team._arun", _team_arun_private_wrapper, priority=50
+)
+_TeamRunStreamPatcher = _patcher("agno.team.run_stream", "agno.team", "Team._run_stream", _team_run_stream_wrapper)
+_TeamArunStreamPatcher = _patcher(
+    "agno.team.arun_stream", "agno.team", "Team._arun_stream", _team_arun_stream_wrapper, priority=50
+)
+_TeamArunPublicPatcher = _patcher(
+    "agno.team.arun.public",
+    "agno.team",
+    "Team.arun",
+    _team_arun_public_wrapper,
+    superseded_by=(_TeamArunPrivatePatcher, _TeamArunStreamPatcher),
+)
 class TeamPatcher(CompositeFunctionWrapperPatcher):
@@ -186,61 +151,24 @@ class TeamPatcher(CompositeFunctionWrapperPatcher):
 # Model patchers
 # ---------------------------------------------------------------------------
 
-
-class _ModelInvokePatcher(FunctionWrapperPatcher):
-    name = "agno.model.invoke"
-    target_module = "agno.models.base"
-    target_path = "Model.invoke"
-    wrapper = _model_invoke_wrapper
-
-
-class _ModelAinvokePatcher(FunctionWrapperPatcher):
-    name = "agno.model.ainvoke"
-    target_module = "agno.models.base"
-    target_path = "Model.ainvoke"
-    wrapper = _model_ainvoke_wrapper
-
-
-class _ModelInvokeStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.model.invoke_stream"
-    target_module = "agno.models.base"
-    target_path = "Model.invoke_stream"
-    wrapper = _model_invoke_stream_wrapper
-
-
-class _ModelAinvokeStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.model.ainvoke_stream"
-    target_module = "agno.models.base"
-    target_path = "Model.ainvoke_stream"
-    wrapper = _model_ainvoke_stream_wrapper
-
-
-class _ModelResponsePatcher(FunctionWrapperPatcher):
-    name = "agno.model.response"
-    target_module = "agno.models.base"
-    target_path = "Model.response"
-    wrapper = _model_response_wrapper
-
-
-class _ModelAresponsePatcher(FunctionWrapperPatcher):
-    name = "agno.model.aresponse"
-    target_module = "agno.models.base"
-    target_path = "Model.aresponse"
-    wrapper = _model_aresponse_wrapper
-
-
-class _ModelResponseStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.model.response_stream"
-    target_module = "agno.models.base"
-    target_path = "Model.response_stream"
-    wrapper = _model_response_stream_wrapper
-
-
-class _ModelAresponseStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.model.aresponse_stream"
-    target_module = "agno.models.base"
-    target_path = "Model.aresponse_stream"
-    wrapper = _model_aresponse_stream_wrapper
+_ModelInvokePatcher = _patcher("agno.model.invoke", "agno.models.base", "Model.invoke", _model_invoke_wrapper)
+_ModelAinvokePatcher = _patcher("agno.model.ainvoke", "agno.models.base", "Model.ainvoke", _model_ainvoke_wrapper)
+_ModelInvokeStreamPatcher = _patcher(
+    "agno.model.invoke_stream", "agno.models.base", "Model.invoke_stream", _model_invoke_stream_wrapper
+)
+_ModelAinvokeStreamPatcher = _patcher(
+    "agno.model.ainvoke_stream", "agno.models.base", "Model.ainvoke_stream", _model_ainvoke_stream_wrapper
+)
+_ModelResponsePatcher = _patcher("agno.model.response", "agno.models.base", "Model.response", _model_response_wrapper)
+_ModelAresponsePatcher = _patcher(
+    "agno.model.aresponse", "agno.models.base", "Model.aresponse", _model_aresponse_wrapper
+)
+_ModelResponseStreamPatcher = _patcher(
+    "agno.model.response_stream", "agno.models.base", "Model.response_stream", _model_response_stream_wrapper
+)
+_ModelAresponseStreamPatcher = _patcher(
+    "agno.model.aresponse_stream", "agno.models.base", "Model.aresponse_stream", _model_aresponse_stream_wrapper
+)
 class ModelPatcher(CompositeFunctionWrapperPatcher):
@@ -263,19 +191,12 @@ class ModelPatcher(CompositeFunctionWrapperPatcher):
 # FunctionCall patchers
 # ---------------------------------------------------------------------------
 
-
-class _FunctionCallExecutePatcher(FunctionWrapperPatcher):
-    name = "agno.function_call.execute"
-    target_module = "agno.tools.function"
-    target_path = "FunctionCall.execute"
-    wrapper = _function_call_execute_wrapper
-
-
-class _FunctionCallAexecutePatcher(FunctionWrapperPatcher):
-    name = "agno.function_call.aexecute"
-    target_module = "agno.tools.function"
-    target_path = "FunctionCall.aexecute"
-    wrapper = _function_call_aexecute_wrapper
+_FunctionCallExecutePatcher = _patcher(
+    "agno.function_call.execute", "agno.tools.function", "FunctionCall.execute", _function_call_execute_wrapper
+)
+_FunctionCallAexecutePatcher = _patcher(
+    "agno.function_call.aexecute", "agno.tools.function", "FunctionCall.aexecute", _function_call_aexecute_wrapper
+)
 
 
 class FunctionCallPatcher(CompositeFunctionWrapperPatcher):
@@ -292,47 +213,30 @@ class FunctionCallPatcher(CompositeFunctionWrapperPatcher):
 # Workflow patchers (optional — requires fastapi)
 # ---------------------------------------------------------------------------
 
-
-class _WorkflowExecutePatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.execute"
-    target_module = "agno.workflow"
-    target_path = "Workflow._execute"
-    wrapper = _workflow_execute_wrapper
-
-
-class _WorkflowExecuteStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.execute_stream"
-    target_module = "agno.workflow"
-    target_path = "Workflow._execute_stream"
-    wrapper = _workflow_execute_stream_wrapper
-
-
-class _WorkflowAexecutePatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.aexecute"
-    target_module = "agno.workflow"
-    target_path = "Workflow._aexecute"
-    wrapper = _workflow_aexecute_wrapper
-
-
-class _WorkflowAexecuteStreamPatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.aexecute_stream"
-    target_module = "agno.workflow"
-    target_path = "Workflow._aexecute_stream"
-    wrapper = _workflow_aexecute_stream_wrapper
-
-
-class _WorkflowExecuteWorkflowAgentPatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.execute_workflow_agent"
-    target_module = "agno.workflow"
-    target_path = "Workflow._execute_workflow_agent"
-    wrapper = _workflow_execute_workflow_agent_wrapper
-
-
-class _WorkflowAexecuteWorkflowAgentPatcher(FunctionWrapperPatcher):
-    name = "agno.workflow.aexecute_workflow_agent"
-    target_module = "agno.workflow"
-    target_path = "Workflow._aexecute_workflow_agent"
-    wrapper = _workflow_aexecute_workflow_agent_wrapper
+_WorkflowExecutePatcher = _patcher(
+    "agno.workflow.execute", "agno.workflow", "Workflow._execute", _workflow_execute_wrapper
+)
+_WorkflowExecuteStreamPatcher = _patcher(
+    "agno.workflow.execute_stream", "agno.workflow", "Workflow._execute_stream", _workflow_execute_stream_wrapper
+)
+_WorkflowAexecutePatcher = _patcher(
+    "agno.workflow.aexecute", "agno.workflow", "Workflow._aexecute", _workflow_aexecute_wrapper
+)
+_WorkflowAexecuteStreamPatcher = _patcher(
+    "agno.workflow.aexecute_stream", "agno.workflow", "Workflow._aexecute_stream", _workflow_aexecute_stream_wrapper
+)
+_WorkflowExecuteWorkflowAgentPatcher = _patcher(
+    "agno.workflow.execute_workflow_agent",
+    "agno.workflow",
+    "Workflow._execute_workflow_agent",
+    _workflow_execute_workflow_agent_wrapper,
+)
+_WorkflowAexecuteWorkflowAgentPatcher = _patcher(
+    "agno.workflow.aexecute_workflow_agent",
+    "agno.workflow",
+    "Workflow._aexecute_workflow_agent",
+    _workflow_aexecute_workflow_agent_wrapper,
+)
 
 
 class WorkflowPatcher(CompositeFunctionWrapperPatcher):

@AbhiPrasad Abhijeet Prasad (AbhiPrasad) merged commit 1163e11 into main Mar 24, 2026
33 checks passed
@AbhiPrasad Abhijeet Prasad (AbhiPrasad) deleted the abhi-agno-migrate branch March 24, 2026 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants