From fc3e4920834d1b360b2a8316a5fed74a76eedcac Mon Sep 17 00:00:00 2001 From: Aran Yogesh Date: Thu, 23 Apr 2026 13:46:28 -0700 Subject: [PATCH] fix: use thread-level LangSmith URLs instead of run-level URLs to fix broken trace links (#1217) * fix: use thread-level LangSmith URLs instead of run-level URLs to fix broken trace links * linting --- agent/utils/langsmith.py | 12 +++++++----- agent/utils/linear.py | 12 ++++++++++-- agent/utils/slack.py | 6 ++++-- agent/webapp.py | 10 +++++----- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/agent/utils/langsmith.py b/agent/utils/langsmith.py index 98c0cea2..bc9d9f9c 100644 --- a/agent/utils/langsmith.py +++ b/agent/utils/langsmith.py @@ -20,11 +20,13 @@ def _compose_langsmith_project_url() -> str: return f"{host_url}/o/{tenant_id}/projects/p/{project_id}" -def get_langsmith_trace_url(run_id: str) -> str | None: - """Build the LangSmith trace URL for a given run ID.""" +def get_langsmith_trace_url(thread_id: str) -> str | None: + """Build the LangSmith thread URL for a given thread ID.""" try: - base = _compose_langsmith_project_url() - return f"{base}?peek={run_id}&peeked_trace={run_id}" + project_url = _compose_langsmith_project_url() + return f"{project_url}/t/{thread_id}" except Exception: # noqa: BLE001 - logger.warning("Failed to build LangSmith trace URL for run %s", run_id, exc_info=True) + logger.warning( + "Failed to build LangSmith trace URL for thread %s", thread_id, exc_info=True + ) return None diff --git a/agent/utils/linear.py b/agent/utils/linear.py index 6ce680af..a8130892 100644 --- a/agent/utils/linear.py +++ b/agent/utils/linear.py @@ -63,15 +63,23 @@ async def comment_on_linear_issue( return bool(result.get("commentCreate", {}).get("success")) -async def post_linear_trace_comment(issue_id: str, run_id: str, triggering_comment_id: str) -> None: +async def post_linear_trace_comment( + issue_id: str, thread_id: str, triggering_comment_id: str +) -> None: """Post a trace URL comment on a Linear issue.""" - trace_url = get_langsmith_trace_url(run_id) + trace_url = get_langsmith_trace_url(thread_id) if trace_url: await comment_on_linear_issue( issue_id, f"On it! [View trace]({trace_url})", parent_id=triggering_comment_id or None, ) + else: + await comment_on_linear_issue( + issue_id, + "On it!", + parent_id=triggering_comment_id or None, + ) async def list_teams() -> dict[str, Any]: diff --git a/agent/utils/slack.py b/agent/utils/slack.py index c54ca290..96bf17b4 100644 --- a/agent/utils/slack.py +++ b/agent/utils/slack.py @@ -365,10 +365,12 @@ async def fetch_slack_thread_messages(channel_id: str, thread_ts: str) -> list[d return messages -async def post_slack_trace_reply(channel_id: str, thread_ts: str, run_id: str) -> None: +async def post_slack_trace_reply(channel_id: str, thread_ts: str, thread_id: str) -> None: """Post a trace URL reply in a Slack thread.""" - trace_url = get_langsmith_trace_url(run_id) + trace_url = get_langsmith_trace_url(thread_id) if trace_url: await post_slack_thread_reply( channel_id, thread_ts, f"Working on it! <{trace_url}|View trace>" ) + else: + await post_slack_thread_reply(channel_id, thread_ts, "Working on it!") diff --git a/agent/webapp.py b/agent/webapp.py index a7166a37..9fcb2f2e 100644 --- a/agent/webapp.py +++ b/agent/webapp.py @@ -675,13 +675,13 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915 langgraph_client = get_client(url=LANGGRAPH_URL) runs = await langgraph_client.runs.list(thread_id, limit=1) if runs: - await post_linear_trace_comment(issue_id, runs[0]["run_id"], triggering_comment_id) + await post_linear_trace_comment(issue_id, thread_id, triggering_comment_id) else: logger.error("Failed to queue message for thread %s", thread_id) else: logger.info("Creating LangGraph run for thread %s", thread_id) langgraph_client = get_client(url=LANGGRAPH_URL) - run = await langgraph_client.runs.create( + await langgraph_client.runs.create( thread_id, "agent", input={"messages": [{"role": "user", "content": content_blocks}]}, @@ -689,7 +689,7 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915 if_not_exists="create", ) logger.info("LangGraph run created successfully for thread %s", thread_id) - await post_linear_trace_comment(issue_id, run["run_id"], triggering_comment_id) + await post_linear_trace_comment(issue_id, thread_id, triggering_comment_id) async def process_slack_mention(event_data: dict[str, Any], repo_config: dict[str, str]) -> None: @@ -834,7 +834,7 @@ async def process_slack_mention(event_data: dict[str, Any], repo_config: dict[st logger.error("Failed to queue Slack message for thread %s", thread_id) return - run = await langgraph_client.runs.create( + await langgraph_client.runs.create( thread_id, "agent", input={"messages": [{"role": "user", "content": content_blocks}]}, @@ -842,7 +842,7 @@ async def process_slack_mention(event_data: dict[str, Any], repo_config: dict[st if_not_exists="create", multitask_strategy="interrupt", ) - await post_slack_trace_reply(channel_id, thread_ts, run["run_id"]) + await post_slack_trace_reply(channel_id, thread_ts, thread_id) def verify_linear_signature(body: bytes, signature: str, secret: str) -> bool: