Repository navigation
ci(loongsuite): add Python 3.14 jobs and classifiers - #285
Conversation
Test the LoongSuite instrumentation packages and loongsuite-distro on Python 3.14, and add the Python 3.14 trove classifier to them. The regenerated loongsuite_test_0.yml gains the matching 37 jobs. CrewAI, OpenHands and QwenPaw stay on Python 3.13 and older: crewai, openhands-ai and qwenpaw declare Requires-Python <3.14. LangChain stays too: its tests pin langchain<1.0.0, and langchain 0.3.30's langchain.chains.base does not import on Python 3.14 (pydantic cannot evaluate the Chain annotations there). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN
There was a problem hiding this comment.
🟢 Approval recommended
The additive CI, metadata, and documentation changes are consistent, with matching test environments and no unresolved blocking issues.
No open issues 🎉
What changed in this PR
Extends Python 3.14 test coverage and compatibility metadata to eligible LoongSuite packages, aligning them with the upstream-derived packages without changing minimum Python versions.
Changes:
- Adds 37 Python 3.14 test environments and corresponding generated CI jobs.
- Adds Python 3.14 classifiers to 27 instrumentation packages and
loongsuite-distro. - Updates compatibility documentation and the changelog, retaining the documented exclusions for CrewAI, LangChain, OpenHands, and QwenPaw.
| File | Description |
|---|---|
tox-loongsuite.ini |
Adds eligible Python 3.14 test environments. |
loongsuite-distro/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-wildtool/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-widesearch/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-webarena/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-vita/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-terminus2/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-strands/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-slop-code/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-qwen-agent/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-minisweagent/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-microsoft-agent-framework/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-mem0/README.md |
Extends documented compatibility through Python 3.14. |
instrumentation-loongsuite/loongsuite-instrumentation-mem0/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-llama-index/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-litellm/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-langgraph/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-hermes-agent/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-google-genai/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-google-adk/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-deepagents/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-dashscope/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-claw-eval/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-claude-agent-sdk/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-bfclv4/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-autogen/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-algotune/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-agno/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-agentscope/pyproject.toml |
Adds Python 3.14 classifier. |
instrumentation-loongsuite/loongsuite-instrumentation-a2a/pyproject.toml |
Adds Python 3.14 classifier. |
CHANGELOG-loongsuite.md |
Records Python 3.14 support and exclusions. |
.github/workflows/loongsuite_test_0.yml |
Adds generated jobs matching the expanded tox matrix. |
Review effort: Balanced
When an application stops iterating an instrumented Agent.run(stream=True) or Agent.arun(stream=True) stream early (close(), aclose(), break, a client disconnect), the wrapper ended its own spans but never closed the Agno stream it was iterating. That stream and the generators under it, including the model-call wrapper with its attached LLM span context, stayed suspended. The wrapper's frame keeps the GeneratorExit in a local, and its traceback points back at the frame, so only the cyclic garbage collector frees them. Agno's own cleanup (the finally of _run_stream, the client-disconnect handling of _arun_stream) waited for the collector too. When the collector freed them, the model wrapper's finally ended the LLM span and reset the current OpenTelemetry context to its value from that old run, an already-ended "react step" span, in whatever code was running on that thread. In the new Python 3.14 CI job this happened in test_tool_call_loop_emits_react_steps_and_split_llm_spans, between starting the second ReAct step and starting its LLM span, so that LLM span got the stale span as its parent, in another trace. It is not specific to 3.14: collecting the same garbage at that point (gc.freeze() until then) gives the same failure on 3.13; 3.14's allocation pattern put CI's collection there. Close the Agno stream before ending the run's spans, so its cleanup runs when the stream is closed. On the sync path this also ends the model and step spans right away, in order. test_streaming_agent_span_finishes_when_consumer_breaks now checks that the model span has ended once close() returns, and a new async test checks that aclose() closes the wrapped stream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN
|
The two red crewai jobs (3.10 and 3.12) are unrelated to this PR: |
|
Thanks for the Python 3.14 coverage and the Agno fix! Please sync with the latest main to pick up #287. Once CI passes, we're happy to merge. We'll follow up on the remaining async lifecycle issue separately. |
Description
The upstream-derived packages in
tox.inialready run on Python 3.14, but the LoongSuite packages intox-loongsuite.inistop at 3.13. This addspy314to their test environments, regeneratesloongsuite_test_0.yml(tox -e generate-workflows, 37 new jobs), and adds the Python 3.14 classifier to the 27 instrumentation packages andloongsuite-distro, following the "Adding support for a new Python version" steps inCONTRIBUTING-loongsuite-zh.md. The mem0 README's compatibility line now says<= 3.14, andCHANGELOG-loongsuite.mdhas an entry. MCP and Dify have no test environments and are unchanged.Four packages stay on 3.13 and older:
crewai,openhands-aiandqwenpawall declareRequires-Python <3.14(the QwenPaw package itself does too).langchain<1.0.0, andimport langchain.chains.basefails on Python 3.14 with langchain 0.3.30 (the latest 0.3) because pydantic cannot evaluateChain's annotations (TypeError: 'function' object is not subscriptable). Moving those tests to LangChain 1.x is a separate change.Python 3.15 is left out: the shared workflow generator (
generate_workflows_lib) has nopy315alias yet, and upstream contrib hasn't added 3.15. The LoongSuite lint jobs (ruff) stay on 3.13, and the Python floor isn't touched.The second commit fixes an Agno instrumentation bug that the new 3.14 agno job exposed (
test_tool_call_loop_emits_react_steps_and_split_llm_spansfailed). When an application stops reading an instrumentedAgent.run(stream=True)orAgent.arun(stream=True)stream early, the wrapper ended its own spans but never closed the Agno stream it iterates. Those suspended generators, including the model-call wrapper with its attached LLM span context, were only freed later by the cyclic garbage collector. Itsfinallythen reset the current OpenTelemetry context to an ended span of the closed run, in whatever code was running. In the 3.14 job that happened inside the next sync test, so its second LLM span got a parent from another trace. Collecting the same garbage at that point fails the same way on 3.13; 3.14's allocation pattern put CI's collection there. The fix closes the Agno stream before the wrapper ends its spans (_run_stream,_arun_stream).test_streaming_agent_span_finishes_when_consumer_breaksnow checks that the model span has ended onceclose()returns, a new test checks thataclose()closes the wrapped stream, and the agnoCHANGELOG.mdhas an entry.Type of change
How Has This Been Tested?
Each new environment run as CI runs it,
tox -c tox-loongsuite.ini -e <env> -- -rawith tox-uv, on CPython 3.14.7 (Linux x86_64). All 37 pass:Results
py314-test-loongsuite-instrumentation-…)agentscope-oldestagentscope-latestdashscope-oldestdashscope-latestclaude-agent-sdk-oldestclaude-agent-sdk-latestgoogle-adk-oldestgoogle-adk-latestgoogle-genai-oldestgoogle-genai-latestagnolanggraph-oldestlanggraph-latestautogendeepagents-latestmicrosoft-agent-frameworkstrands-oldeststrands-latestqwen-agent-oldestqwen-agent-latesthermes-agentmem0-oldestmem0-latestlitellma2allama-indexalgotunebfclv4claw-evalminisweagentslop-codeterminus2vitawebarenawidesearchwildtoolpy314-test-loongsuite-distroThe oldest versions are unchanged; as a check,
py39-test-loongsuite-distro,py39-test-loongsuite-instrumentation-dashscope-oldest,py310-test-loongsuite-instrumentation-a2aandpy310-test-loongsuite-instrumentation-google-adk-oldeststill pass.tox -e generate-workflowsis clean after the change, andcheck-license-headerpasses.For the agno fix, the agno env was also run as CI runs it on GitHub's own CPython builds (the ones
setup-pythoninstalls) with the CI job's exactpip freeze(agno==2.9.0): 37 passed on 3.14.6 and 3.13.14 (10 runs each) and on 3.9.25, andlint-loongsuite-instrumentation-agnoandtox -e precommitpass. To check the cause, a throwaway pytest plugin collected the garbage left bytest_streaming_agent_span_finishes_when_consumer_breaks(kept alive withgc.freeze()) inside the tool-loop test's second LLM call: before the fix this reproduces the CI assertion on both 3.14.6 and 3.13.14, and with the fix that run passes. Over 161 runs with differentgc.set_threshold()values, the abandoned stream was finalized late by the collector in 160 runs before the fix (one of them failing the same test on 3.14.6) and in none after it.Does This PR Require a Core Repo Change?
Checklist:
🤖 Generated with Claude Code
https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN