@@ -57,6 +57,28 @@ def _build_traceable(name: str, run_type: str, metadata: Optional[dict[str, Any]
5757 return _langsmith_traceable (name = name , run_type = run_type )
5858
5959
60+ import inspect
61+
62+ async def async_trace_call (
63+ name : str ,
64+ fn : Callable [..., Any ],
65+ * args : Any ,
66+ run_type : str = "chain" ,
67+ metadata : Optional [dict [str , Any ]] = None ,
68+ ** kwargs : Any ,
69+ ) -> Any :
70+ """Execute an asynchronous callable with LangSmith tracing when available."""
71+ if not LANGSMITH_ENABLED :
72+ return await fn (* args , ** kwargs )
73+
74+ decorator = _build_traceable (name , run_type , metadata )
75+ if decorator is None :
76+ return await fn (* args , ** kwargs )
77+
78+ traced_fn = decorator (fn )
79+ return await traced_fn (* args , ** kwargs )
80+
81+
6082def trace_call (
6183 name : str ,
6284 fn : Callable [..., Any ],
@@ -65,7 +87,10 @@ def trace_call(
6587 metadata : Optional [dict [str , Any ]] = None ,
6688 ** kwargs : Any ,
6789) -> Any :
68- """Execute a callable with LangSmith tracing when available."""
90+ """Execute a callable with LangSmith tracing when available. Supports both sync and async."""
91+ if inspect .iscoroutinefunction (fn ):
92+ return async_trace_call (name , fn , * args , run_type = run_type , metadata = metadata , ** kwargs )
93+
6994 if not LANGSMITH_ENABLED :
7095 return fn (* args , ** kwargs )
7196
@@ -83,8 +108,22 @@ def trace_function(
83108 run_type : str = "chain" ,
84109 metadata_factory : Optional [Callable [..., dict [str , Any ]]] = None ,
85110) -> Callable [[Callable [..., Any ]], Callable [..., Any ]]:
86- """Decorator wrapper that becomes a no-op when LangSmith is disabled."""
111+ """Decorator wrapper that becomes a no-op when LangSmith is disabled. Supports both sync and async. """
87112 def decorator (fn : Callable [..., Any ]) -> Callable [..., Any ]:
113+ if inspect .iscoroutinefunction (fn ):
114+ @wraps (fn )
115+ async def async_wrapped (* args : Any , ** kwargs : Any ) -> Any :
116+ metadata = metadata_factory (* args , ** kwargs ) if metadata_factory else None
117+ return await trace_call (
118+ name ,
119+ fn ,
120+ * args ,
121+ run_type = run_type ,
122+ metadata = metadata ,
123+ ** kwargs ,
124+ )
125+ return async_wrapped
126+
88127 @wraps (fn )
89128 def wrapped (* args : Any , ** kwargs : Any ) -> Any :
90129 metadata = metadata_factory (* args , ** kwargs ) if metadata_factory else None
@@ -96,7 +135,6 @@ def wrapped(*args: Any, **kwargs: Any) -> Any:
96135 metadata = metadata ,
97136 ** kwargs ,
98137 )
99-
100138 return wrapped
101139
102- return decorator
140+ return decorator
0 commit comments