codekingpro/portable-devtools
114k
1"""LangSmith integration for Claude Agent SDK.2 3This module provides automatic tracing for the Claude Agent SDK by instrumenting4`ClaudeSDKClient` and injecting hooks to trace all tool calls.5 6Instrumentation is applied **in place** on the original ``ClaudeSDKClient`` class7so that callers who imported the class *before* ``configure_claude_agent_sdk()``8was called still get traced.9"""10 11import logging12from typing import Optional13 14from ._client import instrument_claude_client, instrument_sdk_mcp_tool15from ._config import set_tracing_config16 17logger = logging.getLogger(__name__)18 19__all__ = ["configure_claude_agent_sdk"]20 21 22def configure_claude_agent_sdk(23 name: Optional[str] = None,24 project_name: Optional[str] = None,25 metadata: Optional[dict] = None,26 tags: Optional[list[str]] = None,27) -> bool:28 """Enable LangSmith tracing for the Claude Agent SDK by patching entry points.29 30 This function instruments the Claude Agent SDK to automatically trace:31 - Chain runs for each conversation stream (via `ClaudeSDKClient`)32 - Model runs for each assistant turn33 - All tool calls including built-in tools, external MCP tools, and SDK MCP tools34 35 Tool tracing is implemented via `PreToolUse` and `PostToolUse` hooks.36 37 The class is patched **in place**, so references obtained via38 ``from claude_agent_sdk import ClaudeSDKClient`` before this call39 will still be instrumented.40 41 Args:42 name: Name of the root trace.43 project_name: LangSmith project to trace to.44 metadata: Metadata to associate with all traces.45 tags: Tags to associate with all traces.46 47 Returns:48 `True` if configuration was successful, `False` otherwise.49 50 Example:51 >>> from langsmith.integrations.claude_agent_sdk import (52 ... configure_claude_agent_sdk,53 ... )54 >>> configure_claude_agent_sdk(55 ... project_name="my-project", tags=["production"]56 ... ) # doctest: +SKIP57 >>> # Now use claude_agent_sdk as normal - tracing is automatic58 """59 try:60 import claude_agent_sdk # type: ignore[import-not-found]61 except ImportError:62 logger.warning("Claude Agent SDK not installed.")63 return False64 65 if not hasattr(claude_agent_sdk, "ClaudeSDKClient"):66 logger.warning("Claude Agent SDK missing ClaudeSDKClient.")67 return False68 69 set_tracing_config(70 name=name,71 project_name=project_name,72 metadata=metadata,73 tags=tags,74 )75 76 instrument_claude_client(claude_agent_sdk.ClaudeSDKClient)77 78 # Patch SdkMcpTool so that tool handlers are lazily wrapped with79 # run-context propagation, regardless of import order.80 sdk_mcp_tool_cls = getattr(claude_agent_sdk, "SdkMcpTool", None)81 if sdk_mcp_tool_cls:82 instrument_sdk_mcp_tool(sdk_mcp_tool_cls)83 84 return True85 