Summary
Every agent-framework dependency is declared floor-only (>=X, no ceiling), so conductor-python[agents] accepts any future major version of langgraph, openai, anthropic, and friends. The e2e bundle's own test deps are fully unpinned. A breaking upstream release therefore reaches users — and downstream CI lanes — with no change to this repo, and presents as an SDK or server regression to whoever triages it.
Where it comes from
Two places, both in this repo:
1. pyproject.toml — the agents extra
langchain = { version = ">=1.2.13", optional = true }
langchain-core = { version = ">=1.2.20", optional = true }
langchain-openai= { version = ">=1.1.11", optional = true }
langgraph = { version = ">=1.1.3", optional = true }
google-adk = { version = ">=1.27.1", optional = true }
openai = { version = ">=2.28.0", optional = true }
openai-agents = { version = ">=0.12.2", optional = true }
anthropic = { version = ">=0.91.0", optional = true }
claude-code-sdk = { version = ">=0.0.25", optional = true }
2. scripts/package-e2e-bundle.sh — the heredoc that writes the bundle's requirements.txt
pytest
pytest-asyncio
pytest-xdist
pytest-rerunfailures
mcp-testkit
The bundle's run.sh does pip install -r requirements.txt at run time, so a consumer resolves "whatever is newest the day their lane happens to run."
Why this matters downstream
conductor-oss/conductor#1351 adds a gating CI lane that downloads the conductor-ai-e2e-python-* bundle and runs it against a from-source server. Because the bundle resolves its deps at run time, an unrelated upstream release can redden that gate. The failure looks like a server regression, which is the expensive part — the first hours go into looking for a Conductor bug that isn't there.
This is not hypothetical. A langgraph/pydantic interaction with typing.TypedDict already fails test_suite11_langgraph.py::test_messages_state_detection on Python < 3.12:
PydanticUserError: Please use `typing_extensions.TypedDict` instead of
`typing.TypedDict` on Python < 3.12
graph.get_input_jsonschema() raises, conductor/ai/agents/frameworks/langgraph.py swallows it in a bare except Exception, _input_is_messages is never set, and the assertion fails. Only the interpreter pin (3.12) is keeping that green today, not a dependency bound.
Proposed fix — bounds, not a lockfile
This is a library, so ranges are right and a committed lockfile would over-constrain consumers. Add next-major ceilings:
| Package |
From |
To |
langchain |
>=1.2.13 |
>=1.2.13,<2 |
langchain-core |
>=1.2.20 |
>=1.2.20,<2 |
langchain-openai |
>=1.1.11 |
>=1.1.11,<2 |
langgraph |
>=1.1.3 |
>=1.1.3,<2 |
google-adk |
>=1.27.1 |
>=1.27.1,<3 |
openai |
>=2.28.0 |
>=2.28.0,<3 |
openai-agents |
>=0.12.2 |
>=0.12.2,<0.13 |
anthropic |
>=0.91.0 |
>=0.91.0,<1 |
claude-code-sdk |
>=0.0.25 |
>=0.0.25,<0.1 |
and in the bundle heredoc: pytest>=8,<10, pytest-asyncio>=1,<2, pytest-xdist>=3,<4, pytest-rerunfailures>=16,<17, mcp-testkit>=1,<2.
Verified: 99 packages resolve cleanly under these bounds (uv pip compile --universal --python-version 3.12), and every capped package lands on the version already installed in a known-good environment — langgraph 1.2.10, anthropic 0.120.2, pytest 9.1.1, mcp-testkit 1.0.3. No cap excludes anything currently in use, so this is a no-op today and only takes effect on a future major.
Open questions for whoever picks this up
- 0.x policy.
anthropic, openai-agents and claude-code-sdk are pre-1.0, where minors are breaking by convention. anthropic>=0.91.0,<1 is loose enough to be nearly no protection given their cadence; <0.121 would be real but needs frequent bumping. The table above is deliberately inconsistent on this point — worth settling it rather than copying.
- Cost of caps. Ceilings can block a consumer who legitimately needs a newer langgraph, and over-capping is a well-known source of resolution pain in Poetry libraries.
<next-major is the mainstream compromise, but it is a trade.
- Alternative considered and rejected: generating a lock inside
package-e2e-bundle.sh. That script documents being static — "no install, no network — the pinned version does not have to be on PyPI yet, so this can run before the publish job finishes" — and compiling a lock would need both, breaking release ordering.
Unrelated finding, same area
mcp-testkit requires Python >= 3.11, but the bundle's README.md and run.sh both advertise 3.10–3.13. Compiling the requirements at 3.10 is unsatisfiable:
The `requires-python` value (>=3.10) includes Python versions that are not
supported by your dependencies (e.g., all versions of mcp-testkit only
supports >=3.11)
Either the floor should say 3.11 or mcp-testkit should be conditional.
Happy to raise the PR if the direction and the 0.x policy are agreed — the change is ~14 lines across the two files.
Summary
Every agent-framework dependency is declared floor-only (
>=X, no ceiling), soconductor-python[agents]accepts any future major version of langgraph, openai, anthropic, and friends. The e2e bundle's own test deps are fully unpinned. A breaking upstream release therefore reaches users — and downstream CI lanes — with no change to this repo, and presents as an SDK or server regression to whoever triages it.Where it comes from
Two places, both in this repo:
1.
pyproject.toml— theagentsextra2.
scripts/package-e2e-bundle.sh— the heredoc that writes the bundle'srequirements.txtThe bundle's
run.shdoespip install -r requirements.txtat run time, so a consumer resolves "whatever is newest the day their lane happens to run."Why this matters downstream
conductor-oss/conductor#1351 adds a gating CI lane that downloads the
conductor-ai-e2e-python-*bundle and runs it against a from-source server. Because the bundle resolves its deps at run time, an unrelated upstream release can redden that gate. The failure looks like a server regression, which is the expensive part — the first hours go into looking for a Conductor bug that isn't there.This is not hypothetical. A langgraph/pydantic interaction with
typing.TypedDictalready failstest_suite11_langgraph.py::test_messages_state_detectionon Python < 3.12:graph.get_input_jsonschema()raises,conductor/ai/agents/frameworks/langgraph.pyswallows it in a bareexcept Exception,_input_is_messagesis never set, and the assertion fails. Only the interpreter pin (3.12) is keeping that green today, not a dependency bound.Proposed fix — bounds, not a lockfile
This is a library, so ranges are right and a committed lockfile would over-constrain consumers. Add next-major ceilings:
langchain>=1.2.13>=1.2.13,<2langchain-core>=1.2.20>=1.2.20,<2langchain-openai>=1.1.11>=1.1.11,<2langgraph>=1.1.3>=1.1.3,<2google-adk>=1.27.1>=1.27.1,<3openai>=2.28.0>=2.28.0,<3openai-agents>=0.12.2>=0.12.2,<0.13anthropic>=0.91.0>=0.91.0,<1claude-code-sdk>=0.0.25>=0.0.25,<0.1and in the bundle heredoc:
pytest>=8,<10,pytest-asyncio>=1,<2,pytest-xdist>=3,<4,pytest-rerunfailures>=16,<17,mcp-testkit>=1,<2.Verified: 99 packages resolve cleanly under these bounds (
uv pip compile --universal --python-version 3.12), and every capped package lands on the version already installed in a known-good environment —langgraph 1.2.10,anthropic 0.120.2,pytest 9.1.1,mcp-testkit 1.0.3. No cap excludes anything currently in use, so this is a no-op today and only takes effect on a future major.Open questions for whoever picks this up
anthropic,openai-agentsandclaude-code-sdkare pre-1.0, where minors are breaking by convention.anthropic>=0.91.0,<1is loose enough to be nearly no protection given their cadence;<0.121would be real but needs frequent bumping. The table above is deliberately inconsistent on this point — worth settling it rather than copying.<next-majoris the mainstream compromise, but it is a trade.package-e2e-bundle.sh. That script documents being static — "no install, no network — the pinned version does not have to be on PyPI yet, so this can run before the publish job finishes" — and compiling a lock would need both, breaking release ordering.Unrelated finding, same area
mcp-testkitrequires Python >= 3.11, but the bundle'sREADME.mdandrun.shboth advertise 3.10–3.13. Compiling the requirements at 3.10 is unsatisfiable:Either the floor should say 3.11 or
mcp-testkitshould be conditional.Happy to raise the PR if the direction and the 0.x policy are agreed — the change is ~14 lines across the two files.