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
This commit is contained in:
Aran Yogesh 2026-04-23 13:46:28 -07:00 • committed by GitHub
parent a3a40a1bec
commit fc3e492083
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 14 deletions

View file

@ -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

View file

@ -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]:

View file

@ -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!")

View file

@ -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: