feat: route graphs to separate LangSmith tracing projects (#1508)

* feat: route graphs to separate LangSmith tracing projects

* docs: point graph entrypoint references at traced wrappers

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Johannes du Plessis 2026-06-11 17:57:16 -07:00 • committed by GitHub
parent 3e105f5027
commit aa98d195a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 45 additions and 9 deletions

View file

@ -27,9 +27,9 @@ make format # ruff format + ruff check --fix
| Graph | Entrypoint | Purpose |
|---|---|---|
| `agent` | `agent.server:get_agent` | Main coding agent (Slack/Linear/GitHub-triggered). |
| `reviewer` | `agent.reviewer:get_reviewer_agent` | Read-only PR reviewer. Findings model + `publish_review`. |
| `analyzer` | `agent.analyzer:get_analyzer` | Learns per-repo reviewer style from historical PRs and this reviewer's own finding outcomes. |
| `agent` | `agent.server:traced_agent` (wraps `get_agent`) | Main coding agent (Slack/Linear/GitHub-triggered). |
| `reviewer` | `agent.reviewer:traced_reviewer_agent` (wraps `get_reviewer_agent`) | Read-only PR reviewer. Findings model + `publish_review`. |
| `analyzer` | `agent.analyzer:traced_analyzer` (wraps `get_analyzer`) | Learns per-repo reviewer style from historical PRs and this reviewer's own finding outcomes. |
The FastAPI app is `agent.webapp:app`.

View file

@ -632,9 +632,9 @@ The `langgraph.json` at the project root defines the three graphs and the HTTP a
```json
{
"graphs": {
"agent": "agent.server:get_agent",
"reviewer": "agent.reviewer:get_reviewer_agent",
"analyzer": "agent.analyzer:get_analyzer"
"agent": "agent.server:traced_agent",
"reviewer": "agent.reviewer:traced_reviewer_agent",
"analyzer": "agent.analyzer:traced_analyzer"
},
"http": {
"app": "agent.webapp:app"

View file

@ -46,6 +46,7 @@ from .utils.github_app import get_github_app_installation_token
from .utils.model import DEFAULT_LLM_REASONING, make_model, provider_model_kwargs
from .utils.sandbox_paths import aresolve_sandbox_work_dir
from .utils.sandbox_state import unwrap_sandbox_backend
from .utils.tracing import REVIEW_TRACING_PROJECT, traced_graph_factory
logger = logging.getLogger(__name__)
@ -148,3 +149,6 @@ async def get_analyzer(config: RunnableConfig) -> Pregel:
ToolErrorMiddleware(),
],
).with_config(config)
traced_analyzer = traced_graph_factory(get_analyzer, REVIEW_TRACING_PROJECT)

View file

@ -74,6 +74,7 @@ from .utils.github_token import cache_github_token_for_thread
from .utils.model import DEFAULT_LLM_REASONING, make_model, provider_model_kwargs
from .utils.repo_prep import materialize_trusted_skills, prepare_review_repo
from .utils.sandbox_paths import aresolve_sandbox_work_dir
from .utils.tracing import REVIEW_TRACING_PROJECT, traced_graph_factory
REVIEWER_PROMPT_TEMPLATE = """You are a specialized code reviewer agent. Your job is to review one GitHub PR and publish a single review.
@ -1052,3 +1053,6 @@ async def get_reviewer_agent(config: RunnableConfig) -> Pregel:
settle_review_check_on_exit,
],
).with_config(config)
traced_reviewer_agent = traced_graph_factory(get_reviewer_agent, REVIEW_TRACING_PROJECT)

View file

@ -95,6 +95,7 @@ from .utils.model import (
)
from .utils.sandbox import create_sandbox
from .utils.sandbox_paths import aresolve_sandbox_work_dir
from .utils.tracing import AGENT_TRACING_PROJECT, traced_graph_factory
client = get_client()
@ -726,3 +727,6 @@ async def get_agent(config: RunnableConfig) -> Pregel:
SanitizeThinkingBlocksMiddleware(),
],
).with_config(config)
traced_agent = traced_graph_factory(get_agent, AGENT_TRACING_PROJECT)

24
agent/utils/tracing.py Normal file
View file

@ -0,0 +1,24 @@
"""Per-graph LangSmith tracing-project routing for langgraph.json entrypoints."""
import contextlib
from collections.abc import AsyncIterator, Awaitable, Callable
import langsmith as ls
from langgraph.graph.state import RunnableConfig
from langgraph.pregel import Pregel
AGENT_TRACING_PROJECT = "open-swe-agent"
REVIEW_TRACING_PROJECT = "open-swe-review"
def traced_graph_factory(
factory: Callable[[RunnableConfig], Awaitable[Pregel]],
project_name: str,
) -> Callable[[RunnableConfig], contextlib.AbstractAsyncContextManager[Pregel]]:
@contextlib.asynccontextmanager
async def entrypoint(config: RunnableConfig) -> AsyncIterator[Pregel]:
graph = await factory(config)
with ls.tracing_context(project_name=project_name):
yield graph
return entrypoint

View file

@ -3,9 +3,9 @@
"python_version": "3.12",
"api_version": "0.10.0rc3",
"graphs": {
"agent": "agent.server:get_agent",
"reviewer": "agent.reviewer:get_reviewer_agent",
"analyzer": "agent.analyzer:get_analyzer",
"agent": "agent.server:traced_agent",
"reviewer": "agent.reviewer:traced_reviewer_agent",
"analyzer": "agent.analyzer:traced_analyzer",
"scheduler": "agent.scheduler:get_scheduler"
},
"dependencies": [