3333 from .tracing import Tracer
3434
3535
36+ def _safe_tracer_call(
37+ tracer: Optional["Tracer"], method_name: str, verbose: bool, *args, **kwargs
38+ ) -> None:
39+ """
40+ Safely call tracer method, catching and logging errors without breaking execution.
41+
42+ Args:
43+ tracer: Tracer instance or None
44+ method_name: Name of tracer method to call (e.g., "emit", "emit_error")
45+ verbose: Whether to print error messages
46+ *args: Positional arguments for the tracer method
47+ **kwargs: Keyword arguments for the tracer method
48+ """
49+ if not tracer:
50+ return
51+ try:
52+ method = getattr(tracer, method_name)
53+ if args and kwargs:
54+ method(*args, **kwargs)
55+ elif args:
56+ method(*args)
57+ elif kwargs:
58+ method(**kwargs)
59+ else:
60+ method()
61+ except Exception as tracer_error:
62+ # Tracer errors should not break agent execution
63+ if verbose:
64+ print(f"⚠️ Tracer error (non-fatal): {tracer_error}")
65+
66+
3667class SentienceAgent(BaseAgent):
3768 """
3869 High-level agent that combines Sentience SDK with any LLM provider.
@@ -159,7 +190,10 @@ def act( # noqa: C901
159190 # Emit step_start trace event if tracer is enabled
160191 if self.tracer:
161192 pre_url = self.browser.page.url if self.browser.page else None
162- self.tracer.emit_step_start(
193+ _safe_tracer_call(
194+ self.tracer,
195+ "emit_step_start",
196+ self.verbose,
163197 step_id=step_id,
164198 step_index=self._step_count,
165199 goal=goal,
@@ -228,7 +262,10 @@ def act( # noqa: C901
228262 if snap.screenshot_format:
229263 snapshot_data["screenshot_format"] = snap.screenshot_format
230264
231- self.tracer.emit(
265+ _safe_tracer_call(
266+ self.tracer,
267+ "emit",
268+ self.verbose,
232269 "snapshot",
233270 snapshot_data,
234271 step_id=step_id,
@@ -254,7 +291,10 @@ def act( # noqa: C901
254291
255292 # Emit LLM query trace event if tracer is enabled
256293 if self.tracer:
257- self.tracer.emit(
294+ _safe_tracer_call(
295+ self.tracer,
296+ "emit",
297+ self.verbose,
258298 "llm_query",
259299 {
260300 "prompt_tokens": llm_response.prompt_tokens,
@@ -315,7 +355,10 @@ def act( # noqa: C901
315355 for el in filtered_snap.elements[:50]
316356 ]
317357
318- self.tracer.emit(
358+ _safe_tracer_call(
359+ self.tracer,
360+ "emit",
361+ self.verbose,
319362 "action",
320363 {
321364 "action": result.action,
@@ -435,14 +478,28 @@ def act( # noqa: C901
435478 verify_data=verify_data,
436479 )
437480
438- self.tracer.emit("step_end", step_end_data, step_id=step_id)
481+ _safe_tracer_call(
482+ self.tracer,
483+ "emit",
484+ self.verbose,
485+ "step_end",
486+ step_end_data,
487+ step_id=step_id,
488+ )
439489
440490 return result
441491
442492 except Exception as e:
443493 # Emit error trace event if tracer is enabled
444494 if self.tracer:
445- self.tracer.emit_error(step_id=step_id, error=str(e), attempt=attempt)
495+ _safe_tracer_call(
496+ self.tracer,
497+ "emit_error",
498+ self.verbose,
499+ step_id=step_id,
500+ error=str(e),
501+ attempt=attempt,
502+ )
446503
447504 if attempt < max_retries:
448505 if self.verbose:
@@ -668,7 +725,10 @@ async def act( # noqa: C901
668725 # Emit step_start trace event if tracer is enabled
669726 if self.tracer:
670727 pre_url = self.browser.page.url if self.browser.page else None
671- self.tracer.emit_step_start(
728+ _safe_tracer_call(
729+ self.tracer,
730+ "emit_step_start",
731+ self.verbose,
672732 step_id=step_id,
673733 step_index=self._step_count,
674734 goal=goal,
@@ -740,7 +800,10 @@ async def act( # noqa: C901
740800 if snap.screenshot_format:
741801 snapshot_data["screenshot_format"] = snap.screenshot_format
742802
743- self.tracer.emit(
803+ _safe_tracer_call(
804+ self.tracer,
805+ "emit",
806+ self.verbose,
744807 "snapshot",
745808 snapshot_data,
746809 step_id=step_id,
@@ -766,7 +829,10 @@ async def act( # noqa: C901
766829
767830 # Emit LLM query trace event if tracer is enabled
768831 if self.tracer:
769- self.tracer.emit(
832+ _safe_tracer_call(
833+ self.tracer,
834+ "emit",
835+ self.verbose,
770836 "llm_query",
771837 {
772838 "prompt_tokens": llm_response.prompt_tokens,
@@ -827,7 +893,10 @@ async def act( # noqa: C901
827893 for el in filtered_snap.elements[:50]
828894 ]
829895
830- self.tracer.emit(
896+ _safe_tracer_call(
897+ self.tracer,
898+ "emit",
899+ self.verbose,
831900 "action",
832901 {
833902 "action": result.action,
@@ -947,14 +1016,28 @@ async def act( # noqa: C901
9471016 verify_data=verify_data,
9481017 )
9491018
950- self.tracer.emit("step_end", step_end_data, step_id=step_id)
1019+ _safe_tracer_call(
1020+ self.tracer,
1021+ "emit",
1022+ self.verbose,
1023+ "step_end",
1024+ step_end_data,
1025+ step_id=step_id,
1026+ )
9511027
9521028 return result
9531029
9541030 except Exception as e:
9551031 # Emit error trace event if tracer is enabled
9561032 if self.tracer:
957- self.tracer.emit_error(step_id=step_id, error=str(e), attempt=attempt)
1033+ _safe_tracer_call(
1034+ self.tracer,
1035+ "emit_error",
1036+ self.verbose,
1037+ step_id=step_id,
1038+ error=str(e),
1039+ attempt=attempt,
1040+ )
9581041
9591042 if attempt < max_retries:
9601043 if self.verbose:
0 commit comments