Skip to content

ci(loongsuite): add Python 3.14 jobs and classifiers - #285

Merged
ralf0131 merged 3 commits into
alibaba:mainfrom
pylaterreur:add-python-3.14
Oct 28, 2026
Merged

ralf0131 merged 3 commits into
alibaba:mainfrom
pylaterreur:add-python-3.14

Conversation

@pylaterreur

@pylaterreur pylaterreur commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Description

The upstream-derived packages in tox.ini already run on Python 3.14, but the LoongSuite packages in tox-loongsuite.ini stop at 3.13. This adds py314 to their test environments, regenerates loongsuite_test_0.yml (tox -e generate-workflows, 37 new jobs), and adds the Python 3.14 classifier to the 27 instrumentation packages and loongsuite-distro, following the "Adding support for a new Python version" steps in CONTRIBUTING-loongsuite-zh.md. The mem0 README's compatibility line now says <= 3.14, and CHANGELOG-loongsuite.md has an entry. MCP and Dify have no test environments and are unchanged.

Four packages stay on 3.13 and older:

  • CrewAI, OpenHands, QwenPaw: crewai, openhands-ai and qwenpaw all declare Requires-Python <3.14 (the QwenPaw package itself does too).
  • LangChain: the tests pin langchain<1.0.0, and import langchain.chains.base fails on Python 3.14 with langchain 0.3.30 (the latest 0.3) because pydantic cannot evaluate Chain'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 no py315 alias 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_spans failed). When an application stops reading an instrumented Agent.run(stream=True) or Agent.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. Its finally then 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_breaks now checks that the model span has ended once close() returns, a new test checks that aclose() closes the wrapped stream, and the agno CHANGELOG.md has an entry.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Each new environment run as CI runs it, tox -c tox-loongsuite.ini -e <env> -- -ra with tox-uv, on CPython 3.14.7 (Linux x86_64). All 37 pass:

Results
Environment (py314-test-loongsuite-instrumentation-…) Result
agentscope-oldest 106 passed
agentscope-latest 49 passed
dashscope-oldest 52 passed, 4 skipped
dashscope-latest 52 passed, 4 skipped
claude-agent-sdk-oldest 84 passed, 9 skipped
claude-agent-sdk-latest 84 passed, 9 skipped
google-adk-oldest 24 passed
google-adk-latest 24 passed
google-genai-oldest 182 passed, 141 skipped
google-genai-latest 226 passed, 97 skipped
agno 37 passed
langgraph-oldest 16 passed
langgraph-latest 16 passed
autogen 36 passed
deepagents-latest 11 passed
microsoft-agent-framework 72 passed
strands-oldest 35 passed, 2 skipped
strands-latest 37 passed
qwen-agent-oldest 45 passed
qwen-agent-latest 45 passed
hermes-agent 36 passed, 2 skipped
mem0-oldest 138 passed
mem0-latest 138 passed
litellm 67 passed
a2a 20 passed
llama-index 47 passed
algotune 264 passed
bfclv4 179 passed
claw-eval 169 passed
minisweagent 168 passed
slop-code 61 passed
terminus2 85 passed
vita 39 passed
webarena 151 passed
widesearch 67 passed
wildtool 117 passed
py314-test-loongsuite-distro 12 passed

The oldest versions are unchanged; as a check, py39-test-loongsuite-distro, py39-test-loongsuite-instrumentation-dashscope-oldest, py310-test-loongsuite-instrumentation-a2a and py310-test-loongsuite-instrumentation-google-adk-oldest still pass. tox -e generate-workflows is clean after the change, and check-license-header passes.

For the agno fix, the agno env was also run as CI runs it on GitHub's own CPython builds (the ones setup-python installs) with the CI job's exact pip freeze (agno==2.9.0): 37 passed on 3.14.6 and 3.13.14 (10 runs each) and on 3.9.25, and lint-loongsuite-instrumentation-agno and tox -e precommit pass. To check the cause, a throwaway pytest plugin collected the garbage left by test_streaming_agent_span_finishes_when_consumer_breaks (kept alive with gc.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 different gc.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?

  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

🤖 Generated with Claude Code

https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor Author

The two red crewai jobs (3.10 and 3.12) are unrelated to this PR: test_tool_calls.py::TestToolCalls::test_agent_with_multiple_tools failed with litellm.InternalServerError: OpenAIException - Connection error, i.e. the test reached the network. The same jobs passed on this PR's first push, and the second commit only touches the agno instrumentation. A re-run of those jobs should pass.

@sipercai

Copy link
Copy Markdown
Collaborator

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.

@ralf0131
ralf0131 merged commit 243bd6e into alibaba:main Oct 28, 2026
278 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants