diff --git a/.github/workflows/loongsuite_lint_0.yml b/.github/workflows/loongsuite_lint_0.yml index 8b51ece98..4ca6f1b60 100644 --- a/.github/workflows/loongsuite_lint_0.yml +++ b/.github/workflows/loongsuite_lint_0.yml @@ -84,7 +84,7 @@ jobs: shell: bash env: LOONGSUITE_ALL_JOBS: >- - [{"name": "lint-loongsuite-instrumentation-agentscope", "package": "loongsuite-instrumentation-agentscope", "tox_env": "lint-loongsuite-instrumentation-agentscope", "ui_name": "loongsuite-instrumentation-agentscope"}, {"name": "lint-loongsuite-instrumentation-dashscope", "package": "loongsuite-instrumentation-dashscope", "tox_env": "lint-loongsuite-instrumentation-dashscope", "ui_name": "loongsuite-instrumentation-dashscope"}, {"name": "lint-loongsuite-instrumentation-claude-agent-sdk", "package": "loongsuite-instrumentation-claude-agent-sdk", "tox_env": "lint-loongsuite-instrumentation-claude-agent-sdk", "ui_name": "loongsuite-instrumentation-claude-agent-sdk"}, {"name": "lint-loongsuite-instrumentation-google-adk", "package": "loongsuite-instrumentation-google-adk", "tox_env": "lint-loongsuite-instrumentation-google-adk", "ui_name": "loongsuite-instrumentation-google-adk"}, {"name": "lint-loongsuite-instrumentation-agno", "package": "loongsuite-instrumentation-agno", "tox_env": "lint-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno"}, {"name": "lint-loongsuite-instrumentation-langchain", "package": "loongsuite-instrumentation-langchain", "tox_env": "lint-loongsuite-instrumentation-langchain", "ui_name": "loongsuite-instrumentation-langchain"}, {"name": "lint-loongsuite-instrumentation-langgraph", "package": "loongsuite-instrumentation-langgraph", "tox_env": "lint-loongsuite-instrumentation-langgraph", "ui_name": "loongsuite-instrumentation-langgraph"}, {"name": "lint-loongsuite-instrumentation-deepagents", "package": "loongsuite-instrumentation-deepagents", "tox_env": "lint-loongsuite-instrumentation-deepagents", "ui_name": "loongsuite-instrumentation-deepagents"}, {"name": "lint-loongsuite-instrumentation-microsoft-agent-framework", "package": "loongsuite-instrumentation-microsoft-agent-framework", "tox_env": "lint-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework"}, {"name": "lint-loongsuite-instrumentation-qwen-agent", "package": "loongsuite-instrumentation-qwen-agent", "tox_env": "lint-loongsuite-instrumentation-qwen-agent", "ui_name": "loongsuite-instrumentation-qwen-agent"}, {"name": "lint-loongsuite-instrumentation-hermes-agent", "package": "loongsuite-instrumentation-hermes-agent", "tox_env": "lint-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent"}, {"name": "lint-loongsuite-instrumentation-mem0", "package": "loongsuite-instrumentation-mem0", "tox_env": "lint-loongsuite-instrumentation-mem0", "ui_name": "loongsuite-instrumentation-mem0"}, {"name": "lint-util-genai", "package": "util-genai", "tox_env": "lint-util-genai", "ui_name": "util-genai"}, {"name": "lint-loongsuite-instrumentation-litellm", "package": "loongsuite-instrumentation-litellm", "tox_env": "lint-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm"}, {"name": "lint-loongsuite-instrumentation-crewai", "package": "loongsuite-instrumentation-crewai", "tox_env": "lint-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai"}, {"name": "lint-loongsuite-instrumentation-qwenpaw", "package": "loongsuite-instrumentation-qwenpaw", "tox_env": "lint-loongsuite-instrumentation-qwenpaw", "ui_name": "loongsuite-instrumentation-qwenpaw"}, {"name": "lint-loongsuite-instrumentation-algotune", "package": "loongsuite-instrumentation-algotune", "tox_env": "lint-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune"}, {"name": "lint-loongsuite-instrumentation-bfclv4", "package": "loongsuite-instrumentation-bfclv4", "tox_env": "lint-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4"}, {"name": "lint-loongsuite-instrumentation-claw-eval", "package": "loongsuite-instrumentation-claw-eval", "tox_env": "lint-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval"}, {"name": "lint-loongsuite-instrumentation-minisweagent", "package": "loongsuite-instrumentation-minisweagent", "tox_env": "lint-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent"}, {"name": "lint-loongsuite-instrumentation-openhands", "package": "loongsuite-instrumentation-openhands", "tox_env": "lint-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands"}, {"name": "lint-loongsuite-instrumentation-slop-code", "package": "loongsuite-instrumentation-slop-code", "tox_env": "lint-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code"}, {"name": "lint-loongsuite-instrumentation-terminus2", "package": "loongsuite-instrumentation-terminus2", "tox_env": "lint-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2"}, {"name": "lint-loongsuite-instrumentation-vita", "package": "loongsuite-instrumentation-vita", "tox_env": "lint-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita"}, {"name": "lint-loongsuite-instrumentation-webarena", "package": "loongsuite-instrumentation-webarena", "tox_env": "lint-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena"}, {"name": "lint-loongsuite-instrumentation-widesearch", "package": "loongsuite-instrumentation-widesearch", "tox_env": "lint-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch"}, {"name": "lint-loongsuite-instrumentation-wildtool", "package": "loongsuite-instrumentation-wildtool", "tox_env": "lint-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool"}] + [{"name": "lint-loongsuite-instrumentation-agentscope", "package": "loongsuite-instrumentation-agentscope", "tox_env": "lint-loongsuite-instrumentation-agentscope", "ui_name": "loongsuite-instrumentation-agentscope"}, {"name": "lint-loongsuite-instrumentation-dashscope", "package": "loongsuite-instrumentation-dashscope", "tox_env": "lint-loongsuite-instrumentation-dashscope", "ui_name": "loongsuite-instrumentation-dashscope"}, {"name": "lint-loongsuite-instrumentation-claude-agent-sdk", "package": "loongsuite-instrumentation-claude-agent-sdk", "tox_env": "lint-loongsuite-instrumentation-claude-agent-sdk", "ui_name": "loongsuite-instrumentation-claude-agent-sdk"}, {"name": "lint-loongsuite-instrumentation-google-adk", "package": "loongsuite-instrumentation-google-adk", "tox_env": "lint-loongsuite-instrumentation-google-adk", "ui_name": "loongsuite-instrumentation-google-adk"}, {"name": "lint-loongsuite-instrumentation-agno", "package": "loongsuite-instrumentation-agno", "tox_env": "lint-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno"}, {"name": "lint-loongsuite-instrumentation-langchain", "package": "loongsuite-instrumentation-langchain", "tox_env": "lint-loongsuite-instrumentation-langchain", "ui_name": "loongsuite-instrumentation-langchain"}, {"name": "lint-loongsuite-instrumentation-langgraph", "package": "loongsuite-instrumentation-langgraph", "tox_env": "lint-loongsuite-instrumentation-langgraph", "ui_name": "loongsuite-instrumentation-langgraph"}, {"name": "lint-loongsuite-instrumentation-autogen", "package": "loongsuite-instrumentation-autogen", "tox_env": "lint-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen"}, {"name": "lint-loongsuite-instrumentation-deepagents", "package": "loongsuite-instrumentation-deepagents", "tox_env": "lint-loongsuite-instrumentation-deepagents", "ui_name": "loongsuite-instrumentation-deepagents"}, {"name": "lint-loongsuite-instrumentation-microsoft-agent-framework", "package": "loongsuite-instrumentation-microsoft-agent-framework", "tox_env": "lint-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework"}, {"name": "lint-loongsuite-instrumentation-qwen-agent", "package": "loongsuite-instrumentation-qwen-agent", "tox_env": "lint-loongsuite-instrumentation-qwen-agent", "ui_name": "loongsuite-instrumentation-qwen-agent"}, {"name": "lint-loongsuite-instrumentation-hermes-agent", "package": "loongsuite-instrumentation-hermes-agent", "tox_env": "lint-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent"}, {"name": "lint-loongsuite-instrumentation-mem0", "package": "loongsuite-instrumentation-mem0", "tox_env": "lint-loongsuite-instrumentation-mem0", "ui_name": "loongsuite-instrumentation-mem0"}, {"name": "lint-util-genai", "package": "util-genai", "tox_env": "lint-util-genai", "ui_name": "util-genai"}, {"name": "lint-loongsuite-instrumentation-litellm", "package": "loongsuite-instrumentation-litellm", "tox_env": "lint-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm"}, {"name": "lint-loongsuite-instrumentation-crewai", "package": "loongsuite-instrumentation-crewai", "tox_env": "lint-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai"}, {"name": "lint-loongsuite-instrumentation-qwenpaw", "package": "loongsuite-instrumentation-qwenpaw", "tox_env": "lint-loongsuite-instrumentation-qwenpaw", "ui_name": "loongsuite-instrumentation-qwenpaw"}, {"name": "lint-loongsuite-instrumentation-algotune", "package": "loongsuite-instrumentation-algotune", "tox_env": "lint-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune"}, {"name": "lint-loongsuite-instrumentation-bfclv4", "package": "loongsuite-instrumentation-bfclv4", "tox_env": "lint-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4"}, {"name": "lint-loongsuite-instrumentation-claw-eval", "package": "loongsuite-instrumentation-claw-eval", "tox_env": "lint-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval"}, {"name": "lint-loongsuite-instrumentation-minisweagent", "package": "loongsuite-instrumentation-minisweagent", "tox_env": "lint-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent"}, {"name": "lint-loongsuite-instrumentation-openhands", "package": "loongsuite-instrumentation-openhands", "tox_env": "lint-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands"}, {"name": "lint-loongsuite-instrumentation-slop-code", "package": "loongsuite-instrumentation-slop-code", "tox_env": "lint-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code"}, {"name": "lint-loongsuite-instrumentation-terminus2", "package": "loongsuite-instrumentation-terminus2", "tox_env": "lint-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2"}, {"name": "lint-loongsuite-instrumentation-vita", "package": "loongsuite-instrumentation-vita", "tox_env": "lint-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita"}, {"name": "lint-loongsuite-instrumentation-webarena", "package": "loongsuite-instrumentation-webarena", "tox_env": "lint-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena"}, {"name": "lint-loongsuite-instrumentation-widesearch", "package": "loongsuite-instrumentation-widesearch", "tox_env": "lint-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch"}, {"name": "lint-loongsuite-instrumentation-wildtool", "package": "loongsuite-instrumentation-wildtool", "tox_env": "lint-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool"}] LOONGSUITE_FULL: ${{ steps.detect.outputs.full }} LOONGSUITE_PACKAGES: ${{ steps.detect.outputs.packages }} run: | diff --git a/.github/workflows/loongsuite_test_0.yml b/.github/workflows/loongsuite_test_0.yml index e0b8dc10e..885c95dbb 100644 --- a/.github/workflows/loongsuite_test_0.yml +++ b/.github/workflows/loongsuite_test_0.yml @@ -84,7 +84,7 @@ jobs: shell: bash env: LOONGSUITE_ALL_JOBS: >- - [{"name": "py310-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.13 ARC"}, {"name": "py39-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.9", "tox_env": "py39-test-util-genai", "ui_name": "util-genai 3.9 ARC"}, {"name": "py310-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.10", "tox_env": "py310-test-util-genai", "ui_name": "util-genai 3.10 ARC"}, {"name": "py311-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.11", "tox_env": "py311-test-util-genai", "ui_name": "util-genai 3.11 ARC"}, {"name": "py312-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.12", "tox_env": "py312-test-util-genai", "ui_name": "util-genai 3.12 ARC"}, {"name": "py313-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.13", "tox_env": "py313-test-util-genai", "ui_name": "util-genai 3.13 ARC"}, {"name": "py314-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.14", "tox_env": "py314-test-util-genai", "ui_name": "util-genai 3.14 ARC"}, {"name": "pypy3-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "pypy-3.9", "tox_env": "pypy3-test-util-genai", "ui_name": "util-genai pypy-3.9 ARC"}, {"name": "py311-test-detect-loongsuite-changes_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "detect-loongsuite-changes", "python_version": "3.11", "tox_env": "py311-test-detect-loongsuite-changes", "ui_name": "detect-loongsuite-changes 3.11 ARC"}, {"name": "py310-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.13 ARC"}, {"name": "py39-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.9", "tox_env": "py39-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.9 ARC"}, {"name": "py310-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.10", "tox_env": "py310-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.10 ARC"}, {"name": "py311-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.11", "tox_env": "py311-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.11 ARC"}, {"name": "py312-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.12", "tox_env": "py312-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.12 ARC"}, {"name": "py313-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.13", "tox_env": "py313-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.13 ARC"}] + [{"name": "py310-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-oldest", "ui_name": "loongsuite-instrumentation-agentscope-oldest 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agentscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agentscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agentscope-latest", "ui_name": "loongsuite-instrumentation-agentscope-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-oldest", "ui_name": "loongsuite-instrumentation-dashscope-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-dashscope-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-dashscope", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-dashscope-latest", "ui_name": "loongsuite-instrumentation-dashscope-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-oldest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claude-agent-sdk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claude-agent-sdk-latest", "ui_name": "loongsuite-instrumentation-claude-agent-sdk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-oldest", "ui_name": "loongsuite-instrumentation-google-adk-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-google-adk-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-google-adk", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-google-adk-latest", "ui_name": "loongsuite-instrumentation-google-adk-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-agno_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-agno", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-oldest", "ui_name": "loongsuite-instrumentation-langchain-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langchain-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langchain", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langchain-latest", "ui_name": "loongsuite-instrumentation-langchain-latest 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-oldest", "ui_name": "loongsuite-instrumentation-langgraph-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-langgraph-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-langgraph", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-langgraph-latest", "ui_name": "loongsuite-instrumentation-langgraph-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-autogen_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-autogen", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-deepagents-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-deepagents", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-deepagents-latest", "ui_name": "loongsuite-instrumentation-deepagents-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-microsoft-agent-framework_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-microsoft-agent-framework", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework 3.13 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.9 ARC"}, {"name": "py39-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.9", "tox_env": "py39-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.9 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-oldest", "ui_name": "loongsuite-instrumentation-qwen-agent-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwen-agent-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwen-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwen-agent-latest", "ui_name": "loongsuite-instrumentation-qwen-agent-latest 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-hermes-agent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-hermes-agent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-oldest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-oldest", "ui_name": "loongsuite-instrumentation-mem0-oldest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-mem0-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-mem0", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-mem0-latest", "ui_name": "loongsuite-instrumentation-mem0-latest 3.13 ARC"}, {"name": "py39-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.9", "tox_env": "py39-test-util-genai", "ui_name": "util-genai 3.9 ARC"}, {"name": "py310-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.10", "tox_env": "py310-test-util-genai", "ui_name": "util-genai 3.10 ARC"}, {"name": "py311-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.11", "tox_env": "py311-test-util-genai", "ui_name": "util-genai 3.11 ARC"}, {"name": "py312-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.12", "tox_env": "py312-test-util-genai", "ui_name": "util-genai 3.12 ARC"}, {"name": "py313-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.13", "tox_env": "py313-test-util-genai", "ui_name": "util-genai 3.13 ARC"}, {"name": "py314-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "3.14", "tox_env": "py314-test-util-genai", "ui_name": "util-genai 3.14 ARC"}, {"name": "pypy3-test-util-genai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "util-genai", "python_version": "pypy-3.9", "tox_env": "pypy3-test-util-genai", "ui_name": "util-genai pypy-3.9 ARC"}, {"name": "py311-test-detect-loongsuite-changes_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "detect-loongsuite-changes", "python_version": "3.11", "tox_env": "py311-test-detect-loongsuite-changes", "ui_name": "detect-loongsuite-changes 3.11 ARC"}, {"name": "py310-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-litellm_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-litellm", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-crewai_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-crewai", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.10 ARC"}, {"name": "py310-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.11 ARC"}, {"name": "py311-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.12 ARC"}, {"name": "py312-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-latest_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-latest", "ui_name": "loongsuite-instrumentation-qwenpaw-latest 3.13 ARC"}, {"name": "py313-test-loongsuite-instrumentation-qwenpaw-legacy_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-qwenpaw", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-qwenpaw-legacy", "ui_name": "loongsuite-instrumentation-qwenpaw-legacy 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-algotune_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-algotune", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-bfclv4_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-bfclv4", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-claw-eval_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-claw-eval", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-minisweagent_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-minisweagent", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-openhands_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-openhands", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-slop-code_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-slop-code", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-terminus2_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-terminus2", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-vita_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-vita", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-webarena_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-webarena", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena 3.13 ARC"}, {"name": "py311-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-widesearch_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-widesearch", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch 3.13 ARC"}, {"name": "py310-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.10", "tox_env": "py310-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.10 ARC"}, {"name": "py311-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.11", "tox_env": "py311-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.11 ARC"}, {"name": "py312-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.12", "tox_env": "py312-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.12 ARC"}, {"name": "py313-test-loongsuite-instrumentation-wildtool_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-instrumentation-wildtool", "python_version": "3.13", "tox_env": "py313-test-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool 3.13 ARC"}, {"name": "py39-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.9", "tox_env": "py39-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.9 ARC"}, {"name": "py310-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.10", "tox_env": "py310-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.10 ARC"}, {"name": "py311-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.11", "tox_env": "py311-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.11 ARC"}, {"name": "py312-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.12", "tox_env": "py312-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.12 ARC"}, {"name": "py313-test-loongsuite-distro_loongsuite-python-arc", "os": "loongsuite-python-arc", "package": "loongsuite-distro", "python_version": "3.13", "tox_env": "py313-test-loongsuite-distro", "ui_name": "loongsuite-distro 3.13 ARC"}] LOONGSUITE_FULL: ${{ steps.detect.outputs.full }} LOONGSUITE_PACKAGES: ${{ steps.detect.outputs.packages }} run: | diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/CHANGELOG.md b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/CHANGELOG.md index 8f978bed5..e5eea384b 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/CHANGELOG.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- Avoid enriching non-AutoGen spans that use overlapping GenAI operation names. + ## Version 0.7.0 (2026-07-03) ### Added diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/patch.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/patch.py index 062983969..a49f1b021 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/patch.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/patch.py @@ -33,6 +33,7 @@ from .config import is_agent_span_enabled, is_llm_span_enabled from .semantic_conventions import ( + AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME, GEN_AI_OPERATION_NAME, GEN_AI_PROVIDER_NAME, @@ -239,6 +240,16 @@ def _apply_invoke_agent_attrs( logger.debug("AutoGen invoke_agent span enrichment failed: %s", exc) +def _mark_autogen_live_span(invocation: Any) -> None: + span = getattr(invocation, "span", None) + if span is None: + return + try: + setattr(span, AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME) + except Exception: + pass + + def _model_client_arg( args: tuple[Any, ...], kwargs: dict[str, Any], name: str ) -> Any: @@ -433,6 +444,7 @@ async def _direct_model_create_wrapper(wrapped, instance, args, kwargs): # type handler = _get_handler() invocation = _make_direct_model_invocation(instance, args, kwargs) handler.start_llm(invocation) + _mark_autogen_live_span(invocation) try: result = await wrapped(*args, **kwargs) apply_create_result(invocation, result) @@ -453,6 +465,7 @@ async def _generator(): # type: ignore[no-untyped-def] handler = _get_handler() invocation = _make_direct_model_invocation(instance, args, kwargs) handler.start_llm(invocation) + _mark_autogen_live_span(invocation) try: async for item in wrapped(*args, **kwargs): if ( @@ -511,6 +524,7 @@ async def _generator(): # type: ignore[no-untyped-def] output_type=output_type, ) handler.start_llm(invocation) + _mark_autogen_live_span(invocation) try: async for item in _contextual_async_iter( wrapped(*args, **kwargs), diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/semantic_conventions.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/semantic_conventions.py index 18b34f25e..5efe2bb18 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/semantic_conventions.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/semantic_conventions.py @@ -35,6 +35,7 @@ class GenAIOperation: AUTOGEN_PROVIDER_NAME: Final = "autogen" +AUTOGEN_LIVE_SPAN_MARKER: Final = "_loongsuite_autogen_framework" GEN_AI_AGENT_DESCRIPTION: Final = "gen_ai.agent.description" GEN_AI_AGENT_ID: Final = "gen_ai.agent.id" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/span_processor.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/span_processor.py index 7b93f06a7..c56d03c67 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/span_processor.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/span_processor.py @@ -18,7 +18,7 @@ import logging import threading -from typing import Any, Optional +from typing import Any, Mapping, Optional from opentelemetry.context import Context from opentelemetry.sdk.trace import SpanProcessor @@ -26,7 +26,11 @@ from opentelemetry.trace import SpanKind from .semantic_conventions import ( + AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME, + GEN_AI_AGENT_DESCRIPTION, + GEN_AI_AGENT_ID, + GEN_AI_AGENT_NAME, GEN_AI_OPERATION_NAME, GEN_AI_PROVIDER_NAME, GEN_AI_SPAN_KIND, @@ -42,9 +46,39 @@ f"{GenAIOperation.EXECUTE_TOOL} ", f"{GenAIOperation.INVOKE_AGENT} ", ) +_AUTOGEN_PRIVATE_ATTRS = frozenset( + { + "autogen.code.block_count", + "autogen.code.exit_code", + "autogen.code.retry_attempt", + "autogen.handoff.context_count", + "autogen.handoff.source", + "autogen.handoff.target", + "autogen.memory.result_count", + "autogen.team.message_count", + "autogen.team.participants", + "autogen.team.stop_reason", + "autogen.team.type", + "autogen.user_input.request_id", + } +) +_CREATE_AGENT_LIFECYCLE_ATTRS = ( + GEN_AI_AGENT_DESCRIPTION, + GEN_AI_AGENT_ID, + GEN_AI_AGENT_NAME, + GEN_AI_OPERATION_NAME, + GEN_AI_PROVIDER_NAME, + GEN_AI_SPAN_KIND, + GEN_AI_SYSTEM, + "gen_ai.agent.version", + "gen_ai.system_instructions", + "gen_ai.tool.definitions", +) def _attr_value(span: Any, key: str) -> Any: + if isinstance(span, Mapping): + return span.get(key) attrs = getattr(span, "_attributes", None) if attrs is not None: try: @@ -57,6 +91,46 @@ def _attr_value(span: Any, key: str) -> Any: return None +def _attr_values(value: Any) -> tuple[str, ...]: + if value is None: + return () + if isinstance(value, (list, tuple)): + values = value + else: + values = (value,) + return tuple(str(item).lower() for item in values if item is not None) + + +def _span_attrs(span: Any) -> Mapping[Any, Any]: + if isinstance(span, Mapping): + return span + attrs = getattr(span, "_attributes", None) + if attrs is not None: + return attrs + attrs = getattr(span, "attributes", None) + if attrs is not None: + return attrs + return {} + + +def _has_live_autogen_marker(live: Any | None) -> bool: + if live is None: + return False + return ( + getattr(live, AUTOGEN_LIVE_SPAN_MARKER, None) == AUTOGEN_PROVIDER_NAME + ) + + +def _has_autogen_marker(readable: Any, live: Any | None = None) -> bool: + if _has_live_autogen_marker(live): + return True + for key in (GEN_AI_SYSTEM, GEN_AI_PROVIDER_NAME): + if AUTOGEN_PROVIDER_NAME in _attr_values(_attr_value(readable, key)): + return True + attrs = _span_attrs(readable) + return any(str(key) in _AUTOGEN_PRIVATE_ATTRS for key in attrs) + + def _set_attr(live_span: OtelSpan, key: str, value: Any) -> None: if value is None: return @@ -138,19 +212,9 @@ def _set_otel_span_kind( def _is_autogen_span( - name: str, operation: Optional[str], readable: Any + _name: str, _operation: Optional[str], readable: Any, live: Any | None ) -> bool: - if _attr_value(readable, GEN_AI_SYSTEM) == AUTOGEN_PROVIDER_NAME: - return True - if _attr_value(readable, GEN_AI_PROVIDER_NAME) == AUTOGEN_PROVIDER_NAME: - return True - if operation in { - GenAIOperation.CREATE_AGENT, - GenAIOperation.EXECUTE_TOOL, - GenAIOperation.INVOKE_AGENT, - }: - return True - return name.startswith(_AUTOGEN_NAME_PREFIXES) + return _has_autogen_marker(readable, live) def _classify_span( @@ -208,10 +272,15 @@ def on_end(self, span: Any) -> None: name = span.name or "" existing_op = _attr_value(span, GEN_AI_OPERATION_NAME) operation = existing_op if isinstance(existing_op, str) else None - if not _is_autogen_span(name, operation, span): + if not _is_autogen_span(name, operation, span, live): return span_kind, op_name = _classify_span(name, operation) + if op_name == GenAIOperation.CREATE_AGENT: + for attr_name in _CREATE_AGENT_LIFECYCLE_ATTRS: + _delete_attr_on_both(live, span, attr_name) + return + if span_kind and not _attr_value(span, GEN_AI_SPAN_KIND): _set_attr_on_both(live, span, GEN_AI_SPAN_KIND, span_kind) if not operation: @@ -235,7 +304,11 @@ def on_end(self, span: Any) -> None: if span_kind == GenAISpanKind.LLM: _set_otel_span_kind(live, span, SpanKind.CLIENT) - elif span_kind in {GenAISpanKind.AGENT, GenAISpanKind.TOOL}: + elif span_kind == GenAISpanKind.AGENT and op_name == ( + GenAIOperation.INVOKE_AGENT + ): + _set_otel_span_kind(live, span, SpanKind.INTERNAL) + elif span_kind == GenAISpanKind.TOOL: _set_otel_span_kind(live, span, SpanKind.INTERNAL) except Exception as exc: # pragma: no cover - defensive logger.warning("AutoGenSemanticProcessor.on_end failed: %s", exc) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/utils.py index cb7fdad41..8d318fb38 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/utils.py @@ -25,6 +25,7 @@ GenericToolDefinition, InputMessage, LLMInvocation, + MessagePart, OutputMessage, Reasoning, Text, @@ -159,6 +160,17 @@ def to_input_messages(messages: Sequence[Any] | None) -> list[InputMessage]: return result +def system_instruction_parts( + messages: Sequence[Any] | None, +) -> list[MessagePart]: + parts: list[MessagePart] = [] + for message in messages or []: + if _type_name(message) != "SystemMessage": + continue + parts.extend(_content_parts(field_value(message, "content"))) + return parts + + def tool_definitions(tools: Iterable[Any] | None) -> list[Any]: definitions: list[Any] = [] for tool in tools or []: @@ -241,7 +253,7 @@ def provider_name(model_client: Any) -> str: def _finish_reason(value: Any) -> str: reason = _text(value or "unknown") - if reason == "function_calls": + if reason in {"tool_call", "function_call", "function_calls"}: return "tool_calls" return reason @@ -311,6 +323,7 @@ def make_agent_invocation(instance: Any) -> InvokeAgentInvocation: ) description = field_value(instance, "description", "_description") model_client = field_value(instance, "_model_client") + system_messages = field_value(instance, "_system_messages") or [] return InvokeAgentInvocation( provider=AUTOGEN_PROVIDER_NAME, agent_name=name, @@ -325,9 +338,7 @@ def make_agent_invocation(instance: Any) -> InvokeAgentInvocation: ) if model_client is not None else None, - input_messages=to_input_messages( - field_value(instance, "_system_messages") or [] - ), + system_instruction=system_instruction_parts(system_messages), tool_definitions=tool_definitions(field_value(instance, "_tools")), ) @@ -401,18 +412,10 @@ def apply_agent_stream_item( invocation.attributes["autogen.team.stop_reason"] = _text( stop_reason ) - if messages: - last_message = messages[-1] - parts = _content_parts(field_value(last_message, "content")) - if parts: - invocation.output_messages = [ - OutputMessage( - role="assistant", - parts=parts, - finish_reason="stop", - ) - ] - invocation.finish_reasons = ["stop"] + output_message = _final_agent_output_message(messages) + if output_message is not None: + invocation.output_messages = [output_message] + invocation.finish_reasons = ["stop"] usage = field_value(message, "models_usage") prompt_tokens = field_value(usage, "prompt_tokens") @@ -428,20 +431,53 @@ def apply_agent_stream_item( except (TypeError, ValueError): pass - content = field_value(message, "content") - parts = _content_parts(content) - if parts and message_type != "ToolCallRequestEvent": - invocation.output_messages = [ - OutputMessage( - role="assistant", - parts=parts, - finish_reason="stop", - ) - ] - invocation.finish_reasons = ["stop"] + if _is_agent_output_message_type(message_type): + output_message = _agent_output_message_from_message(message) + if output_message is not None: + invocation.output_messages = [output_message] + invocation.finish_reasons = ["stop"] return first_token_s +def _final_agent_output_message( + messages: Sequence[Any], +) -> OutputMessage | None: + for message in reversed(messages): + if not _is_agent_output_message_type(_type_name(message)): + continue + output_message = _agent_output_message_from_message(message) + if output_message is not None: + return output_message + return None + + +def _is_agent_output_message_type(message_type: str) -> bool: + return message_type in { + "ChatMessage", + "TextMessage", + "ToolCallSummaryMessage", + } + + +def _agent_output_message_from_message(message: Any) -> OutputMessage | None: + parts = _user_visible_parts( + _content_parts(field_value(message, "content")) + ) + if not parts: + return None + return OutputMessage(role="assistant", parts=parts, finish_reason="stop") + + +def _user_visible_parts(parts: Sequence[Any]) -> list[Any]: + visible: list[Any] = [] + for part in parts: + part_type = getattr(part, "type", None) + if part_type in {"tool_call", "tool_call_response", "reasoning"}: + continue + visible.append(part) + return visible + + def make_tool_invocation(tool_call: Any) -> ExecuteToolInvocation: name = _text(field_value(tool_call, "name")) return ExecuteToolInvocation( diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/test-requirements.txt index 4f991e2a2..3d39f8f8b 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/test-requirements.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/test-requirements.txt @@ -17,5 +17,6 @@ pytest-asyncio pytest-cov setuptools +-e opentelemetry-instrumentation -e util/opentelemetry-util-genai -e instrumentation-loongsuite/loongsuite-instrumentation-autogen diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_patch.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_patch.py index c48cdc948..898d69d7c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_patch.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_patch.py @@ -16,6 +16,10 @@ import pytest +from opentelemetry.instrumentation._semconv import ( + OTEL_SEMCONV_STABILITY_OPT_IN, + _OpenTelemetrySemanticConventionStability, +) from opentelemetry.instrumentation.autogen import patch from opentelemetry.instrumentation.autogen.semantic_conventions import ( AUTOGEN_PROVIDER_NAME, @@ -30,6 +34,9 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) +from opentelemetry.util.genai.environment_variables import ( + OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, +) class Handler: @@ -169,6 +176,19 @@ def _set_handler(handler: Handler): patch._get_handler.handler = handler # type: ignore[attr-defined] +@pytest.fixture() +def genai_span_content(monkeypatch): + monkeypatch.setenv( + OTEL_SEMCONV_STABILITY_OPT_IN, "gen_ai_latest_experimental" + ) + monkeypatch.setenv( + OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, "SPAN_ONLY" + ) + _OpenTelemetrySemanticConventionStability._initialized = False + yield + _OpenTelemetrySemanticConventionStability._initialized = False + + def test_direct_model_patch_list_excludes_wrappers_and_replay_clients(): targets = {target for _, target in patch._DIRECT_MODEL_CLIENT_PATCHES} @@ -199,10 +219,9 @@ async def wrapped(): @pytest.mark.asyncio -async def test_agent_wrapper_enriches_native_autogen_agent_span(monkeypatch): - monkeypatch.setenv( - "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT", "SPAN_ONLY" - ) +async def test_agent_wrapper_enriches_native_autogen_agent_span( + genai_span_content, +): handler = Handler() _set_handler(handler) exporter = InMemorySpanExporter() @@ -239,8 +258,10 @@ async def wrapped(*args, **kwargs): assert handler.calls == [] assert attributes["gen_ai.request.model"] == "qwen-plus" assert "gen_ai.input.messages" in attributes - assert "system" in attributes["gen_ai.input.messages"] + assert "system" not in attributes["gen_ai.input.messages"] assert "hello" in attributes["gen_ai.input.messages"] + assert "gen_ai.system_instructions" in attributes + assert "system" in attributes["gen_ai.system_instructions"] assert "gen_ai.output.messages" in attributes assert "agent done" in attributes["gen_ai.output.messages"] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_span_processor.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_span_processor.py index 5ab862ff0..1099f95c8 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_span_processor.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_span_processor.py @@ -14,8 +14,12 @@ from __future__ import annotations +from opentelemetry.instrumentation.autogen.patch import _mark_autogen_live_span from opentelemetry.instrumentation.autogen.semantic_conventions import ( + AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME, + GEN_AI_AGENT_DESCRIPTION, + GEN_AI_AGENT_ID, GEN_AI_AGENT_NAME, GEN_AI_OPERATION_NAME, GEN_AI_PROVIDER_NAME, @@ -66,7 +70,7 @@ def test_processor_normalizes_native_autogen_invoke_span(): assert span.kind == SpanKind.INTERNAL -def test_processor_keeps_create_agent_as_lifecycle_span(): +def test_processor_keeps_create_agent_as_lifecycle_span_without_agent_kind(): exporter = InMemorySpanExporter() provider = TracerProvider() provider.add_span_processor(AutoGenSemanticProcessor()) @@ -87,10 +91,52 @@ def test_processor_keeps_create_agent_as_lifecycle_span(): [span] = exporter.get_finished_spans() attributes = _span_attributes(span) - assert attributes[GEN_AI_PROVIDER_NAME] == AUTOGEN_PROVIDER_NAME - assert attributes[GEN_AI_OPERATION_NAME] == GenAIOperation.CREATE_AGENT + assert GEN_AI_AGENT_NAME not in attributes + assert GEN_AI_OPERATION_NAME not in attributes + assert GEN_AI_PROVIDER_NAME not in attributes + assert GEN_AI_SPAN_KIND not in attributes + assert GEN_AI_SYSTEM not in attributes + assert span.kind == SpanKind.CLIENT + + +def test_processor_removes_native_agent_kind_from_create_agent_span(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "create_agent assistant", + kind=SpanKind.CLIENT, + attributes={ + GEN_AI_SYSTEM: AUTOGEN_PROVIDER_NAME, + GEN_AI_AGENT_DESCRIPTION: "test agent", + GEN_AI_AGENT_ID: "agent-1", + GEN_AI_OPERATION_NAME: GenAIOperation.CREATE_AGENT, + GEN_AI_AGENT_NAME: "assistant", + GEN_AI_PROVIDER_NAME: AUTOGEN_PROVIDER_NAME, + GEN_AI_SPAN_KIND: GenAISpanKind.AGENT, + "gen_ai.agent.version": "1.0.0", + "gen_ai.system_instructions": "be helpful", + "gen_ai.tool.definitions": ["search"], + }, + ): + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert GEN_AI_AGENT_DESCRIPTION not in attributes + assert GEN_AI_AGENT_ID not in attributes + assert GEN_AI_AGENT_NAME not in attributes + assert GEN_AI_OPERATION_NAME not in attributes + assert GEN_AI_PROVIDER_NAME not in attributes assert GEN_AI_SPAN_KIND not in attributes assert GEN_AI_SYSTEM not in attributes + assert "gen_ai.agent.version" not in attributes + assert "gen_ai.system_instructions" not in attributes + assert "gen_ai.tool.definitions" not in attributes assert span.kind == SpanKind.CLIENT @@ -115,3 +161,171 @@ def test_processor_classifies_llm_span_from_provider_attributes(): assert attributes[GEN_AI_SPAN_KIND] == GenAISpanKind.LLM assert span.kind == SpanKind.CLIENT + + +def test_processor_classifies_llm_span_from_autogen_private_marker(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "chat gpt-4o-mini", + attributes={ + GEN_AI_PROVIDER_NAME: "openai", + GEN_AI_OPERATION_NAME: GenAIOperation.CHAT, + }, + ) as span: + setattr(span, AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME) + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert attributes[GEN_AI_PROVIDER_NAME] == "openai" + assert attributes[GEN_AI_SPAN_KIND] == GenAISpanKind.LLM + assert AUTOGEN_LIVE_SPAN_MARKER not in attributes + assert span.kind == SpanKind.CLIENT + + +def test_patch_marks_live_llm_span_without_exported_attribute(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "chat gpt-4o-mini", + attributes={ + GEN_AI_PROVIDER_NAME: "openai", + GEN_AI_OPERATION_NAME: GenAIOperation.CHAT, + }, + ) as live_span: + invocation = type("Invocation", (), {"span": live_span})() + _mark_autogen_live_span(invocation) + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert attributes[GEN_AI_PROVIDER_NAME] == "openai" + assert attributes[GEN_AI_SPAN_KIND] == GenAISpanKind.LLM + assert AUTOGEN_LIVE_SPAN_MARKER not in attributes + assert span.kind == SpanKind.CLIENT + + +def test_processor_classifies_agent_span_from_known_private_attribute(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "invoke_agent assistant", + attributes={ + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + GEN_AI_AGENT_NAME: "assistant", + "autogen.team.type": "RoundRobinGroupChat", + }, + ): + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert attributes[GEN_AI_PROVIDER_NAME] == AUTOGEN_PROVIDER_NAME + assert attributes[GEN_AI_SPAN_KIND] == GenAISpanKind.AGENT + + +def test_processor_ignores_maf_span_with_overlapping_agent_operation(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "invoke_agent my-agent", + attributes={ + GEN_AI_PROVIDER_NAME: "microsoft.agent_framework", + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + }, + ): + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert attributes[GEN_AI_PROVIDER_NAME] == "microsoft.agent_framework" + assert GEN_AI_SPAN_KIND not in attributes + + +def test_processor_ignores_unmarked_overlapping_agent_operation(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "invoke_agent assistant", + attributes={GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT}, + ): + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert GEN_AI_PROVIDER_NAME not in attributes + assert GEN_AI_SPAN_KIND not in attributes + + +def test_processor_ignores_foreign_provider_agent_spans(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + for provider_name in ("langchain", "agentscope"): + with tracer.start_as_current_span( + f"invoke_agent {provider_name}-agent", + attributes={ + GEN_AI_PROVIDER_NAME: provider_name, + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + }, + ): + pass + + spans = exporter.get_finished_spans() + assert len(spans) == 2 + for span in spans: + attributes = _span_attributes(span) + assert attributes[GEN_AI_PROVIDER_NAME] in {"langchain", "agentscope"} + assert GEN_AI_SPAN_KIND not in attributes + + +def test_processor_ignores_unknown_autogen_prefixed_foreign_attribute(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(AutoGenSemanticProcessor()) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + + tracer = provider.get_tracer(__name__) + with tracer.start_as_current_span( + "invoke_agent langchain-agent", + attributes={ + GEN_AI_PROVIDER_NAME: "langchain", + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + "autogen.unrelated": "foreign-custom-attribute", + }, + ): + pass + + [span] = exporter.get_finished_spans() + attributes = _span_attributes(span) + + assert attributes[GEN_AI_PROVIDER_NAME] == "langchain" + assert GEN_AI_SPAN_KIND not in attributes diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_utils.py index 845abbba5..9fc2a5c5c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests/test_utils.py @@ -21,6 +21,7 @@ GEN_AI_AGENT_NAME, ) from opentelemetry.instrumentation.autogen.utils import ( + apply_agent_stream_item, apply_create_result, make_agent_invocation, make_llm_invocation, @@ -75,6 +76,28 @@ class FunctionCall: arguments: dict +@dataclass +class ToolCallRequestEvent: + content: list[FunctionCall] + + +@dataclass +class ToolCallExecutionEvent: + content: list[FunctionExecutionResult] + + +@dataclass +class ToolCallSummaryMessage: + content: str + source: str + + +@dataclass +class TaskResult: + messages: list + stop_reason: str | None = None + + @dataclass class Usage: prompt_tokens: int @@ -220,6 +243,22 @@ def test_apply_create_result_normalizes_tool_call_finish_reason(): assert invocation.output_messages[0].finish_reason == "tool_calls" +def test_apply_create_result_normalizes_singular_tool_call_finish_reason(): + invocation = make_llm_invocation(ModelClient(), [], []) + + apply_create_result( + invocation, + CreateResult( + [FunctionCall("call-1", "lookup", {"q": "x"})], + "tool_call", + Usage(prompt_tokens=3, completion_tokens=5), + ), + ) + + assert invocation.finish_reasons == ["tool_calls"] + assert invocation.output_messages[0].finish_reason == "tool_calls" + + def test_make_agent_invocation_uses_assistant_metadata(): class AssistantAgent: _name = "assistant" @@ -235,5 +274,47 @@ class AssistantAgent: assert invocation.agent_description == "answers" assert invocation.request_model == "qwen-plus" assert invocation.response_model_name == "qwen-plus-2025-04-28" - assert invocation.input_messages[0].parts == [Text(content="system")] + assert invocation.input_messages == [] + assert invocation.system_instruction == [Text(content="system")] assert invocation.tool_definitions == tool_definitions([Tool()]) + + +def test_apply_agent_stream_item_uses_only_final_task_result_output(): + invocation = make_agent_invocation(type("AssistantAgent", (), {})()) + + apply_agent_stream_item( + invocation, + TaskResult( + messages=[ + TextMessage("Use the weather tool.", "user"), + ToolCallRequestEvent( + [FunctionCall("call-1", "lookup", {"city": "Hangzhou"})] + ), + ToolCallExecutionEvent( + [FunctionExecutionResult("call-1", "sunny")] + ), + ToolCallSummaryMessage("Weather is sunny.", "assistant"), + ], + stop_reason="done", + ), + first_token_s=None, + ) + + assert invocation.output_messages[0].parts == [ + Text(content="Weather is sunny.") + ] + assert invocation.output_messages[0].finish_reason == "stop" + assert invocation.finish_reasons == ["stop"] + assert invocation.attributes["autogen.team.message_count"] == 4 + + +def test_apply_agent_stream_item_skips_intermediate_tool_events(): + invocation = make_agent_invocation(type("AssistantAgent", (), {})()) + + apply_agent_stream_item( + invocation, + ToolCallExecutionEvent([FunctionExecutionResult("call-1", "sunny")]), + first_token_s=None, + ) + + assert invocation.output_messages == [] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/CHANGELOG.md b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/CHANGELOG.md index 3441b2a6f..f1820e343 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/CHANGELOG.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- Avoid enriching non-MAF spans that use overlapping GenAI operation names. + ## Version 0.7.0 (2026-07-03) ### Added diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/react_step_patch.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/react_step_patch.py index 86cb2d81c..d38d59213 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/react_step_patch.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/react_step_patch.py @@ -41,6 +41,8 @@ import contextvars import inspect import logging +from dataclasses import dataclass +from types import TracebackType from typing import Any logger = logging.getLogger(__name__) @@ -54,6 +56,9 @@ _maf_react_step_counter: contextvars.ContextVar[int] = contextvars.ContextVar( "_maf_react_step_counter", default=0 ) +_maf_current_react_step: contextvars.ContextVar[Any] = contextvars.ContextVar( + "_maf_current_react_step", default=None +) _applied = False _original_fil_get_response: Any = None @@ -61,6 +66,27 @@ _handler: Any = None +@dataclass +class _OpenReactStep: + cm: Any + invocation: Any + + +def _mark_maf_live_span(invocation: Any) -> None: + span = getattr(invocation, "span", None) + if span is None: + return + try: + from opentelemetry.instrumentation.microsoft_agent_framework.semantic_conventions import ( + MAF_LIVE_SPAN_MARKER, + MAF_PROVIDER_NAME, + ) + + setattr(span, MAF_LIVE_SPAN_MARKER, MAF_PROVIDER_NAME) + except Exception: + pass + + def _get_extended_handler(tracer_provider: Any = None) -> Any: """Return the singleton ExtendedTelemetryHandler, creating it on first use.""" global _handler @@ -124,11 +150,17 @@ def _fil_wrapper(wrapped, instance, args, kwargs): # type: ignore[no-untyped-de async def _scoped(): # type: ignore[no-untyped-def] token_active = _maf_react_loop_active.set(True) token_counter = _maf_react_step_counter.set(0) + token_step = _maf_current_react_step.set(None) try: return await result + except Exception as exc: + _close_current_react_step(type(exc), exc, exc.__traceback__) + raise finally: + _close_current_react_step() _maf_react_loop_active.reset(token_active) _maf_react_step_counter.reset(token_counter) + _maf_current_react_step.reset(token_step) return _scoped() @@ -151,26 +183,24 @@ def _chat_wrapper(wrapped, instance, args, kwargs): # type: ignore[no-untyped-d local_handler = handler async def _step_scoped(): # type: ignore[no-untyped-def] - from opentelemetry.util.genai.extended_types import ( - ReactStepInvocation, - ) - - step_inv = ReactStepInvocation(round=round_num) - token_counter = _maf_react_step_counter.set(round_num) + previous_step = _close_current_react_step() + if previous_step is not None and inspect.isawaitable( + previous_step + ): + await previous_step + step_inv = _open_current_react_step(local_handler, round_num) + _maf_react_step_counter.set(round_num) try: - with local_handler.react_step(step_inv) as step: - try: - response = await result - # Best-effort finish_reason extraction from the response. - finish = _extract_finish_reason(response) - if finish is not None: - step.finish_reason = finish - return response - except Exception: - step.finish_reason = "error" - raise - finally: - _maf_react_step_counter.reset(token_counter) + response = await result + # Best-effort finish_reason extraction from the response. + finish = _extract_finish_reason(response) + if finish is not None: + step_inv.finish_reason = finish + return response + except Exception as exc: + step_inv.finish_reason = "error" + _close_current_react_step(type(exc), exc, exc.__traceback__) + raise return _step_scoped() @@ -212,6 +242,31 @@ def _unwrap_to_function(func: Any) -> Any: return cur +def _open_current_react_step(handler: Any, round_num: int) -> Any: + from opentelemetry.util.genai.extended_types import ReactStepInvocation + + step_inv = ReactStepInvocation(round=round_num) + cm = handler.react_step(step_inv) + step = cm.__enter__() + _mark_maf_live_span(step) + _maf_current_react_step.set(_OpenReactStep(cm=cm, invocation=step)) + return step + + +def _close_current_react_step( + exc_type: type[BaseException] | None = None, + exc: BaseException | None = None, + tb: TracebackType | None = None, +) -> Any: + current = _maf_current_react_step.get() + if current is None: + return None + _maf_current_react_step.set(None) + if exc_type is not None and current.invocation.finish_reason is None: + current.invocation.finish_reason = "error" + return current.cm.__exit__(exc_type, exc, tb) + + def _is_response_stream(result: Any) -> bool: """Return True for MAF ResponseStream-like values. @@ -228,23 +283,38 @@ def _is_response_stream(result: Any) -> bool: def _extract_finish_reason(result: Any) -> Any: """Best-effort extraction of a finish_reason string from a ChatResponse.""" try: + fr = getattr(result, "finish_reason", None) + if fr: + return _normalize_finish_reason(fr) + raw = getattr(result, "raw_representation", None) + if raw is not None: + fr = getattr(raw, "finish_reason", None) + if fr: + return _normalize_finish_reason(fr) # MAF ChatResponse.messages[-1].finish_reason or choices[0].finish_reason messages = getattr(result, "messages", None) if messages: last = messages[-1] fr = getattr(last, "finish_reason", None) if fr: - return fr + return _normalize_finish_reason(fr) choices = getattr(result, "choices", None) if choices: fr = getattr(choices[0], "finish_reason", None) if fr: - return fr + return _normalize_finish_reason(fr) except Exception: return None return None +def _normalize_finish_reason(value: Any) -> str: + reason = str(value) + if reason in {"tool_call", "function_call", "function_calls"}: + return "tool_calls" + return reason + + def revert_react_step_patch() -> None: """Revert the ReAct step patch. Safe to call even if not applied.""" global _applied, _original_fil_get_response, _original_chat_get_response diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/semantic_conventions.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/semantic_conventions.py index 3ee12eda0..ed2fb8954 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/semantic_conventions.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/semantic_conventions.py @@ -26,6 +26,9 @@ from typing import Final +MAF_PROVIDER_NAME: Final = "microsoft.agent_framework" +MAF_LIVE_SPAN_MARKER: Final = "_loongsuite_maf_framework" + class GenAISpanKind: """``gen_ai.span.kind`` enumeration (ARMS gen-ai.md).""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/span_processor.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/span_processor.py index 8adab3b0d..9b6e10bdd 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/span_processor.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/span_processor.py @@ -47,7 +47,7 @@ import threading import time from collections import defaultdict -from typing import Any, Dict, Optional, Tuple +from typing import Any, Dict, Mapping, Optional, Tuple from opentelemetry.context import Context from opentelemetry.metrics import ObservableGauge, get_meter @@ -72,6 +72,8 @@ GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, MAF_ATTR_RENAME_MAP, + MAF_LIVE_SPAN_MARKER, + MAF_PROVIDER_NAME, MAF_SPAN_NAME_PREFIXES, PROVIDER_NAME_NORMALIZE, GenAIOperation, @@ -94,11 +96,31 @@ _EDGE_GROUP_PROCESS = "edge_group.process" _LIVE_SPAN_MAX_AGE_NS = 60 * 1_000_000_000 _GEN_AI_TOOL_NAME = "gen_ai.tool.name" -_FRAMEWORK_PROVIDER_NAME = "microsoft.agent_framework" +_GEN_AI_INPUT_MESSAGES = "gen_ai.input.messages" +_GEN_AI_OUTPUT_MESSAGES = "gen_ai.output.messages" +_FRAMEWORK_PROVIDER_NAME = MAF_PROVIDER_NAME +_GEN_AI_SYSTEM = "gen_ai.system" +_MAF_LIVE_SPAN_MARKER = MAF_LIVE_SPAN_MARKER +_MAF_INTERNAL_NAME_PREFIXES = ( + _WORKFLOW_RUN, + _WORKFLOW_BUILD, + _MESSAGE_SEND, + _EXECUTOR_PROCESS, + _EDGE_GROUP_PROCESS, +) +_TOOL_CALL_FINISH_REASONS = frozenset( + {"tool_call", "tool_calls", "function_call", "function_calls"} +) +_AGENT_OUTPUT_ROLES = frozenset({"assistant", "ai", "model"}) +_AGENT_INTERMEDIATE_PART_TYPES = frozenset( + {"tool_call", "tool_call_response", "reasoning"} +) def _attr_value(span: Any, key: str) -> Any: """Read an attribute from a live Span or ReadableSpan, tolerating both.""" + if isinstance(span, Mapping): + return span.get(key) attrs = getattr(span, "_attributes", None) if attrs is not None: try: @@ -111,6 +133,70 @@ def _attr_value(span: Any, key: str) -> Any: return None +def _attr_values(value: Any) -> tuple[str, ...]: + if value is None: + return () + if isinstance(value, (list, tuple)): + values = value + else: + values = (value,) + return tuple(str(item).lower() for item in values if item is not None) + + +def _span_attrs(readable: Any) -> Mapping[Any, Any]: + if isinstance(readable, Mapping): + return readable + attrs = getattr(readable, "_attributes", None) + if attrs is not None: + return attrs + attrs = getattr(readable, "attributes", None) + if attrs is not None: + return attrs + return {} + + +def _has_live_maf_marker(live: Any | None) -> bool: + if live is None: + return False + if isinstance(live, Mapping): + return live.get(_MAF_LIVE_SPAN_MARKER) == _FRAMEWORK_PROVIDER_NAME + return ( + getattr(live, _MAF_LIVE_SPAN_MARKER, None) == _FRAMEWORK_PROVIDER_NAME + ) + + +def _scope_name(span: Any) -> str: + for attr in ("instrumentation_scope", "instrumentation_library"): + scope = getattr(span, attr, None) + name = getattr(scope, "name", None) + if name: + return str(name).lower() + return "" + + +def _has_maf_scope(readable: Any, live: Any | None = None) -> bool: + return any( + "agent_framework" in _scope_name(span) + or "microsoft_agent_framework" in _scope_name(span) + for span in (readable, live) + if span is not None + ) + + +def _has_maf_provider_marker(readable: Any) -> bool: + for key in (_GEN_AI_SYSTEM, GEN_AI_PROVIDER_NAME): + if _FRAMEWORK_PROVIDER_NAME in _attr_values( + _attr_value(readable, key) + ): + return True + return False + + +def _has_maf_private_marker(readable: Any) -> bool: + attrs = _span_attrs(readable) + return any(key in attrs for key in MAF_ATTR_RENAME_MAP) + + def _safe_dumps(obj: Any) -> Optional[str]: """Serialize ``obj`` to a JSON string capped at 4 KB. @@ -182,13 +268,46 @@ def _set_attr(live_span: OtelSpan, key: str, value: Any) -> None: try: if lock is not None: with lock: - attrs[key] = coerced + _set_attr_value(attrs, key, coerced) else: - attrs[key] = coerced + _set_attr_value(attrs, key, coerced) except Exception as exc: # pragma: no cover - defensive logger.debug("set_attribute(%s) failed: %s", key, exc) +def _set_attr_value(attrs: Any, key: str, value: Any) -> None: + try: + attrs[key] = value + return + except TypeError: + pass + backing_dict = getattr(attrs, "_dict", None) + if backing_dict is not None: + backing_dict[key] = value + + +def _set_attr_on_both( + live_span: OtelSpan, readable: Any, key: str, value: Any +) -> None: + _set_attr(live_span, key, value) + _set_attr(readable, key, value) + + +def _delete_attr(span: Any, key: str) -> None: + attrs = getattr(span, "_attributes", None) + if attrs is None: + return + lock = getattr(span, "_lock", None) + try: + if lock is not None: + with lock: + attrs.pop(key, None) + else: + attrs.pop(key, None) + except Exception as exc: # pragma: no cover - defensive + logger.debug("delete_attribute(%s) failed: %s", key, exc) + + def _rename_maf_attrs(live_span: OtelSpan, readable: Any) -> list[str]: """Rename MAF-private attributes to ``gen_ai.*`` canonical keys. @@ -214,7 +333,7 @@ def _rename_maf_attrs(live_span: OtelSpan, readable: Any) -> list[str]: continue if not present: continue - _set_attr(live_span, new_key, value) + _set_attr_on_both(live_span, readable, new_key, value) renamed.append(new_key) # best-effort removal of the old (private) key try: @@ -225,11 +344,14 @@ def _rename_maf_attrs(live_span: OtelSpan, readable: Any) -> list[str]: attrs.pop(old_key, None) except Exception: pass + _delete_attr(readable, old_key) else: # No live attrs; fall back to readable.attributes (read-only) readable_attrs = getattr(readable, "attributes", None) or {} if old_key in readable_attrs: - _set_attr(live_span, new_key, readable_attrs[old_key]) + _set_attr_on_both( + live_span, readable, new_key, readable_attrs[old_key] + ) renamed.append(new_key) return renamed @@ -241,7 +363,7 @@ def _copy_maf_attrs(live_span: OtelSpan, readable: Any) -> list[str]: value = _attr_value(readable, old_key) if value is None: continue - _set_attr(live_span, new_key, value) + _set_attr_on_both(live_span, readable, new_key, value) copied.append(new_key) return copied @@ -278,6 +400,18 @@ def _normalize_provider(value: Any) -> Optional[str]: def _normalize_finish_reasons(live_span: OtelSpan, readable: Any) -> None: """Normalize JSON-encoded finish reasons to an OTel string array.""" value = _attr_value(readable, GEN_AI_RESPONSE_FINISH_REASONS) + if isinstance(value, (list, tuple)) and all( + isinstance(item, str) for item in value + ): + normalized = [_normalize_finish_reason_value(item) for item in value] + if list(value) != normalized: + _set_attr_on_both( + live_span, + readable, + GEN_AI_RESPONSE_FINISH_REASONS, + normalized, + ) + return if not isinstance(value, str): return try: @@ -287,7 +421,198 @@ def _normalize_finish_reasons(live_span: OtelSpan, readable: Any) -> None: if isinstance(parsed, list) and all( isinstance(item, str) for item in parsed ): - _set_attr(live_span, GEN_AI_RESPONSE_FINISH_REASONS, parsed) + parsed = [_normalize_finish_reason_value(item) for item in parsed] + _set_attr_on_both( + live_span, readable, GEN_AI_RESPONSE_FINISH_REASONS, parsed + ) + + +def _normalize_input_messages( + live_span: OtelSpan, readable: Any, *, agent_boundary: bool = False +) -> None: + if not agent_boundary: + return + handled, normalized = _agent_boundary_input_messages_value( + _attr_value(readable, _GEN_AI_INPUT_MESSAGES) + ) + if not handled: + return + if normalized is None: + _delete_attr(live_span, _GEN_AI_INPUT_MESSAGES) + _delete_attr(readable, _GEN_AI_INPUT_MESSAGES) + else: + _set_attr_on_both( + live_span, readable, _GEN_AI_INPUT_MESSAGES, normalized + ) + + +def _normalize_output_messages( + live_span: OtelSpan, + readable: Any, + *, + agent_boundary: bool = False, +) -> None: + if agent_boundary: + handled, normalized = _agent_boundary_output_messages_value( + _attr_value(readable, _GEN_AI_OUTPUT_MESSAGES) + ) + if not handled: + return + if normalized is None: + _delete_attr(live_span, _GEN_AI_OUTPUT_MESSAGES) + _delete_attr(readable, _GEN_AI_OUTPUT_MESSAGES) + else: + _set_attr_on_both( + live_span, readable, _GEN_AI_OUTPUT_MESSAGES, normalized + ) + return + + normalized = _normalized_output_messages_value( + _attr_value(readable, _GEN_AI_OUTPUT_MESSAGES) + ) + if normalized is not None: + _set_attr_on_both( + live_span, readable, _GEN_AI_OUTPUT_MESSAGES, normalized + ) + + +def _normalized_output_messages_value(value: Any) -> Optional[str]: + if value is None: + return None + try: + messages = json.loads(value) if isinstance(value, str) else value + except (TypeError, ValueError): + return None + if not isinstance(messages, list): + return None + changed = False + normalized_messages = [] + for message in messages: + if not isinstance(message, dict): + normalized_messages.append(message) + continue + normalized = dict(message) + current = normalized.get("finish_reason") + default = _default_finish_reason_for_message(normalized) + finish_reason = _normalize_finish_reason_value( + current, default=default + ) + if current != finish_reason: + normalized["finish_reason"] = finish_reason + changed = True + normalized_messages.append(normalized) + if not changed and isinstance(value, str): + return None + try: + return json.dumps( + normalized_messages, ensure_ascii=False, separators=(",", ":") + ) + except (TypeError, ValueError): + return None + + +def _parse_message_list(value: Any) -> tuple[bool, list[Any]]: + if value is None: + return False, [] + try: + messages = json.loads(value) if isinstance(value, str) else value + except (TypeError, ValueError): + return False, [] + if not isinstance(messages, list): + return False, [] + return True, messages + + +def _agent_boundary_input_messages_value( + value: Any, +) -> tuple[bool, Optional[str]]: + handled, messages = _parse_message_list(value) + if not handled: + return False, None + normalized_messages = [] + for message in messages: + if not isinstance(message, dict): + continue + if str(message.get("role") or "").lower() != "user": + continue + normalized = _message_with_visible_parts(message) + if normalized is not None: + normalized_messages.append(normalized) + if not normalized_messages: + return True, None + return True, _dump_messages(normalized_messages) + + +def _agent_boundary_output_messages_value( + value: Any, +) -> tuple[bool, Optional[str]]: + handled, messages = _parse_message_list(value) + if not handled: + return False, None + for message in reversed(messages): + if not isinstance(message, dict): + continue + role = str(message.get("role") or "").lower() + if role not in _AGENT_OUTPUT_ROLES: + continue + normalized = _message_with_visible_parts(message) + if normalized is None: + continue + current = normalized.get("finish_reason") + normalized["finish_reason"] = _normalize_finish_reason_value( + current, default="stop" + ) + return True, _dump_messages([normalized]) + return True, None + + +def _message_with_visible_parts( + message: Mapping[Any, Any], +) -> Optional[dict[Any, Any]]: + parts = message.get("parts") + if not isinstance(parts, list): + return None + visible_parts = [] + for part in parts: + if isinstance(part, Mapping): + part_type = part.get("type") + if part_type in _AGENT_INTERMEDIATE_PART_TYPES: + continue + visible_parts.append(dict(part)) + else: + visible_parts.append(part) + if not visible_parts: + return None + normalized = dict(message) + normalized["parts"] = visible_parts + return normalized + + +def _dump_messages(messages: list[Any]) -> Optional[str]: + try: + return json.dumps(messages, ensure_ascii=False, separators=(",", ":")) + except (TypeError, ValueError): + return None + + +def _default_finish_reason_for_message(message: Mapping[Any, Any]) -> str: + parts = message.get("parts") + if isinstance(parts, list): + for part in parts: + if isinstance(part, Mapping) and part.get("type") == "tool_call": + return "tool_calls" + return "stop" + + +def _normalize_finish_reason_value( + value: Any, *, default: str = "stop" +) -> str: + if value is None or value == "": + return default + reason = str(value) + if reason in _TOOL_CALL_FINISH_REASONS: + return "tool_calls" + return reason def _set_span_kind(live_span: OtelSpan, readable: Any, kind: SpanKind) -> None: @@ -354,20 +679,30 @@ def _is_mcp_tool_call_span(name: str, readable: Any) -> bool: return name.startswith(f"{_MCP_TOOL_CALL_METHOD} ") -def _is_maf_span(name: str, operation: Optional[str], readable: Any) -> bool: +def _is_maf_span( + name: str, + _operation: Optional[str], + readable: Any, + live: Any | None = None, + *, + allow_name_prefix: bool = True, +) -> bool: """Return True when the span carries a Microsoft Agent Framework signal.""" if _is_mcp_span(readable) and not _is_mcp_tool_call_span(name, readable): return False - if operation: - return True - if _is_mcp_tool_call_span(name, readable): + if ( + _has_live_maf_marker(live) + or _has_live_maf_marker(readable) + or _has_maf_scope(readable, live) + ): return True - if name == _REACT_STEP_NAME: + if _has_maf_provider_marker(readable): return True - if any(name.startswith(prefix) for prefix in MAF_SPAN_NAME_PREFIXES): + if allow_name_prefix and any( + name.startswith(prefix) for prefix in _MAF_INTERNAL_NAME_PREFIXES + ): return True - attrs = getattr(readable, "attributes", None) or {} - return any(key in attrs for key in MAF_ATTR_RENAME_MAP) + return _has_maf_private_marker(readable) def _classify_span( @@ -741,7 +1076,12 @@ def on_start( with self._live_span_lock: self._live_spans[key] = span self._span_parents[key] = parent_id - self._apply_semantic_attributes(span, span, remove_private_attrs=True) + self._apply_semantic_attributes( + span, + span, + remove_private_attrs=True, + allow_name_prefix=False, + ) def on_end(self, span: Any) -> None: """Enrich a just-ended MAF span with ARMS GenAI semantic conventions.""" @@ -774,7 +1114,7 @@ def on_end(self, span: Any) -> None: if ttft is not None and not _attr_value( span, GEN_AI_RESPONSE_TTFT ): - _set_attr(live, GEN_AI_RESPONSE_TTFT, ttft) + _set_attr_on_both(live, span, GEN_AI_RESPONSE_TTFT, ttft) # 7) ENTRY detection: a root invoke_agent span with no parent becomes # the trace entry point. @@ -813,6 +1153,7 @@ def _apply_semantic_attributes( readable: Any, *, remove_private_attrs: bool, + allow_name_prefix: bool = True, ) -> Optional[Tuple[str, str]]: """Write GenAI semantic attributes while the span is still exportable. @@ -823,7 +1164,13 @@ def _apply_semantic_attributes( name = getattr(readable, "name", "") or getattr(live, "name", "") or "" existing_op = _attr_value(readable, GEN_AI_OPERATION_NAME) existing_op = existing_op if isinstance(existing_op, str) else None - if not _is_maf_span(name, existing_op, readable): + if not _is_maf_span( + name, + existing_op, + readable, + live, + allow_name_prefix=allow_name_prefix, + ): return None span_kind, op_name = _classify_span(name, existing_op, readable) @@ -844,7 +1191,7 @@ def _apply_semantic_attributes( existing_kind == GenAISpanKind.WORKFLOW and span_kind != GenAISpanKind.WORKFLOW ): - _set_attr(live, GEN_AI_SPAN_KIND, span_kind) + _set_attr_on_both(live, readable, GEN_AI_SPAN_KIND, span_kind) # 2) gen_ai.operation.name (set if missing or freshly derived for # workflow spans where MAF does not write it). For spans MAF @@ -855,16 +1202,16 @@ def _apply_semantic_attributes( # kinds whose operation.name we own (AGENT reclassification of # ``executor.process``). if not existing_op: - _set_attr(live, GEN_AI_OPERATION_NAME, op_name) + _set_attr_on_both(live, readable, GEN_AI_OPERATION_NAME, op_name) elif existing_op != op_name and span_kind == GenAISpanKind.AGENT: - _set_attr(live, GEN_AI_OPERATION_NAME, op_name) + _set_attr_on_both(live, readable, GEN_AI_OPERATION_NAME, op_name) if span_kind == GenAISpanKind.MCP and not _attr_value( readable, _GEN_AI_TOOL_NAME ): tool_name = _mcp_tool_name(name, readable) if tool_name: - _set_attr(live, _GEN_AI_TOOL_NAME, tool_name) + _set_attr_on_both(live, readable, _GEN_AI_TOOL_NAME, tool_name) # 3) Rename MAF private-prefix attributes if remove_private_attrs: @@ -876,7 +1223,7 @@ def _apply_semantic_attributes( provider = _attr_value(readable, GEN_AI_PROVIDER_NAME) normalized = _normalize_provider(provider) if normalized is not None and normalized != provider: - _set_attr(live, GEN_AI_PROVIDER_NAME, normalized) + _set_attr_on_both(live, readable, GEN_AI_PROVIDER_NAME, normalized) elif ( normalized is None and span_kind == GenAISpanKind.AGENT @@ -886,10 +1233,24 @@ def _apply_semantic_attributes( GenAIOperation.INVOKE_AGENT, } ): - _set_attr(live, GEN_AI_PROVIDER_NAME, _FRAMEWORK_PROVIDER_NAME) + _set_attr_on_both( + live, readable, GEN_AI_PROVIDER_NAME, _FRAMEWORK_PROVIDER_NAME + ) - # 5) Normalize finish reasons written by MAF as a JSON string. + # 5) Normalize finish reasons and content-capture messages. AGENT + # input/output is the user-visible boundary; intermediate ReAct/tool + # messages stay on child STEP/LLM/TOOL spans. _normalize_finish_reasons(live, readable) + agent_boundary = ( + span_kind == GenAISpanKind.AGENT + and op_name == GenAIOperation.INVOKE_AGENT + ) + _normalize_input_messages( + live, readable, agent_boundary=agent_boundary + ) + _normalize_output_messages( + live, readable, agent_boundary=agent_boundary + ) # 6) LLM/embedding spans should use CLIENT OTel span kind. if span_kind == GenAISpanKind.LLM: diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/util_genai_bridge.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/util_genai_bridge.py index b4257182d..c45493cde 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/util_genai_bridge.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/src/opentelemetry/instrumentation/microsoft_agent_framework/util_genai_bridge.py @@ -72,17 +72,23 @@ GEN_AI_SPAN_KIND, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, + MAF_LIVE_SPAN_MARKER, GenAIOperation, GenAISpanKind, ) from .span_processor import ( _FRAMEWORK_PROVIDER_NAME, + _agent_boundary_input_messages_value, + _agent_boundary_output_messages_value, _attr_value, _classify_span, + _delete_attr, _is_exception_event, _is_maf_span, _mcp_tool_name, + _normalize_finish_reason_value, _normalize_provider, + _normalized_output_messages_value, _ttft_from_events, ) @@ -101,6 +107,16 @@ _END_WRAPPED_ATTR = "_loongsuite_util_genai_end_wrapped" _STREAM_START_ATTR = "_loongsuite_util_genai_stream_start_s" _STREAM_FIRST_TOKEN_ATTR = "_loongsuite_util_genai_stream_first_token_s" +_MAF_BRIDGE_MARKER = {MAF_LIVE_SPAN_MARKER: _FRAMEWORK_PROVIDER_NAME} + + +def _mark_maf_live_span(span: OtelSpan | None) -> None: + if span is None: + return + try: + setattr(span, MAF_LIVE_SPAN_MARKER, _FRAMEWORK_PROVIDER_NAME) + except Exception: + pass def apply_util_genai_bridge() -> None: @@ -272,6 +288,7 @@ def _get_span( original, bridge_attrs, span_name_attribute ) with span_cm as span: + _mark_maf_live_span(span) try: yield span finally: @@ -290,6 +307,7 @@ def _start_streaming_span( span = _start_streaming_span_with_kind( original, bridge_attrs, span_name_attribute ) + _mark_maf_live_span(span) _mark_stream_start(span) _wrap_span_end(span) return span @@ -375,6 +393,7 @@ def _get_function_span( ) -> Generator[OtelSpan, Any, Any]: bridge_attrs = _prepare_start_attributes(attributes) with original(bridge_attrs) as span: + _mark_maf_live_span(span) try: yield span finally: @@ -399,6 +418,7 @@ def _create_mcp_client_span( if target: bridge_attrs.setdefault("gen_ai.tool.name", target) with original(method_name, target, bridge_attrs) as span: + _mark_maf_live_span(span) yield span return _create_mcp_client_span @@ -465,6 +485,7 @@ def _start_detached_span_with_kind( span = observability.get_tracer().start_span( f"{operation} {span_name}", kind=kind ) + _mark_maf_live_span(span) span.set_attributes(attributes) return span @@ -518,7 +539,10 @@ def _prepare_start_attributes(attributes: Mapping[Any, Any]) -> dict[str, Any]: op_name = _mapping_value(bridge_attrs, GEN_AI_OPERATION_NAME) span_name = _span_name_from_attributes(bridge_attrs) if not _is_maf_span( - span_name, op_name if isinstance(op_name, str) else None, bridge_attrs + span_name, + op_name if isinstance(op_name, str) else None, + bridge_attrs, + _MAF_BRIDGE_MARKER, ): return bridge_attrs span_kind, classified_op = _classify_span( @@ -607,6 +631,38 @@ def _set_common_live_attributes( finish_reasons = _finish_reasons(span) if finish_reasons: span.set_attribute(GEN_AI_RESPONSE_FINISH_REASONS, finish_reasons) + agent_boundary = ( + span_kind == GenAISpanKind.AGENT + and op_name == GenAIOperation.INVOKE_AGENT + ) + if agent_boundary: + handled_input, input_messages = _agent_boundary_input_messages_value( + _attr_value(span, "gen_ai.input.messages") + ) + if handled_input: + _set_or_delete_attr(span, "gen_ai.input.messages", input_messages) + handled_output, output_messages = ( + _agent_boundary_output_messages_value( + _attr_value(span, "gen_ai.output.messages") + ) + ) + if handled_output: + _set_or_delete_attr( + span, "gen_ai.output.messages", output_messages + ) + else: + output_messages = _normalized_output_messages_value( + _attr_value(span, "gen_ai.output.messages") + ) + if output_messages is not None: + span.set_attribute("gen_ai.output.messages", output_messages) + + +def _set_or_delete_attr(span: OtelSpan, key: str, value: Any | None) -> None: + if value is None: + _delete_attr(span, key) + else: + span.set_attribute(key, value) def _llm_invocation(span: OtelSpan, op_name: str) -> LLMInvocation: @@ -772,12 +828,12 @@ def _finish_reasons(span: Any) -> Optional[list[str]]: if isinstance(parsed, list) and all( isinstance(item, str) for item in parsed ): - return parsed - return [value] + return [_normalize_finish_reason_value(item) for item in parsed] + return [_normalize_finish_reason_value(value)] if isinstance(value, (list, tuple)) and all( isinstance(item, str) for item in value ): - return list(value) + return [_normalize_finish_reason_value(item) for item in value] return None diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_processor.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_processor.py index 265374f74..1b1822f12 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_processor.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_processor.py @@ -26,6 +26,7 @@ from __future__ import annotations +import json import time from opentelemetry.instrumentation.microsoft_agent_framework.semantic_conventions import ( @@ -36,6 +37,8 @@ GEN_AI_SPAN_KIND, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, + MAF_LIVE_SPAN_MARKER, + MAF_PROVIDER_NAME, GenAIOperation, GenAISpanKind, ) @@ -85,9 +88,14 @@ def _flush(exporter): return exporter.get_finished_spans() +def _mark_maf_span(span): + setattr(span, MAF_LIVE_SPAN_MARKER, MAF_PROVIDER_NAME) + + def test_llm_span_gets_llm_kind_and_chat_operation(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") span.set_attribute("gen_ai.request.model", "gpt-4o") @@ -102,9 +110,27 @@ def test_llm_span_gets_llm_kind_and_chat_operation(): assert s.status.status_code == StatusCode.UNSET +def test_live_marker_set_after_start_is_visible_to_exporter_snapshot(): + tp, tracer, exporter, _ = _setup() + with tracer.start_as_current_span("chat gpt-4o") as span: + # The MAF bridge marks live spans after the SDK has called + # SpanProcessor.on_start. on_end enrichments must update the + # ReadableSpan snapshot too, otherwise downstream exporters on newer + # SDKs will not see the fields. + _mark_maf_span(span) + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) + span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") + span.set_attribute("gen_ai.request.model", "gpt-4o") + + spans = _flush(exporter) + assert spans[0].attributes.get(GEN_AI_SPAN_KIND) == GenAISpanKind.LLM + assert spans[0].kind == SpanKind.CLIENT + + def test_tool_span_gets_tool_kind(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("execute_tool get_weather") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.EXECUTE_TOOL) span.set_attribute("gen_ai.tool.name", "get_weather") spans = _flush(exporter) @@ -116,6 +142,7 @@ def test_embedding_span(): with tracer.start_as_current_span( "embeddings text-embedding-3-small" ) as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.EMBEDDINGS) span.set_attribute("gen_ai.request.model", "text-embedding-3-small") spans = _flush(exporter) @@ -125,6 +152,7 @@ def test_embedding_span(): def test_agent_span(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("invoke_agent my-agent") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.INVOKE_AGENT) span.set_attribute("gen_ai.agent.name", "my-agent") spans = _flush(exporter) @@ -238,6 +266,7 @@ def test_message_send_span(): def test_provider_normalization_azure_openai_to_openai(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute(GEN_AI_PROVIDER_NAME, "azure_openai") spans = _flush(exporter) @@ -247,6 +276,7 @@ def test_provider_normalization_azure_openai_to_openai(): def test_ttft_backfill_from_first_event(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") # Emit a streaming-chunk event a bit after start. @@ -264,6 +294,7 @@ def test_ttft_backfill_from_first_event(): def test_ttft_backfill_skips_exception_event(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") span.add_event("exception", {"exception.type": "RuntimeError"}) @@ -274,10 +305,161 @@ def test_ttft_backfill_skips_exception_event(): def test_finish_reasons_json_string_normalized_to_array(): tp, tracer, exporter, _ = _setup() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) - span.set_attribute(GEN_AI_RESPONSE_FINISH_REASONS, '["stop"]') + span.set_attribute(GEN_AI_RESPONSE_FINISH_REASONS, '["tool_call"]') spans = _flush(exporter) - assert spans[0].attributes.get(GEN_AI_RESPONSE_FINISH_REASONS) == ("stop",) + assert spans[0].attributes.get(GEN_AI_RESPONSE_FINISH_REASONS) == ( + "tool_calls", + ) + + +def test_output_messages_finish_reason_added_for_agent_span(): + tp, tracer, exporter, _ = _setup() + with tracer.start_as_current_span("invoke_agent planner") as span: + _mark_maf_span(span) + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.INVOKE_AGENT) + span.set_attribute( + "gen_ai.output.messages", + json.dumps( + [ + { + "role": "assistant", + "parts": [{"type": "text", "content": "done"}], + } + ] + ), + ) + [exported] = _flush(exporter) + messages = json.loads(exported.attributes["gen_ai.output.messages"]) + assert messages[0]["finish_reason"] == "stop" + + +def test_agent_input_output_boundary_filters_intermediate_messages(): + tp, tracer, exporter, _ = _setup() + with tracer.start_as_current_span("invoke_agent planner") as span: + _mark_maf_span(span) + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.INVOKE_AGENT) + span.set_attribute( + "gen_ai.input.messages", + json.dumps( + [ + { + "role": "system", + "parts": [{"type": "text", "content": "system"}], + }, + { + "role": "user", + "parts": [{"type": "text", "content": "weather?"}], + }, + { + "role": "assistant", + "parts": [ + { + "type": "tool_call", + "id": "call-1", + "name": "lookup", + "arguments": {"city": "Hangzhou"}, + } + ], + }, + { + "role": "tool", + "parts": [ + { + "type": "tool_call_response", + "id": "call-1", + "response": "sunny", + } + ], + }, + ] + ), + ) + span.set_attribute( + "gen_ai.output.messages", + json.dumps( + [ + { + "role": "assistant", + "finish_reason": "tool_call", + "parts": [ + { + "type": "tool_call", + "id": "call-1", + "name": "lookup", + "arguments": {"city": "Hangzhou"}, + } + ], + }, + { + "role": "tool", + "parts": [ + { + "type": "tool_call_response", + "id": "call-1", + "response": "sunny", + } + ], + }, + { + "role": "assistant", + "parts": [ + { + "type": "reasoning", + "content": "hidden scratchpad", + }, + { + "type": "text", + "content": "Hangzhou is sunny.", + }, + ], + }, + ] + ), + ) + [exported] = _flush(exporter) + + input_messages = json.loads(exported.attributes["gen_ai.input.messages"]) + assert [message["role"] for message in input_messages] == ["user"] + assert input_messages[0]["parts"][0]["content"] == "weather?" + + output_messages = json.loads(exported.attributes["gen_ai.output.messages"]) + assert len(output_messages) == 1 + assert output_messages[0]["role"] == "assistant" + assert output_messages[0]["parts"] == [ + {"type": "text", "content": "Hangzhou is sunny."} + ] + assert output_messages[0]["finish_reason"] == "stop" + + +def test_output_messages_finish_reason_tool_call_is_normalized(): + tp, tracer, exporter, _ = _setup() + with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) + span.set_attribute( + "gen_ai.output.messages", + json.dumps( + [ + { + "role": "assistant", + "finish_reason": "tool_call", + "parts": [ + { + "type": "tool_call", + "id": "call-1", + "name": "lookup", + "arguments": {"q": "x"}, + } + ], + } + ] + ), + ) + [exported] = _flush(exporter) + messages = json.loads(exported.attributes["gen_ai.output.messages"]) + assert messages[0]["finish_reason"] == "tool_calls" def _setup_with_metrics(): @@ -297,6 +479,7 @@ def test_error_span_keeps_error_status_and_increments_error_counter(): tp, tracer, exporter, processor = _setup_with_metrics() try: with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") span.set_status(Status(StatusCode.ERROR, "boom")) @@ -318,6 +501,7 @@ def test_error_span_keeps_error_status_and_increments_error_counter(): def test_metrics_counters_incremented_on_llm_span(): tp, tracer, exporter, processor = _setup_with_metrics() with tracer.start_as_current_span("chat gpt-4o") as span: + _mark_maf_span(span) span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) span.set_attribute("gen_ai.request.model", "gpt-4o") span.set_attribute(GEN_AI_USAGE_INPUT_TOKENS, 5) @@ -340,11 +524,12 @@ def test_metrics_counters_incremented_on_llm_span(): def test_react_step_span_classification(): tp, tracer, exporter, _ = _setup() - with tracer.start_as_current_span("react step"): + with tracer.start_as_current_span("react step") as span: + _mark_maf_span(span) # When emitted by our react_step_patch, the handler sets # gen_ai.operation.name=react and gen_ai.span.kind=STEP itself. But - # if the processor sees a "react step" name without op set, it should - # classify it as STEP/react as a fallback. + # when a marked MAF span reaches the processor without op set, it + # should classify it as STEP/react. pass spans = _flush(exporter) s = spans[0] @@ -394,6 +579,52 @@ def test_non_maf_span_is_left_untouched(): assert not processor._counters.calls_count +def test_autogen_span_with_overlapping_agent_operation_is_left_untouched(): + tp, tracer, exporter, processor = _setup_with_metrics() + with tracer.start_as_current_span("invoke_agent assistant") as span: + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.INVOKE_AGENT) + span.set_attribute(GEN_AI_PROVIDER_NAME, "autogen") + spans = _flush(exporter) + s = spans[0] + assert s.attributes.get(GEN_AI_PROVIDER_NAME) == "autogen" + assert GEN_AI_SPAN_KIND not in s.attributes + assert not processor._counters.calls_count + + +def test_autogen_llm_span_with_private_marker_is_left_untouched(): + tp, tracer, exporter, processor = _setup_with_metrics() + with tracer.start_as_current_span("chat gpt-4o") as span: + span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.CHAT) + span.set_attribute(GEN_AI_PROVIDER_NAME, "openai") + setattr(span, "_loongsuite_autogen_framework", "autogen") + spans = _flush(exporter) + s = spans[0] + assert s.attributes.get(GEN_AI_PROVIDER_NAME) == "openai" + assert GEN_AI_SPAN_KIND not in s.attributes + assert "_loongsuite_autogen_framework" not in s.attributes + assert s.kind == SpanKind.INTERNAL + assert not processor._counters.calls_count + + +def test_foreign_agent_spans_are_left_untouched(): + tp, tracer, exporter, processor = _setup_with_metrics() + for provider_name in ("langchain", "agentscope"): + with tracer.start_as_current_span( + f"invoke_agent {provider_name}-agent" + ) as span: + span.set_attribute( + GEN_AI_OPERATION_NAME, GenAIOperation.INVOKE_AGENT + ) + span.set_attribute(GEN_AI_PROVIDER_NAME, provider_name) + span.set_attribute("gen_ai.agent.name", f"{provider_name}-agent") + + spans = _flush(exporter) + assert len(spans) == 2 + for span in spans: + assert GEN_AI_SPAN_KIND not in span.attributes + assert not processor._counters.calls_count + + def test_dict_attribute_is_serialized_via_gen_ai_json_dumps(): """Dict/list GenAI values are JSON-serialized before SDK export.""" from opentelemetry.instrumentation.microsoft_agent_framework import ( @@ -450,6 +681,7 @@ def test_mcp_tool_call_span_classified_as_mcp_execute_tool(): with tracer.start_as_current_span( "tools/call get_weather", kind=SpanKind.CLIENT ) as span: + _mark_maf_span(span) # MAF writes mcp.method.name (no gen_ai.operation.name). span.set_attribute("mcp.method.name", "tools/call") span.set_attribute("mcp.session.id", "sess-1") @@ -510,6 +742,7 @@ def test_mcp_tool_call_stays_mcp_when_maf_writes_execute_tool(): with tracer.start_as_current_span( "tools/call slow_summary", kind=SpanKind.CLIENT ) as span: + _mark_maf_span(span) # MAF writes both mcp.method.name AND gen_ai.operation.name=execute_tool. span.set_attribute("mcp.method.name", "tools/call") span.set_attribute(GEN_AI_OPERATION_NAME, GenAIOperation.EXECUTE_TOOL) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_react_step.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_react_step.py index dcd4b153f..49374e8ab 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_react_step.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_react_step.py @@ -278,17 +278,18 @@ class _ChatTelemetryLayer: _reset_extended_handler_singletons() react_step_patch.apply_react_step_patch(tracer_provider=None) - assert react_step_patch._applied is True - - # Call the wrapped method directly (no instance — staticmethod-style). - coro = _FunctionInvocationLayer.get_response("self-arg", "a", kw="v") - assert asyncio.iscoroutine(coro), ( - "FIL wrapper must return a coroutine so MAF can `await` it" - ) - result = asyncio.get_event_loop().run_until_complete(coro) - assert result[0] == "fil-ok" - - react_step_patch.revert_react_step_patch() + try: + assert react_step_patch._applied is True + + # Call the wrapped method directly (no instance — staticmethod-style). + coro = _FunctionInvocationLayer.get_response("self-arg", "a", kw="v") + assert asyncio.iscoroutine(coro), ( + "FIL wrapper must return a coroutine so MAF can `await` it" + ) + result = asyncio.run(coro) + assert result[0] == "fil-ok" + finally: + react_step_patch.revert_react_step_patch() def test_fil_wrapper_preserves_streaming_response_type(monkeypatch): @@ -350,11 +351,12 @@ class _ChatTelemetryLayer: _reset_extended_handler_singletons() react_step_patch.apply_react_step_patch(tracer_provider=None) - result = _FunctionInvocationLayer.get_response("self-arg", stream=True) - assert result is stream - assert not asyncio.iscoroutine(result) - - react_step_patch.revert_react_step_patch() + try: + result = _FunctionInvocationLayer.get_response("self-arg", stream=True) + assert result is stream + assert not asyncio.iscoroutine(result) + finally: + react_step_patch.revert_react_step_patch() def test_chat_wrapper_outside_loop_passes_through(monkeypatch): @@ -456,3 +458,86 @@ class _ChatTelemetryLayer: react_step_patch._maf_react_loop_active.reset(token) react_step_patch.revert_react_step_patch() + + +def test_react_step_scope_keeps_tool_under_planning_step(monkeypatch): + """A real MAF ReAct round runs tool calls after the planning chat returns. + + The step span must therefore remain current until the next planning chat + begins, otherwise the tool becomes a sibling of the step under the agent. + """ + import asyncio + import sys + import types + + tp = TracerProvider() + exporter = InMemorySpanExporter() + tp.add_span_processor(SimpleSpanProcessor(exporter)) + tracer = tp.get_tracer("fake-maf-react") + chat_calls = {"count": 0} + + async def _chat_get_response(self, *args, **kwargs): + chat_calls["count"] += 1 + with tracer.start_as_current_span("chat qwen-plus"): + finish_reason = "tool_call" if chat_calls["count"] == 1 else "stop" + message = types.SimpleNamespace(finish_reason=finish_reason) + return types.SimpleNamespace(messages=[message]) + + async def _fil_get_response(self, *args, **kwargs): + response = await _ChatTelemetryLayer.get_response(self) + with tracer.start_as_current_span("execute_tool get_weather"): + pass + return await _ChatTelemetryLayer.get_response(self, response) + + class _FunctionInvocationLayer: + get_response = staticmethod(_fil_get_response) + + class _ChatTelemetryLayer: + get_response = staticmethod(_chat_get_response) + + tools_mod = types.ModuleType("agent_framework._tools") + tools_mod.FunctionInvocationLayer = _FunctionInvocationLayer # type: ignore[attr-defined] + obs_mod = types.ModuleType("agent_framework.observability") + obs_mod.ChatTelemetryLayer = _ChatTelemetryLayer # type: ignore[attr-defined] + af_mod = types.ModuleType("agent_framework") + af_mod._tools = tools_mod # type: ignore[attr-defined] + af_mod.observability = obs_mod # type: ignore[attr-defined] + + monkeypatch.setitem(sys.modules, "agent_framework", af_mod) + monkeypatch.setitem(sys.modules, "agent_framework._tools", tools_mod) + monkeypatch.setitem(sys.modules, "agent_framework.observability", obs_mod) + + react_step_patch.revert_react_step_patch() + react_step_patch._applied = False + react_step_patch._original_fil_get_response = None + react_step_patch._original_chat_get_response = None + _reset_extended_handler_singletons() + + react_step_patch.apply_react_step_patch(tracer_provider=tp) + try: + + async def _run(): + with tracer.start_as_current_span("invoke_agent planner"): + await _FunctionInvocationLayer.get_response("self-arg") + + asyncio.run(_run()) + finally: + react_step_patch.revert_react_step_patch() + + spans = exporter.get_finished_spans() + by_name = {} + for span in spans: + by_name.setdefault(span.name, []).append(span) + [tool] = by_name["execute_tool get_weather"] + first_step = sorted( + by_name["react step"], key=lambda span: span.start_time or 0 + )[0] + first_chat = sorted( + by_name["chat qwen-plus"], key=lambda span: span.start_time or 0 + )[0] + + assert tool.parent.span_id == first_step.context.span_id + assert first_chat.parent.span_id == first_step.context.span_id + assert first_step.attributes.get("gen_ai.react.finish_reason") == ( + "tool_calls" + ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_util_genai_bridge.py b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_util_genai_bridge.py index c40e4cf5b..1d18e3730 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_util_genai_bridge.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/tests/test_util_genai_bridge.py @@ -23,6 +23,7 @@ import asyncio import contextlib +import json import sys import types @@ -325,6 +326,155 @@ def test_agent_span_gets_framework_provider_when_missing(monkeypatch): ) +def test_agent_output_messages_get_finish_reason_before_export(monkeypatch): + obs_mod, exporter = _install_fake_observability(monkeypatch) + util_genai_bridge.apply_util_genai_bridge() + try: + with obs_mod._get_span( + { + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + "gen_ai.agent.name": "planner", + "gen_ai.output.messages": json.dumps( + [ + { + "role": "assistant", + "parts": [{"type": "text", "content": "done"}], + } + ] + ), + }, + "gen_ai.agent.name", + ): + pass + finally: + util_genai_bridge.revert_util_genai_bridge() + + span = exporter.get_finished_spans()[0] + messages = json.loads(span.attributes["gen_ai.output.messages"]) + assert messages[0]["finish_reason"] == "stop" + + +def test_agent_boundary_messages_filtered_before_export(monkeypatch): + obs_mod, exporter = _install_fake_observability(monkeypatch) + util_genai_bridge.apply_util_genai_bridge() + try: + with obs_mod._get_span( + { + GEN_AI_OPERATION_NAME: GenAIOperation.INVOKE_AGENT, + "gen_ai.agent.name": "planner", + "gen_ai.input.messages": json.dumps( + [ + { + "role": "system", + "parts": [{"type": "text", "content": "system"}], + }, + { + "role": "user", + "parts": [{"type": "text", "content": "weather?"}], + }, + { + "role": "tool", + "parts": [ + { + "type": "tool_call_response", + "id": "call-1", + "response": "sunny", + } + ], + }, + ] + ), + "gen_ai.output.messages": json.dumps( + [ + { + "role": "assistant", + "finish_reason": "tool_call", + "parts": [ + { + "type": "tool_call", + "id": "call-1", + "name": "lookup", + "arguments": {"city": "Hangzhou"}, + } + ], + }, + { + "role": "assistant", + "parts": [ + { + "type": "reasoning", + "content": "hidden scratchpad", + }, + { + "type": "text", + "content": "Hangzhou is sunny.", + }, + ], + }, + ] + ), + }, + "gen_ai.agent.name", + ): + pass + finally: + util_genai_bridge.revert_util_genai_bridge() + + span = exporter.get_finished_spans()[0] + input_messages = json.loads(span.attributes["gen_ai.input.messages"]) + assert [message["role"] for message in input_messages] == ["user"] + assert input_messages[0]["parts"][0]["content"] == "weather?" + + output_messages = json.loads(span.attributes["gen_ai.output.messages"]) + assert output_messages == [ + { + "role": "assistant", + "parts": [{"type": "text", "content": "Hangzhou is sunny."}], + "finish_reason": "stop", + } + ] + + +def test_tool_call_finish_reason_is_normalized_before_export(monkeypatch): + obs_mod, exporter = _install_fake_observability(monkeypatch) + util_genai_bridge.apply_util_genai_bridge() + try: + with obs_mod._get_span( + { + GEN_AI_OPERATION_NAME: GenAIOperation.CHAT, + GEN_AI_REQUEST_MODEL: "qwen-plus", + GEN_AI_RESPONSE_FINISH_REASONS: '["tool_call"]', + "gen_ai.output.messages": json.dumps( + [ + { + "role": "assistant", + "finish_reason": "tool_call", + "parts": [ + { + "type": "tool_call", + "id": "call-1", + "name": "lookup", + "arguments": {"q": "x"}, + } + ], + } + ] + ), + }, + GEN_AI_REQUEST_MODEL, + ): + pass + finally: + util_genai_bridge.revert_util_genai_bridge() + + span = exporter.get_finished_spans()[0] + messages = json.loads(span.attributes["gen_ai.output.messages"]) + assert messages[0]["finish_reason"] == "tool_calls" + assert span.attributes.get(GEN_AI_RESPONSE_FINISH_REASONS) == ( + "tool_calls", + ) + + def test_mcp_span_is_seeded_before_export(monkeypatch): obs_mod, exporter = _install_fake_observability(monkeypatch) util_genai_bridge.apply_util_genai_bridge() diff --git a/tox-loongsuite.ini b/tox-loongsuite.ini index ab53b795d..6482b0196 100644 --- a/tox-loongsuite.ini +++ b/tox-loongsuite.ini @@ -45,6 +45,10 @@ envlist = py3{9,10,11,12,13}-test-loongsuite-instrumentation-langgraph-{oldest,latest} lint-loongsuite-instrumentation-langgraph + ; loongsuite-instrumentation-autogen + py3{10,11,12,13}-test-loongsuite-instrumentation-autogen + lint-loongsuite-instrumentation-autogen + ; loongsuite-instrumentation-deepagents py3{11,12,13}-test-loongsuite-instrumentation-deepagents-latest lint-loongsuite-instrumentation-deepagents @@ -188,6 +192,9 @@ deps = langgraph-latest: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-langgraph/tests/requirements.latest.txt lint-loongsuite-instrumentation-langgraph: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-langgraph/tests/requirements.oldest.txt + loongsuite-instrumentation-autogen: {[testenv]test_deps} + loongsuite-instrumentation-autogen: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-autogen/test-requirements.txt + deepagents-latest: {[testenv]test_deps} deepagents-latest: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-deepagents/tests/requirements.latest.txt lint-loongsuite-instrumentation-deepagents: {[testenv]test_deps} @@ -310,6 +317,9 @@ commands = test-loongsuite-instrumentation-langgraph: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-langgraph/tests {posargs} lint-loongsuite-instrumentation-langgraph: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-langgraph + test-loongsuite-instrumentation-autogen: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-autogen/tests {posargs} + lint-loongsuite-instrumentation-autogen: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-autogen + test-loongsuite-instrumentation-deepagents: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-deepagents/tests {posargs} lint-loongsuite-instrumentation-deepagents: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-deepagents