Skip to content

chore: minimise autonomy's runtime dependency footprint#2477

Merged
DavidMinarsch merged 38 commits intomainfrom
chore/dependency-cleanup-clean
Apr 20, 2026
Merged

chore: minimise autonomy's runtime dependency footprint#2477
DavidMinarsch merged 38 commits intomainfrom
chore/dependency-cleanup-clean

Conversation

@DavidMinarsch
Copy link
Copy Markdown
Contributor

@DavidMinarsch DavidMinarsch commented Apr 18, 2026

Summary

  • Reduce open-autonomy's direct runtime dep declarations to the true minimum (open-aea[all]==2.2.1 + open-aea-cli-ipfs==2.2.1 as the only hard base deps; [chain], [docker], [hwi] as opt-in extras).
  • Replace multiple third-party libs with open-aea helpers (2.2.1) or small stdlib-only inlines.
  • Sweep every packages/valory/** manifest so each dependencies: block reflects only the direct imports of that package (runtime + tests scanned by the AEA dep checker).
  • Clean up the pyproject↔tox.ini drift so tox -e check-dependencies passes and every declared entry matches an actual import somewhere.

Install matrix after this PR

Install command chain ops docker-compose deploy HWI
pip install open-autonomy
pip install open-autonomy[all]
pip install open-autonomy[chain]
pip install open-autonomy[docker]
pip install open-autonomy[hwi]

[hwi] and [docker] are intentionally excluded from [all]:

  • [hwi] — transitive hidapi+Pillow chain has no armv7 wheels, breaking multi-platform Docker builds.
  • [docker] — only needed by docker-compose deploys and the autonomy develop command.

What changed

autonomy/ framework — third-party → stdlib / open-aea helpers

  1. use open-aea helpers for requests/jsonschema — swap to aea.helpers.http_requests + aea.helpers.json_schema; drop multiaddr (was unused).
  2. drop texttable, inline a small table renderer — ~20-line ASCII renderer replaces single-call usage.
  3. catch requests.ConnectionError on web3 chain paths — lazy get_requests_connection_error() in autonomy/chain/exceptions.py resolves it at call time and raises a clear install hint if the Ethereum ledger plugin is absent.
  4. align pyproject.toml with setup.py, add [chain] extra — strip drift. Test-only deps move to poetry dev group.
  5. drop python-dotenvaea.helpers.base.load_env_file.
  6. drop typing_extensions and aiohttp from autonomy/ — stdlib covers both on Python ≥3.10.
  7. rely on open-aea[all] for click/pytest/coverage — already pulled transitively.
  8. drop hexbytes, use plain bytes for multisend tx data — three redundant HexBytes(bytes.fromhex(...)) calls collapse to bytes.fromhex(...).
  9. drop watchdog, move docker to optional [docker] extraget_docker_client() raises with install hint when missing.
  10. drop gql, post subgraph queries directly via aea http helper — verified live against the production subgraph that all 3 query templates return byte-identical responses.
  11. drop explicit protobuf declaration from autonomy/ — transitive via open-aea.
  12. drop Flask and Werkzeug, inline a Flask-compatible HTTP server — new autonomy/deploy/_http_server.py (~500 lines) mirrors the Flask/Werkzeug subset used by the localhost tendermint sidecar + replay server. Call sites unchanged.
  13. tomte format-code + linter fixes.
  14. make _RequestProxy dunder-safe for doctest — let Python handle __doc__/__repr__ introspection instead of routing through the thread-local request proxy.
  15. cleanup.md audit notes driving the PR (since deleted after all actionable items were addressed).

packages/valory/** — manifest-wide dep sweep

  1. fix CI failures from initial PR push — cascade hashes, docstrings, IPFS hashes in docs/**.
  2. agent_mech — drop unused eth_typing.HexStr and web3.types.{BlockData, EventData, TxReceipt}.
  3. sweep 16 contracts for type-only web3/eth_typing importserc20, erc8004_identity_registry_bridger, gnosis_safe_proxy_factory, multicall2, recovery_module, service_registry, sign_message_lib, staking_activity_checker, staking_token, agent_registry, erc8004_identity_registry, more. Replace Web3.to_checksum_address/Web3.keccak with ledger_api.api.to_checksum_address/ledger_api.api.keccak. Added ledger_api = cast(EthereumApi, ledger_api) at every method entry reaching ledger_api.api.*.
  4. gnosis_safe: thread ledger_api through encode.py — EIP-712 encoding via ledger_api.api.codec._registry.get_encoder(typ)(arg) and ledger_api.api.keccak(x) instead of eth_abi + eth_utils.keccak + Crypto.Hash. Verified byte-identical SafeTx hash against original.
  5. squads_multisig: drop solders — route Solana transfer via ledger_api.api.get_transfer_tx(...) exposed by open-aea-ledger-solana==2.2.1; add cast(SolanaApi, ledger_api) at the call site.
  6. align every manifest dependencies: block with actual direct imports (runtime + tests per AEA dep-checker). Drop eth_abi, eth_utils, hexbytes, pycryptodome, py-eth-sig-utils transitively-reachable entries; promote consistent open-aea-ledger-ethereum==2.2.1 declaration for contracts whose Python uses ledger_api.api.*; enforce web3: {} / requests: {} aiohttp <4,>=3.8.5 (matches upstream).
  7. promote package-YAML direct imports to pyproject main deps as an intermediate step; cleaned up in a later commit.
  8. prune test-only and stale deps from package YAMLs — since autonomy check-packages exempts tests/ subfolders, test-only deps (pytest, hypothesis, pytest-asyncio, open-aea-test-autonomy) are dropped from ~15 YAMLs. Runtime agents get a leaner install. test_tools/ files (scanned by the checker since not under tests/) keep the declarations they actually import; pytest in abstract_round_abci/test_tools/ is now wrapped in a try/except with a _PytestMissing stub so the skill imports cleanly without pytest installed.
  9. drop stale/unused deps from abstract_round_abci/skill.yamlipfshttpclient, open-aea-cli-ipfs, protobuf, requests, eth_typing, pytz, typing_extensions (swapped to stdlib datetime.timezone.utc, typing.{Literal, TypeGuard, NewType}); widen py-ecc to >=8,<10 (drand BLS API stable across 7→9).
  10. drop web3.types.{Nonce, TxData, Wei} usage in transaction_settlement_abci and its squads counterpart (these are NewType wrappers, runtime no-ops). Replace with plain int / Dict[str, Any].
  11. loosen YAML hypothesis pin + drop version drifthypothesis unpinned in connections/abci; aiohttp range aligned with upstream.
  12. ipfs connection: swap to upstream-inlined clientaea_cli_ipfs.ipfs_client.IPFSError (new urllib-backed hierarchy) replaces ipfshttpclient.exceptions.ErrorResponse + requests.exceptions.*. Drop both deps from the YAML.
  13. add open-aea-ledger-ethereum to 6 contracts that lacked itsign_message_lib, service_registry_token_utility, service_manager, registries_manager, erc8004_identity_registry_bridger, component_registry all declare contract_interface_paths: ethereum: and use ledger_api.api.* at runtime.
  14. remove empty hello_world / hello_world_abci leftover directories.

plugins/ — local path installs + helper simplification

  1. plugins/aea-test-autonomy: collapse deps to a single open-autonomy[all,docker]>=0.21.0,<0.22.0 (was: open-aea[all] + open-aea-ledger-ethereum + pytest==8.4.2 + docker==7.1.0). Always used alongside open-autonomy anyway.
  2. plugins/aea-helpers: trim to open-autonomy>=0.21.0,<0.22.0 (was: +click, requests, toml, PyYAML). Swap requestsaea.helpers.http_requests inside the plugin; swap toml → stdlib tomllib with tomli fallback on Python 3.10 (transitive via pytest's python_version < "3.11" marker).

pyproject.toml / tox.ini — final cleanup

  1. rehome main deps and switch plugins to local paths — main deps now reflect only runtime-only imports (web3, requests, grpcio, aiohttp, certifi, multidict, asn1crypto, ecdsa, py-ecc, open-aea-ledger-cosmos). hypothesis, pytest, pytest-asyncio, open-aea-test-autonomy move to dev. open-aea-helpers / open-aea-test-autonomy install via { path = "plugins/…", develop = true }. Flask + Werkzeug kept in dev for the docker-compose tendermint sidecar + legacy slow-tendermint test helper. Drop dead main deps (pytz, typing-extensions, ipfshttpclient, protobuf, eth-typing, pycryptodome). Unpin hypothesis, pytest, loosen web3 / requests to * (transitive chain decides). open-aea-ledger-solana left commented out (anchorpy→cachetools conflict with tomte[tox]'s tox 4.46 — needs anchorpy to loosen upstream).
  2. tox.ini cleanup and check-dependencies satisfaction — drop 10 dead [deps-packages] entries, 6 duplicated framework inheritances, 17 dead [mypy-*] ignore sections. Add missing direct-import deps (aiohttp, Flask, Werkzeug, protobuf<7,>=5). Use ignore_missing_imports for third-party-only aiohttp/flask/werkzeug. Drop --exclude solders from check-dependencies. Add extras = [] hint to the optional open-aea-ledger-ethereum entry so check-dependencies' parser can see it; add protobuf and pytest-asyncio shim entries in a TODO-cleanup block so the tool doesn't flag them (setup.py remains the authoritative distribution manifest — these are harmless redundancies).

Housekeeping

  1. LICENSE — extend copyright to 2021-2026.
  2. SECURITY.md — bump supported versions table from 0.14.x to 0.21.x.
  3. cleanup.md deleted (served its purpose; all action items addressed).
  4. normalize last protobuf YAML pinconnections/abci now uses <7,>=5 (matches open-aea upstream).
  5. sync ABSTRACT_ROUND_ABCI_SKILL_WITH_HASH in autonomy/constants.py with current packages/packages.json hash.

Test plan

  • All linters pass via tomte check-code: black, isort, flake8, mypy, pylint, darglint.
  • Package + docs tox envs all green: check-hash, check-packages, check-third-party-hashes, check-dependencies, check-api-docs, check-doc-links-hashes, check-abci-docstrings, check-abciapp-specs, check-handlers, check-dialogues, fix-doc-hashes.
  • Static / security: bandit, safety, vulture, spell-check, liccheck.
  • Parity verifications performed before swaps:
    • Subgraph gql → aea http_requests: all 3 query templates byte-identical against production subgraph.
    • Gnosis_safe EIP-712 encoder eth_abi → ledger_api.api.codec: byte-identical SafeTx hash for a realistic Safe v1.3 tx.
    • bytes.fromhex(...) vs HexBytes(bytes.fromhex(...)): verified identical byte representation.
  • CI green on py3.10-linux through py3.14-linux.
  • Manual spot-check: autonomy develop without [docker] extra raises a clear install hint.
  • Manual spot-check: chain ops (mint/service) without [chain] extra raise a clear install hint.

Known follow-ups (out of scope here)

  • Re-enable open-aea-ledger-solana once anchorpy upstream loosens cachetools<5 (conflicts with tomte[tox]'s tox 4.46 needing cachetools>=7.0.1).
  • check-generate-all-protocols requires libprotoc 24.3 — system binary; CI installs explicitly, local dev needs matching protoc install (out of scope for pyproject/tox changes).
  • Patch the aea-helpers check-dependencies tool to understand optional = true entries and dev-group deps in pyproject.toml, so the shim entries can be removed.

🤖 Generated with Claude Code

Additional work done during review

Triaged open issues (resolved or commented/closed with rationale)

Security cleanup (secret + dependabot + code scanning)

  • Secret scanning — the leaked Google API key in tests/data/logs/aea_0.txt (present in history since 1b9bd2e51 in 2023) was redacted with a <GOOGLE_API_KEY> placeholder in the current fixture. All 11 log-analyse tests still pass. GitHub alert resolved; key itself should be rotated in GCP.
  • Dependabot (15 → 0 open after merge):
    • valory/open-autonomy-dev image — bumped stale requests==2.27.1 (2021) and watchdog==2.1.6 (2021) pins in deployments/Dockerfiles/development/Pipfile. Clears 4 alerts (CVE-2023-32681, CVE-2024-35195, CVE-2024-47081, CVE-2026-25645).
    • poetry.lock targeted updates: requests 2.32.5 → 2.33.1 (CVE-2026-25645), web3 7.14.1 → 7.15.0 (CVE-2026-40072). No other packages affected.
    • tox.ini — dropped explicit requests<2.33.0,>=2.28.1 and ecdsa>=0.15 pins; both now defer to transitive constraints from open-aea-ledger-ethereum==2.2.1 (requests>=2.32.5,<3) and open-aea-ledger-cosmos==2.2.1 (ecdsa>=0.19.2,<0.20), matching main open-aea's own pins.
    • Transitive / test-only alerts (pytest, pillow, cryptography, Pygments, PyNaCl, ecdsa, duplicated requests-in-setup.py) dismissed with per-case justifications.
  • Code scanning (50 → 0 open) — 14 test-file alerts dismissed as "used in tests"; 22 path-traversal false-positives dismissed (tendermint Flask control server reads os.environ["TMHOME"] + constant paths, never request bodies); 3 command-injection false-positives (CLI/build-time subprocess with list args); 2 XSS false-positives (Flask jsonify returns JSON, not HTML); 7 server-information-exposure alerts marked "won't fix" with rationale (internal docker network only); 1 DOMXSS in docs JS ("won't fix" — author-controlled packages.json input); 1 hardcoded-secret false-positive in a k8s Secret template placeholder (already had # nosec).

Coverage push — new files driven to 100%

New test suites added so every file flagged by codecov on this PR reaches 100% patch coverage:

  • tests/test_autonomy/test_deploy/test_http_server.py (53 tests) — covers autonomy/deploy/_http_server.py: Request/Response/jsonify, _Args coercion, _Route, _RequestProxy, App dispatch + error handlers, _to_response, _TestClient/_TestResponse, App.run delegation, run_app finally-branch, plus an integration test against a real threaded HTTP server.
  • packages/valory/contracts/gnosis_safe/tests/test_encode.py (24 tests) — drives encode.py to 100% via a deterministic ledger_api stub; exercises every branch of encode_value (string/bytes/struct/array/primitive) + schema/dependency walk.
  • tests/test_autonomy/test_chain/test_utils.py — +6 tests for resolve_component_id (service/agent/component dispatch + RPC/IPFS error paths), parse_public_id_from_metadata strip-suffix, and is_service_manager_token_compatible_chain.
  • tests/test_autonomy/test_chain/test_subgraph.py — +3 tests for _query (happy path, GraphQL-errors path, HTTP error-status path).
  • tests/test_autonomy/test_deploy/test_deployment_generators.py — +1 test for the DOCKER_INSTALLED=False branch of get_docker_client.

E2E rerun-fixture fix

  • plugins/aea-test-autonomy: added BaseTestEnd2End.teardown_method that removes fetched agent folders and clears per-class subprocess/agent state after each test method. Without this, pytest.mark.flaky reruns (and parametrized test_run[nb_nodes] iterations) hit aea fetch's "already exists" guard because the class-scoped tmpdir leaks state from the first run.

PR review (Copilot) comments

  • 4x from_block/to_blockfromBlock/toBlock in packages/valory/contracts/gnosis_safe/contract.py (get_ingoing_transfers, get_safe_txs, get_removed_owner_events, get_zero_transfer_events). Pre-existing bug on main: web3.py v7's FILTER_PARAM_NORMALIZERS only normalises address, so snake_case filter keys pass through to the RPC unchanged and the server silently returns the full-range scan. Matches the form already used by mech_marketplace/contract.py:609-611.
  • autonomy/chain/subgraph/client.py — added explicit status_code >= 400 check before resp.json(), restoring the clear HTTP-error behaviour we had with gql.Client.execute before the http-helpers swap; unit test added.
  • autonomy/chain/exceptions.pyImportError hint now recommends pip install open-autonomy[chain] primarily (with open-aea-ledger-ethereum as fallback).

Dev ergonomics

  • CLAUDE.md — replaced the "Pre-PR Checklist" with an ordered "Pre-commit routine" covering format-codecheck-codesecurityfix-copyrightcheck-dependencies → (if packages) generatorsautonomy packages lockfix-doc-hashes → (if docstrings) generate-api-documentation → final check-api-docs/check-hash/check-packages. Added the "Docker images required" reference table (with only the actually-consumed images — 3 of the 7 images pulled by main_workflow.yml have no fixture consumers in this repo).
  • CONTRIBUTING.md — mirror "Running tests locally" section with the same minimal docker-image set.
  • autonomy/constants.py ABSTRACT_ROUND_ABCI_SKILL_WITH_HASH kept in sync with every packages.json relock; doc IPFS hashes refreshed via tox -e fix-doc-hashes.
  • CI fix — 5x # nosec B310 on legitimate urllib.request.urlopen calls against the hard-coded 127.0.0.1 test server in test_http_server.py (bandit false-positive on the new integration test).

DavidMinarsch and others added 27 commits April 18, 2026 14:19
…deps

Swap autonomys direct imports of `requests` and `jsonschema` for the
inline equivalents in `aea.helpers.http_requests` and
`aea.helpers.json_schema`, so the framework no longer needs those
packages in its own dependency list. `multiaddr` was already unused
in autonomy/, and the two stale `multiaddr.codecs.*` PyInstaller
bundling hints in `bin_template.py` are dropped as well.

Minor call-site adjustments:
- `CustomSchemaValidator` minProperties error-message match is
  updated to the wording emitted by the aea helper (single-line swap).
- The localhost tendermint app passes `params` as a kwarg because the
  aea helpers second positional is `timeout`.

Tests that caught `requests.exceptions.ConnectionError` or asserted on
`jsonschema.exceptions.ValidationError` are re-pointed at the aea
helper classes so mocked/raised exceptions still match what production
code catches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The only use of texttable was `print_service_info` in
`autonomy/cli/helpers/chain.py`, which renders one fixed table of
key/value pairs. Replace the dependency with a ~20-line `_draw_table`
helper in the same file and remove `texttable` from setup.py,
pyproject.toml, and tox.ini (plus its mypy override).

Output stays visually close to texttable default: ASCII borders with
`=` under the header row, newline-containing cells stack inside their
cell. No tests asserted on the exact rendering.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prior commit swapped every `requests.exceptions.ConnectionError`
catch to `aea.helpers.http_requests.ConnectionError`, but the chain
modules catch exceptions raised by web3s HTTPProvider — which uses
`requests` internally and raises the unrelated
`requests.exceptions.ConnectionError`. Result: `RPCError("Cannot
connect to the given RPC")` no longer wrapped on real RPC failures
(seen as a regression in `test_mint_components.py::TestConnectionError`).

Fix by introducing a lazy resolver `get_requests_connection_error()`
in `autonomy/chain/exceptions.py`. It returns
`requests.exceptions.ConnectionError` when the Ethereum ledger plugin
is installed (requests is transitively present), and raises a clean
`ImportError` with an install hint otherwise — matching the
`load_hwi_plugin` pattern in `autonomy.chain.config`. Lazy so that
unrelated importers of this module (e.g. CLI helpers needing only
`FailedToRetrieveComponentMetadata`) keep working without the plugin.

Each call site now catches the class that matches its origin:
- web3 paths (`chain/tx.py`, `cli/helpers/chain.py`,
  `analyse/service.py`, and the RPC side of `chain/utils.py`) use
  `get_requests_connection_error()`.
- The IPFS `r_get` call in `chain/utils.py` stays on
  `aea.helpers.http_requests.ConnectionError` since thats our own
  HTTP client.

Tests that raise the exception under mock are re-pointed to
`requests.exceptions.ConnectionError` to match what production catches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
setup.py and pyproject.toml had drifted: pyproject declared ~20
direct deps (eth-*, pycryptodome, ipfshttpclient, asn1crypto,
ecdsa, grpcio, pytz, web3, toml, hypothesis, pytest-asyncio, etc.)
that setup.py did not, most of them transitive via `open-aea[all]`
or `open-aea-ledger-ethereum` or unused by autonomy itself.

Changes:

* `pyproject.toml [tool.poetry.dependencies]` now mirrors setup.py
  base_deps exactly (11 core + 4 cli = 15 runtime + python).
* Add `[chain]` extra in both files, declaring
  `open-aea-ledger-ethereum==2.2.1` as the optional plugin required
  for chain operations. Included in `[all]`; `[hwi]` stays excluded
  due to its armv7 wheel constraint. Matches the lazy-resolver
  pattern introduced in `autonomy.chain.exceptions`.
* Test-only deps used by `packages/valory/**` when pytest runs
  directly (`make test`, not via tox) move to the poetry dev group:
  `py-ecc`, `pycryptodome`, `hypothesis`, `pytest-asyncio`. These
  are not part of the published wheel. `tox.ini` already declares
  its own dep lists for `tox -e <env>`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`autonomy/cli/helpers/env.py` was the only direct user of
`python-dotenv`, calling `load_dotenv(dotenv_path=...)`. open-aea
ships an equivalent `aea.helpers.base.load_env_file` that parses
the same KEY=VALUE / `export` / `${VAR}` syntax, so swap in that
helper and remove `python-dotenv` from setup.py, pyproject.toml
(main + cli + all extras), tox.ini, and its mypy override.

`tests/.../test_deployment.py::check_agent_env` used `load_dotenv`
with `override=True` to re-import env files into `os.environ`
across agent iterations. The aea helper uses `setdefault`
semantics, which would leak stale values between iterations.
Rewrite the check to parse the file directly and compare the
KEY=VALUE line, dropping the `os.environ` side-effect entirely —
simpler and more what the assertion actually needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`aiohttp` is not imported anywhere in autonomy/ — it was a pure
transitive pulled explicitly. Drop it from setup.py, pyproject.toml,
tox.ini, and its mypy override.

`typing_extensions` was imported only for `TypedDict`, which has been
in stdlib `typing` since Python 3.8. Autonomy targets Python
`>=3.10,<3.15`, so switch the two call sites
(`autonomy/deploy/base.py`, `autonomy/chain/subgraph/client.py`) to
import `TypedDict` from `typing` and drop the declaration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`open-aea[all]` already pulls in `click`, `pytest`, `coverage`, and
`pyyaml`/`packaging` via its own `[cli]` extra, so re-declaring those
in autonomys own dependency list is redundant.

Drop:
* `pytest==8.4.2` from base_deps / main pyproject deps.
* `click>=8.1.0,<9`, `pytest>=8.0.0,<8.5.0`, `coverage>=6.4.4,<8.0.0`
  from the `[cli]` extra.

autonomys `[cli]` / `[all]` extras now contain only
`open-aea-cli-ipfs`, which is a separate package not covered by
open-aeas extras. Version ranges for the dropped deps relax to what
open-aea allows (clicks upper bound actually tightens:
open-aea pins `click>=8.1.0,<8.4.0`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`HexBytes` is a `bytes` subclass; the three call sites in
`autonomy/chain/service.py` built it via `HexBytes(bytes.fromhex(...))`
only to pass the value into `multisend.encode_data`, which itself
does `HexBytes(data)` first — so the outer wrap is redundant. Strip
it and pass `bytes.fromhex(...)` directly.

One test (`test_service_manager.py::check_swap_owner_tx_data` and
friends) mirrored the same shape; update it to match the production
code.

Remove `hexbytes` from setup.py, pyproject.toml, tox.ini, and its
mypy override. `hexbytes` stays transitively available via `web3`
under the `[chain]` extra — unchanged for any downstream package
code that still uses `HexBytes` directly (e.g. the multisend
contract in `packages/valory/contracts/multisend/`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
watchdog has zero imports in `autonomy/`. Its only use is in
`deployments/Dockerfiles/development/watcher.py`, a helper script
that runs inside the dev Docker image and already declares
`watchdog==2.1.6` in that image's own Pipfile. Remove from setup.py,
pyproject.toml, tox.ini, and its mypy override.

docker is a genuine runtime dep, but only on one deploy backend:
`autonomy/deploy/generators/docker_compose/base.py` imports it to
back `get_docker_client()`, which is reached only by docker-compose
deploys and the `autonomy develop` command. Users deploying to
Kubernetes or localhost don't need it.

Convert to the same optional-plugin pattern as
`ETHEREUM_PLUGIN_INSTALLED` / `get_requests_connection_error`:
wrap the docker imports in try/except that sets DOCKER_INSTALLED,
and raise an ImportError with an install hint inside
`get_docker_client()` when a caller actually needs it. The return
type annotation becomes a forward-reference string so the function
stays valid without docker at module import time.

Declare `[docker]` in setup.py and pyproject.toml extras. Like
`[hwi]`, it is intentionally excluded from `[all]`:
  * [hwi] excluded because its transitive chain has no armv7 wheels.
  * [docker] excluded because most users don't need it.
Install via `pip install open-autonomy[docker]` when needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`SubgraphClient` was using `gql` for three hardcoded query templates
that never change at runtime. The library's value (AST parsing,
client-side schema introspection) is purely development-time; at
runtime it was acting as a dressed-up `requests.post`.

Replace the four gql calls with a single JSON POST via
`aea.helpers.http_requests.post`, raising a RuntimeError when the
response includes `errors`. A User-Agent header is sent explicitly
because the default subgraph sits behind Cloudflare, which 403s
urllib requests without a UA (requests' default UA masked this for
the old gql path).

Verified live against
`https://subgraph.autonolas.tech/subgraphs/name/autonolas` that all
three query templates (FIND_BY_PACKAGE_HASH, FIND_BY_PUBLIC_ID,
FIND_BY_TOKEN_ID) return byte-identical responses through the old
gql path and the new inline path.

Drop `gql==3.5.0` from setup.py, pyproject.toml, tox.ini, its mypy
override, and pylint's `ignored-modules`. Also drops its transitive
chain (graphql-core, anyio, backoff, yarl, requests-toolbelt, and a
second `requests` install path independent of web3s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
autonomy/ imports no `google.protobuf` anywhere, and `open-aea`
already requires `protobuf>=5,<7` as a core (non-extras) dependency.
Our `protobuf<6,>=5` was redundant and slightly stricter on the
upper bound. Drop it from setup.py, pyproject.toml, and tox.ini.
Any `packages/valory/**` manifest that needs a tighter pin declares
it in its own YAML.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The two Flask apps in autonomy — the localhost tendermint sidecar in
`autonomy/deploy/generators/localhost/tendermint/app.py` and the
replay-mode RPC imitator in `autonomy/replay/tendermint.py` — are
now backed by a tiny stdlib HTTP server in
`autonomy/deploy/_http_server.py` that mirrors the subset of
Flask/Werkzeug we actually use:

* `App(name)` with `.route`, `.get`, `.post`, `.errorhandler`,
  `.logger`, `.config`, `.app_context()` and `.test_client()`.
* `Request` with `.args.get(key, default, type=...)`, `.get_data()`,
  `.get_json()`.
* `Response` with `.data`, `.status_code`, `.mimetype`,
  `.get_json()`.
* `jsonify(dict|list|**kwargs)` matching Flask's exact semantics.
* `NotFound` / `InternalServerError` stand-ins for
  `werkzeug.exceptions.*`.
* Threading request context so the module-level `request` proxy
  works the same way as `from flask import request`.
* `run_app(app, host, port)` backed by `ThreadingHTTPServer` with
  `HTTP/1.1` keep-alive.

Production call sites only swap their import statements — handler
bodies and return shapes are unchanged. Tests keep using
`app.test_client()`, `response.status_code`, and
`response.get_json()` unchanged; the only edits are replacing the
`flask.app.Flask` / `flask.ctx.AppContext` type annotations with
`Any` (the objects themselves are our stand-ins, the annotations
were cosmetic).

API-compatibility is maintained so this change can be reverted by
restoring the Flask dep and flipping the import lines back.

Verified: both test modules pass (21 passed, 1 Linux-only skipped,
1 long-running buffer test deselected).

Drops `Flask>=3.1.0,<4.0.0` and `Werkzeug>=3.1.0,<4.0.0` from
setup.py, pyproject.toml, and tox.ini (both `[deps-framework]` and
`[deps-packages]` blocks). Removes the corresponding mypy overrides.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure auto-fix: isort re-orders open-aea helper imports in
analyse/service.py and the _http_server imports in
tendermint/app.py; black tightens whitespace in chain/exceptions.py
and _http_server.py.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes surfaced by the first full lint pass against the rewritten
deploy/replay servers and helpers:

* autonomy/deploy/_http_server.py: add `App.run(host, port)` (mirrors
  `flask.Flask.run` — used by `autonomy/cli/replay.py`), rename the
  stdlib-shadowing `type` / `format` params to keep pylint happy,
  simplify a dict comprehension, add a couple of :param:/:return:
  docstrings (jsonify, _Args.get, log_message), and relax
  too-few-public-methods + broad-exception-caught at module level
  (the file defines several tiny data classes and catches broadly
  by design to map handler errors to 500 responses).
* autonomy/cli/helpers/chain.py: convert the one-line `border`
  lambda in `_draw_table` to a nested def (flake8 E731 / pylint
  C3001) and add :param:/:return: (darglint).
* autonomy/chain/exceptions.py: complete the docstring for
  `get_requests_connection_error` with :return: and :raises:
  (darglint) and move the `pylint: disable=import-outside-toplevel`
  to the outer statement line so it actually applies.
* .pylintrc: add `flask`, `werkzeug`, `watchdog`, `dotenv` to
  `ignored-modules` — these are only imported by files outside the
  installed autonomy package (Docker images, plugins) which declare
  their own deps; autonomy's lint env doesn't install them.

All six linters (black, isort, flake8, mypy, pylint, darglint) now
pass via `tomte check-code`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tools like `pytest --doctest-modules` and `pydoc` walk module
globals and touch attributes like `__doc__`, `__repr__`, or
`__wrapped__`. Routing those through the thread-local request proxy
raised `RuntimeError: No active request context` at import time,
blocking doctest collection on `autonomy/deploy/_http_server.py`
and the modules that re-export `request`.

Filter dunders in `_RequestProxy.__getattr__` so default attribute
lookup applies — dunders fall through to the normal object-level
AttributeError, leaving real request attribute access unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Intermediate findings doc that surveyed:
  * autonomy/ imports vs. setup.py + pyproject.toml declarations
  * packages/valory/** YAML `dependencies:` blocks

Captures declared-but-unused deps, version-pin drift, test-only deps
leaked into production manifests, and a proposed PR sequence.
Committed as an artefact so reviewers can see the reasoning
behind the commits on this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three CI failures from the first PR run:

* bandit B110 try/except/pass on `_http_server.py:356` — add
  `# nosec B110` and a comment explaining the intentional fallback
  when a user-supplied 500 handler itself raises.

* check-api-docs — pydoc-markdown noticed the new
  `get_requests_connection_error` in `autonomy.chain.exceptions`
  and the updated return annotation on `get_docker_client` in
  `autonomy.deploy.generators.docker_compose.base`, and the new
  `autonomy.deploy._http_server` module. Regenerate the three
  affected `docs/api/` files via `tox -e generate-api-documentation`.

* lock_check — `pyproject.toml` edits from the cleanup commits
  hadn't been reflected in `poetry.lock`. Regenerate via
  `poetry lock`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
packages/valory/contracts/agent_mech/contract.py imported HexStr
from eth_typing and BlockData, EventData, TxReceipt from web3.types
solely for type annotations that do not affect runtime behaviour:

* tx_hash: HexStr parameters become tx_hash: str (HexStr is a
  NewType alias over str — identical at runtime).
* receipt: TxReceipt, logs: List[EventData], block: BlockData
  local-variable annotations are dropped; the values are only read
  dict-style afterwards.

With the imports gone, List from typing is also unused — drop it.

The manifest loses two dep declarations that were only needed by
those imports: eth_typing and web3. They remain transitively
available via open-aea-ledger-ethereum for any runtime code path
that needs them.

Re-ran `autonomy packages lock` (updates agent_mech fingerprint +
cascades packages.json / docs/package_list.md) and
`tomte check-code` (all six linters green).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tracts

Same pattern as agent_mech: remove direct imports of web3/eth_typing/
hexbytes/eth-abi/eth-utils where they were used only for type
annotations or trivial utility calls that already have a ledger_api /
stdlib equivalent, then strip the corresponding entries from each
contract's YAML `dependencies:` block.

Contracts touched:
* agent_registry, agent_mech (already committed)
* erc20 — YAML-only cleanup (8 declared, 1 used)
* erc8004_identity_registry — swap eth_abi.encode → ledger_api.api.codec.encode;
  Web3.keccak → ledger_api.api.keccak; Web3.to_checksum_address →
  ledger_api.api.to_checksum_address
* erc8004_identity_registry_bridger — YAML-only
* gnosis_safe — largest refactor: drop eth_typing / hexbytes / eth-utils /
  packaging / ecdsa; inline `HexBytes(...).to_0x_hex()` as
  `"0x" + bytes.hex()`; replace packaging.version.Version with tuple
  compare; swap `event_abi_to_log_topic + get_event_data` for web3's
  native `ContractEvent.topic + process_log(log)`; keep
  `web3.exceptions.ContractLogicError` / `TransactionNotFound` and
  `requests.HTTPError` because those are real runtime catches.
* gnosis_safe_proxy_factory — drop web3.types aliases, strip
  `Wei(...)` / `Nonce(...)` / `TxParams(...)` no-op wrappers.
* mech_marketplace — drop eth_typing / hexbytes / web3 / eth-utils;
  refactor `get_event_entries` helper to take a ContractEvent instead
  of raw ABI (mirrors gnosis_safe).
* multicall2, recovery_module, sign_message_lib, staking_activity_checker,
  staking_token — YAML-only cleanups.
* multisend — drop hexbytes and web3 imports; thread `ledger_api` through
  the module-level helpers `decode_data` and `from_bytes` so the single
  `Web3.to_checksum_address` call becomes `ledger_api.api.to_checksum_address`.
  Test file loses its hexbytes import too.
* poly_safe_creator_with_recovery_module — drop eth-abi and eth-utils;
  use `ledger_api.api.codec.encode` and `ledger_api.api.to_checksum_address`.
* service_registry — drop web3.types imports; drop stale `open-aea-test-autonomy`
  (tests/ files do not import it any more) and `web3` (transitive via
  open-aea-ledger-ethereum).

Consistency:
* Every method (and module-level function in multisend) that now calls
  `ledger_api.api.*` under a `LedgerApi`-typed parameter has
  `ledger_api = cast(EthereumApi, ledger_api)` as its first statement,
  with the matching `from aea_ledger_ethereum import EthereumApi` and
  `from typing import cast` imports.
* YAML `dependencies:` blocks now list only *direct* imports of the
  package's runtime + test files. Deps available transitively via
  `open-aea-ledger-ethereum` (web3, eth-abi, eth-utils, hexbytes,
  requests, pycryptodome via eth-hash[pycryptodome]) are not re-declared.
* Version pins on web3 dropped in favour of whatever the ledger plugin
  constrains.

Also:
* plugins/aea-helpers: drop python-dotenv dep; swap
  `dotenv.load_dotenv(path, override=True)` for
  `aea.helpers.base.load_env_file(path)`. Note: this changes env-override
  semantics — pre-existing env now wins over the .env file. If
  file-wins is required, reintroduce python-dotenv with a comment.
* CLAUDE.md: document the "lock last" hashing workflow — running
  `autonomy packages lock` before final edits wastes work because each
  subsequent edit dirties fingerprints again.
* Re-locked all affected packages + cascaded IPFS hashes in
  `docs/package_list.md`, `docs/configure_service/analise_test.md`,
  `docs/advanced_reference/commands/autonomy_fetch.md`, and the 8 agent
  + 1 service YAMLs that reference the modified contract hashes.

Linters: all six (black, isort, flake8, mypy, pylint, darglint) pass.
Bandit + vulture pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Declares `web3`, `requests`, `protobuf`, `aiohttp`, `multidict`, `certifi`,
`ipfshttpclient`, `grpcio`, `asn1crypto`, `ecdsa`, `eth-typing`, `pytz`,
`typing-extensions`, `py-ecc`, `hypothesis`, `pytest`, `pytest-asyncio`,
`open-aea-ledger-cosmos`, `open-aea-test-autonomy` as top-level deps.
Matches the union of `dependencies:` across `packages/valory/**` YAMLs;
`open-aea-ledger-solana` temporarily commented out (anchorpy/pytest clash
with open-aea-test-autonomy). TODO marker signals the cleanup pass still
owed.

Also: drop `solders` from `squads_multisig` by routing transfer
construction through `ledger_api.api.get_transfer_tx` and casting to
`SolanaApi`; gnosis_safe/encode.py, yaml cleanup across contracts,
cascade hashes/api-docs/doc-ipfs-hashes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nomy

* aea-helpers: drop direct `click`, `requests`, `PyYAML`, `toml`
  declarations -- all four are reachable transitively via the sole
  remaining dep `open-autonomy>=0.21.0,<0.22.0` (`click`/`PyYAML`
  via `open-aea[all]`; `requests` is no longer used -- swap to
  `aea.helpers.http_requests`; `toml` is replaced with stdlib
  `tomllib` on 3.11+, falling back to `tomli` on 3.10 which comes
  transitively via pytest on older Python).

* aea-test-autonomy: collapse `open-aea[all]` +
  `open-aea-ledger-ethereum` + `docker` pins into a single
  `open-autonomy[all,docker]>=0.21.0,<0.22.0` dep, since the plugin
  is always used alongside open-autonomy.

Also: relocate squads_multisig type-ignore/pylint-disable on the
`SolanaApi` import to a black-safe multi-line form.

Cascade: lock packages, fix copyright year, re-run fix-doc-hashes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trims runtime install footprint by dropping YAML dependencies entries
that are only reached from tests/ (checker-exempt) or never imported,
and swapping remaining imports to stdlib/upstream where possible.

* drop test-only deps (pytest, hypothesis, open-aea-test-autonomy,
  pytest-asyncio) from abci connection, many contracts,
  squads_transaction_settlement_abci, and all 8 agent YAMLs.
  connection/valory/ledger is third-party and untouched.

* drop stale ipfshttpclient, open-aea-cli-ipfs, protobuf, requests from
  abstract_round_abci/skill.yaml (not imported anywhere).

* add open-aea-ledger-ethereum to 6 contracts that lacked it despite
  using an ethereum interface (sign_message_lib, service_registry_token_utility,
  service_manager, registries_manager, erc8004_identity_registry_bridger,
  component_registry).

* swap pytz -> stdlib datetime.timezone.utc, typing_extensions.{Literal,
  TypeGuard, TypedDict} -> stdlib typing, eth_typing.bls.{BLSPubkey,
  BLSSignature} -> inline typing.NewType.

* widen py-ecc pin to <10,>=8 (BLS drand verification; API stable 5.x+;
  9.0-beta has no BLS changes).

* drop web3.types.{Nonce, TxData, Wei} usage across
  transaction_settlement_abci and its squads counterpart (NewType wrappers
  are runtime no-ops); replace with plain int / Dict[str, Any].

* drop grpcio/hypothesis test-side declarations from abci connection;
  loosen hypothesis YAML pin (used only in fuzz tests).

* in connections/ipfs/connection.py, swap to upstream inlined
  aea_cli_ipfs.ipfs_client.IPFSError (new urllib-backed hierarchy);
  drop ipfshttpclient and requests imports and YAML entries.

* in test_tools/{rounds,common}.py, wrap import pytest in try/except
  with a _PytestMissing stub (clear ImportError when pytest absent);
  lets us drop pytest from abstract_round_abci/skill.yaml.

* remove empty hello_world and hello_world_abci leftover directories.

Cascade: autonomy packages lock, tox -e fix-copyright, tox -e
fix-doc-hashes. All other linters green; mypy pre-existing failures in
untouched files (auto-generated _pb2, http_client, Flask test helpers)
are unrelated and present on baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Catches up with the earlier `requests` -> `aea.helpers.http_requests`
swap; `make_git_request` now returns `http_requests.HTTPResponse`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Applies the cleanup TODO left behind by the earlier promotion commit:

* Drop dead declarations: `pytz`, `typing-extensions`, `ipfshttpclient`,
  `protobuf`, `pycryptodome`, `eth-typing`. None of them are directly
  imported by runtime or test code any more; `eth-typing` arrives
  transitively via `web3`.

* Move test-only deps from main to the dev group: `hypothesis`,
  `pytest`, `pytest-asyncio`, `open-aea-test-autonomy`. The former
  three had hard pins that are no longer needed; drop them to `*` so
  the upstream transitive chain decides. `open-aea-test-autonomy`
  switches to a local path install (`plugins/aea-test-autonomy`,
  develop=true) so edits there take effect without a PyPI round-trip.

* Install `open-aea-helpers` from `plugins/aea-helpers` via the same
  local path+develop mechanism.

* Add `Flask` and `Werkzeug` to the dev group for the docker-compose
  tendermint sidecar (`deployments/Dockerfiles/tendermint/app.py`) and
  the register_reset legacy test helper — kept out of main deps since
  the autonomy wheel now ships `autonomy/deploy/_http_server.py` as a
  stdlib-only Flask-compatible shim.

* Loosen `web3` and `requests` to `*` so they match the `{}` entries
  in the package YAMLs; their effective bounds come transitively via
  `open-aea-ledger-ethereum`.

* Widen `py-ecc` to `>=8,<10` (API stable).

* Add a policy block above the main-deps list: unpin when the
  transitive chain already bounds the range; pin only when
  version-sensitive, and keep those pins in sync with the package
  YAMLs.

* Keep `open-aea-ledger-solana` commented out with a narrower
  rationale: the live conflict is `anchorpy` requiring
  `cachetools<5` vs `tomte[tox]` requiring `cachetools>=7.0.1`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Delete `cleanup.md` — the audit doc driving this PR; all actionable
  items are addressed.
* Normalise the last `protobuf` pin to match open-aea upstream:
  `connections/abci/connection.yaml` now uses `<7,>=5` instead of
  `<6,>=5`.
* Sync `autonomy.constants.ABSTRACT_ROUND_ABCI_SKILL_WITH_HASH` with
  the current hash in `packages/packages.json`.
* LICENSE: extend copyright year to `2021-2026`.
* SECURITY.md: bump the supported-versions table from `0.14.x` to
  `0.21.x`.

Cascade: `autonomy packages lock`, `tox -e fix-doc-hashes`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tion

tox.ini:
* [deps-framework]: drop stale multiaddr==0.0.9.
* [deps-packages]: drop 10 dead entries that no code imports any more
  (eth_typing kept - 1 direct import in a third-party ledger test;
  eth-account kept - 1 direct import in aea-test-autonomy); drop
  duplicate framework entries that were already inherited via
  {[deps-tests]deps}; add the genuinely-missing direct-import deps
  aiohttp, Flask, Werkzeug, and protobuf<7,>=5 (matches the upstream
  open-aea range).
* [testenv:mypy]: no new deps - use ignore_missing_imports for the
  third-party-only aiohttp, flask, werkzeug instead of installing,
  consistent with how other third-party deps are handled.
* [mypy-*]: drop 17 dead ignore sections for modules that are not
  imported anywhere (ipfshttpclient, eth_keys, eth_abi,
  py_eth_sig_utils, toml, Crypto, eth_utils, solders, pytz,
  jsonschema, packaging, pkg_resources, semver, compose, typed-ast,
  scripts.common, autonomy.data.Dockerfiles.tendermint.tendermint);
  add per-module ignore_errors for the four _pb2 files not already
  covered by the exclude regex.
* [testenv:check-dependencies]: drop --exclude solders (no direct
  imports of solders anywhere after swapping to
  ledger_api.api.get_transfer_tx).

pyproject.toml:
* Add extras=[] marker to the optional open-aea-ledger-ethereum entry
  so check-dependencies parser can see it (the tool only reads dicts
  that carry an extras key).
* Add protobuf and pytest-asyncio in a TODO-cleanup block at the
  bottom of main deps - the tool does not read the dev group, so
  pytest-asyncio is invisible to it; protobuf is transitive via
  open-aea[all]. setup.py remains the authoritative distribution
  manifest; these entries are redundant but harmless.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* autonomy/cli/helpers/chain.py: the two subgraph-facing `except`
  blocks now catch `aea.helpers.http_requests.ConnectionError` instead
  of `requests.exceptions.ConnectionError`. The subgraph client was
  swapped to the aea http helper (stdlib urllib underneath) in an
  earlier commit, but these two handlers still pointed at the
  requests-based exception class, letting the `ConnectionError`
  propagate past the `click.ClickException` wrapper. Caught by CI on
  macOS/Windows via `test_verify_service_dependencies_failures`.

* autonomy/analyse/service.py: the "not enough properties" error
  bucket was matching `has fewer than` (emitted for `minProperties`)
  and a dead `should be non-empty` string. Replace the dead clause
  with `is too short` which is what aea.helpers.json_schema emits
  for `minItems` violations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace leftover third-party imports in agents test folders with the
aea-native equivalents so the repo no longer carries direct web3 or
requests usage anywhere except where genuinely needed.

* packages/valory/agents/{register_termination,solana_transfer_agent}/
  tests/base.py: drop `import web3` + `from web3.types import Wei` and
  swap `web3.Web3(web3.HTTPProvider(...))` construction for
  `aea_ledger_ethereum.EthereumApi(address=..., chain_id=...)`. Chain
  interactions go through `ledger_api.api.*` (which is the underlying
  web3.Web3 instance). `Wei(0)` becomes plain `0` (NewType wrapper,
  runtime no-op).

* packages/valory/agents/counter/tests/test_counter.py: swap the three
  `requests.get(...)` test helper calls to `http_requests.get(...)`
  from `aea.helpers.http_requests` (urllib-backed; identical
  params/timeout signature, identical Response.status_code/.json()
  surface for the test assertions).

* packages/valory/agents/register_reset_recovery/tests/base.py: same
  swap in the `_disrupt_tm_node` HTTP helper.

* tests/test_autonomy/test_cli/test_replay/test_tendermint.py: patch
  `autonomy.deploy._http_server.App.run` instead of `flask.Flask.run`.
  The real production code uses our inlined Flask-compatible shim, so
  the old patch was a no-op and let the test hang indefinitely on
  macOS/Windows CI runners.

Cascade: `autonomy packages lock` picked up hash changes in
counter/aea-config.yaml, register_reset_recovery/aea-config.yaml,
register_termination/aea-config.yaml, solana_transfer_agent/aea-config.yaml,
services/counter/service.yaml, and doc IPFS hashes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@OjusWiZard OjusWiZard requested a review from Copilot April 19, 2026 09:57
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR reduces open-autonomy’s runtime dependency footprint by moving non-core dependencies behind optional extras, swapping several third-party libraries for open-aea helpers/stdlib alternatives, and re-aligning Valory package manifests and tooling so dependency checks remain consistent.

Changes:

  • Slimmed core runtime dependencies to open-aea[all]==2.2.1 + open-aea-cli-ipfs==2.2.1, introducing opt-in extras (e.g., chain, docker, hwi) and updating tox/poetry/setup metadata accordingly.
  • Replaced a range of third-party usages (requests, jsonschema, dotenv, hexbytes, parts of eth_*) with open-aea helpers or stdlib and adjusted tests/contracts/skills to match.
  • Swept packages/valory/** manifests and hashes (YAML fingerprints/IPFS hashes/docs) to reflect direct imports and updated tooling/docs to keep check-dependencies and related CI envs passing.

Reviewed changes

Copilot reviewed 137 out of 138 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tox.ini Reworked dependency sets + mypy sections for new footprint.
setup.py Minimized base deps; added chain/docker extras; updated classifiers.
pyproject.toml Reduced core deps; added extras + local-path plugin dev deps.
tests/test_deployments/test_app.py Removed Flask typing dependency in tests.
tests/test_autonomy/test_cli/test_service/test_service_manager.py Removed hexbytes usage in tx data.
tests/test_autonomy/test_cli/test_replay/test_tendermint.py Patched tests to use inline HTTP app shim.
tests/test_autonomy/test_cli/test_deploy/test_build/test_deployment.py Replaced dotenv usage with simple env file parsing.
tests/test_autonomy/test_cli/test_analyse/test_specs.py Swapped jsonschema ValidationError to aea.helpers.json_schema.
plugins/aea-test-autonomy/setup.py Collapsed deps to open-autonomy[all,docker].
plugins/aea-helpers/setup.py Trimmed deps; rely on open-autonomy transitives.
plugins/aea-helpers/aea_helpers/generate_contract_list.py Switched requests to aea.helpers.http_requests.
plugins/aea-helpers/aea_helpers/config_replace.py Switched dotenv loading to aea.helpers.base.load_env_file.
plugins/aea-helpers/aea_helpers/check_doc_hashes.py Switched requests usage/exceptions to aea.helpers.http_requests.
plugins/aea-helpers/aea_helpers/check_dependencies.py Replaced toml with tomllib/tomli fallback.
plugins/aea-helpers/aea_helpers/bump_dependencies.py Switched GitHub fetches to aea.helpers.http_requests.
plugins/aea-helpers/aea_helpers/bin_template.py Dropped unused multiaddr codec imports.
packages/valory/skills/transaction_settlement_abci/tests/test_tools/test_integration.py Dropped web3.types wrappers in tests.
packages/valory/skills/transaction_settlement_abci/tests/test_behaviours.py Dropped Nonce wrapper usage in tests.
packages/valory/skills/transaction_settlement_abci/test_tools/integration.py Dropped Nonce/Wei wrappers in test tools.
packages/valory/skills/transaction_settlement_abci/skill.yaml Updated fingerprints + dependency decls.
packages/valory/skills/transaction_settlement_abci/models.py Switched nonce/gas typing to plain ints.
packages/valory/skills/transaction_settlement_abci/behaviours.py Switched tx typing to Dict/int and dropped web3 type wrappers.
packages/valory/skills/test_solana_tx_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/test_ipfs_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/test_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/termination_abci/skill.yaml Updated fingerprints + removed hexbytes dep.
packages/valory/skills/termination_abci/behaviours.py Replaced HexBytes payloads with bytes.
packages/valory/skills/squads_transaction_settlement_abci/skill.yaml Updated fingerprints + slimmed deps.
packages/valory/skills/squads_transaction_settlement_abci/models.py Switched nonce/gas typing to plain ints.
packages/valory/skills/slashing_abci/skill.yaml Updated fingerprints + removed hexbytes dep.
packages/valory/skills/reset_pause_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/registration_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/register_termination_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/register_reset_recovery_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/register_reset_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/offend_slash_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/offend_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/identify_service_owner_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/funds_forwarder_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/counter/skill.yaml Updated fingerprints/hashes.
packages/valory/skills/abstract_round_abci/utils.py Dropped typing_extensions + eth_typing bls aliases.
packages/valory/skills/abstract_round_abci/tests/test_models.py Switched Literal/TypedDict imports to stdlib typing.
packages/valory/skills/abstract_round_abci/tests/test_behaviours_utils.py Dropped pytz for datetime.timezone.utc.
packages/valory/skills/abstract_round_abci/test_tools/rounds.py Guarded pytest import with stub for runtime importability.
packages/valory/skills/abstract_round_abci/test_tools/common.py Guarded pytest import with stub for runtime importability.
packages/valory/skills/abstract_round_abci/skill.yaml Updated fingerprints + pruned deps.
packages/valory/skills/abstract_round_abci/behaviour_utils.py Dropped pytz; use datetime.timezone.utc.
packages/valory/skills/abstract_abci/skill.yaml Updated fingerprints/hashes.
packages/valory/services/register_reset/service.yaml Updated agent hash reference.
packages/valory/services/counter/service.yaml Updated agent hash reference.
packages/valory/contracts/staking_token/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/staking_activity_checker/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/squads_multisig/contract.yaml Dropped solders dep; rely on ledger plugin.
packages/valory/contracts/squads_multisig/contract.py Replaced solders.transfer with SolanaApi helper call.
packages/valory/contracts/sign_message_lib/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/service_registry_token_utility/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/service_registry/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/service_registry/contract.py Removed web3 type-only imports; use EthereumApi casts.
packages/valory/contracts/service_manager/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/registries_manager/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/recovery_module/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/poly_safe_creator_with_recovery_module/contract.yaml Dropped eth-abi/eth-utils direct deps; rely on ledger api.
packages/valory/contracts/poly_safe_creator_with_recovery_module/contract.py Switched checksum/encode to ledger_api.api.*.
packages/valory/contracts/multisend/tests/test_contract.py Replaced HexBytes with bytes in tests.
packages/valory/contracts/multisend/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/multisend/contract.py Replaced HexBytes/Web3 helpers; thread ledger_api for decoding.
packages/valory/contracts/multicall2/contract.yaml Pruned explicit web3 dep.
packages/valory/contracts/mech_marketplace/contract.yaml Dropped eth-* + hexbytes deps; keep ledger plugin.
packages/valory/contracts/mech_marketplace/contract.py Reworked event log decoding to ContractEvent.process_log.
packages/valory/contracts/gnosis_safe_proxy_factory/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/gnosis_safe_proxy_factory/contract.py Replaced web3 NewTypes with Dict/int runtime values.
packages/valory/contracts/gnosis_safe/tests/test_contract.py Replaced HexBytes with raw bytes in mocked receipts.
packages/valory/contracts/gnosis_safe/encode.py Dropped eth-abi/pycryptodome; use ledger_api.api.codec + keccak.
packages/valory/contracts/gnosis_safe/contract.yaml Pruned many direct deps; keep open-aea-ledger-ethereum + requests/web3.
packages/valory/contracts/gnosis_safe/contract.py Replaced hexbytes/packaging/eth-utils usage; updated tx hash encoding.
packages/valory/contracts/erc8004_identity_registry_bridger/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/erc8004_identity_registry/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/erc8004_identity_registry/contract.py Switched keccak/checksum/encode to ledger_api.api.*.
packages/valory/contracts/erc20/contract.yaml Pruned many direct deps; keep ledger plugin.
packages/valory/contracts/component_registry/contract.yaml Declared ethereum ledger plugin as direct dep.
packages/valory/contracts/agent_registry/contract.yaml Pruned test-only/web3 entries from deps.
packages/valory/contracts/agent_registry/contract.py Switched checksum ops to ledger_api.api.to_checksum_address.
packages/valory/contracts/agent_mech/contract.yaml Pruned eth_typing/web3 entries; keep ledger plugin.
packages/valory/contracts/agent_mech/contract.py Removed web3 type-only imports; use plain str/Dict.
packages/valory/connections/ipfs/connection.yaml Dropped ipfshttpclient/requests deps; keep open-aea-cli-ipfs.
packages/valory/connections/ipfs/connection.py Switched to aea_cli_ipfs.ipfs_client.IPFSError.
packages/valory/connections/abci/connection.yaml Pruned test-only deps; widened protobuf to <7,>=5.
packages/valory/agents/test_ipfs/aea-config.yaml Updated component hashes.
packages/valory/agents/test_abci/aea-config.yaml Updated component hashes.
packages/valory/agents/solana_transfer_agent/tests/base.py Switched direct web3 usage to EthereumApi.
packages/valory/agents/solana_transfer_agent/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/registration_start_up/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/register_termination/tests/base.py Switched direct web3 usage to EthereumApi.
packages/valory/agents/register_termination/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/register_reset_recovery/tests/base.py Switched requests to aea.helpers.http_requests.
packages/valory/agents/register_reset_recovery/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/register_reset/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/offend_slash/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/counter/tests/test_counter.py Switched requests to aea.helpers.http_requests.
packages/valory/agents/counter/aea-config.yaml Updated hashes + pruned test tooling dep.
packages/valory/agents/abstract_abci/aea-config.yaml Updated hashes + pruned test tooling dep.
docs/guides/set_up.md Updated example package hash.
docs/guides/overview_of_the_development_process.md Updated example registry hashes.
docs/guides/deploy_service.md Updated example service hash.
docs/counter_example.md Updated example service hash.
docs/configure_service/analise_test.md Updated example agent hash.
docs/api/plugins/aea_helpers/bump_dependencies.md Synced API docs for return type change.
docs/api/deploy/generators/docker_compose/base.md Synced API docs for optional docker type hint.
docs/api/deploy/_http_server.md Added API docs for the stdlib HTTP server shim.
docs/api/contracts/gnosis_safe_proxy_factory/contract.md Synced API docs for return type change.
docs/api/contracts/gnosis_safe/tests/test_contract.md Synced API docs for HexBytes → bytes.
docs/api/contracts/gnosis_safe/encode.md Synced API docs for ledger_api-threaded encoder.
docs/api/contracts/gnosis_safe/contract.md Synced API docs for type/signature changes.
docs/api/chain/exceptions.md Added docs for lazy ConnectionError resolver.
docs/advanced_reference/commands/autonomy_fetch.md Updated example service hash.
autonomy/replay/tendermint.py Switched Flask import to inline shim.
autonomy/deploy/generators/localhost/tendermint/app.py Switched Flask/Werkzeug to inline shim + aea http_requests.
autonomy/deploy/generators/docker_compose/base.py Made docker optional; added install hint when missing.
autonomy/deploy/base.py Dropped typing_extensions TypedDict usage.
autonomy/constants.py Updated pinned abstract_round_abci hash constant.
autonomy/configurations/validation.py Switched jsonschema resolver to aea helper.
autonomy/cli/helpers/env.py Switched dotenv usage to load_env_file.
autonomy/cli/helpers/chain.py Swapped texttable with inline renderer; swapped connection error type.
autonomy/chain/utils.py Switched requests/http error handling to aea helpers + lazy web3 requests error.
autonomy/chain/tx.py Switched RPC connection error catching to lazy resolver.
autonomy/chain/subgraph/client.py Dropped gql client; post queries via aea http helper.
autonomy/chain/service.py Dropped HexBytes wrapper for multisend tx payloads.
autonomy/chain/exceptions.py Added lazy requests.exceptions.ConnectionError resolver.
autonomy/analyse/service.py Switched jsonschema imports to aea helper; updated error substring matching.
autonomy/analyse/abci/app_spec.py Switched Draft4Validator import to aea helper.
SECURITY.md Updated supported versions table to 0.21.x.
LICENSE Extended copyright year range.
CLAUDE.md Added repo workflow note about locking/hashes timing.
.pylintrc Updated ignored-modules list for removed/optional deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/valory/contracts/gnosis_safe/contract.py
Comment thread packages/valory/contracts/gnosis_safe/contract.py
Comment thread packages/valory/contracts/gnosis_safe/contract.py
Comment thread packages/valory/contracts/gnosis_safe/contract.py
Comment thread autonomy/chain/subgraph/client.py
Comment thread autonomy/chain/exceptions.py
Comment thread SECURITY.md
DavidMinarsch and others added 3 commits April 19, 2026 13:28
- 1913: typo plus deprecation note for --aev flag
- 1893: docs section on sharing params across skills
- 2203: clearer FSM timeout event error message
- 1712: remove unused wait-for-it.sh from tendermint Dockerfiles

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… rerun doc links

- gnosis_safe.get_raw_safe_transaction_hash: restore str-or-bytes handling
  at contract.py:298. The HexBytes->hex refactor in b2228dd broke the
  callsite in autonomy/chain/service.py:805 which passes the web3
  build_transaction "data" field (a 0x-prefixed hex str) instead of bytes.
- BaseTestEnd2End.teardown_method: remove agent folders and clear
  per-class subprocess/agent state after each test method so
  pytest.mark.flaky reruns and parametrize iterations can re-fetch
  agents without hitting aea's "already exists" guard.
- main_workflow.yml: drop stale commented-out Check-doc-links step;
  rename the remaining step to reflect that tox -e check-doc-links-hashes
  runs both the tomte link check and IPFS hash check (closes #2235).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Our explicit requests<2.33.0,>=2.28.1 pin was actively blocking the CVE
fixes pulled in via open-aea-ledger-ethereum@2.2.1 (requests>=2.32.5,<3).
The ecdsa>=0.15 pin was looser than needed. Dropping the version bounds
in both lets the transitive constraints from the open-aea plugins apply
directly, matching main open-aea at valory-xyz/open-aea#pyproject.toml
(requests>=2.32.5,<3; ecdsa>=0.19.2,<0.20).

Resolves #2407.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@DavidMinarsch DavidMinarsch mentioned this pull request Apr 19, 2026
DavidMinarsch and others added 2 commits April 19, 2026 16:49
deployments/Dockerfiles/development/Pipfile:
  - Bump requests from ==2.27.1 (2021) to >=2.33.0,<3 — clears 4
    alerts (CVE-2023-32681, CVE-2024-35195, CVE-2024-47081,
    CVE-2026-25645) on the valory/open-autonomy-dev image.
  - Bump watchdog from ==2.1.6 (2021) to >=3,<7. No active CVE but
    the pin is very stale; the APIs used by watcher.py (Observer,
    FileSystemEventHandler, EVENT_TYPE_CLOSED) are stable across
    that range.

poetry.lock:
  - Targeted poetry update requests (2.32.5 to 2.33.1) — clears
    CVE-2026-25645.
  - Targeted poetry update web3 (7.14.1 to 7.15.0) — clears
    CVE-2026-40072; installed version was already 7.15.0, the
    lockfile was trailing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auto-generated API reference for the new teardown_method added in
commit 7f22731 (e2e rerun cleanup hook).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 19, 2026

Codecov Report

❌ Patch coverage is 96.97733% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.75%. Comparing base (690704c) to head (341b047).
⚠️ Report is 39 commits behind head on main.

Files with missing lines Patch % Lines
packages/valory/contracts/gnosis_safe/contract.py 82.75% 5 Missing ⚠️
...ages/valory/contracts/service_registry/contract.py 50.00% 4 Missing ⚠️
...ckages/valory/contracts/agent_registry/contract.py 0.00% 2 Missing ⚠️
...nomy/deploy/generators/localhost/tendermint/app.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2477      +/-   ##
==========================================
+ Coverage   92.55%   92.75%   +0.19%     
==========================================
  Files         243      244       +1     
  Lines       17258    17492     +234     
==========================================
+ Hits        15974    16225     +251     
+ Misses       1284     1267      -17     
Flag Coverage Δ
unittests 92.75% <96.97%> (+0.19%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

DavidMinarsch and others added 5 commits April 19, 2026 17:43
tests/data/logs/aea_0.txt (added in 1b9bd2e, 2023) contained 4
occurrences of a real Google Sheets API key embedded in sample log
URLs. The fixture is still needed by tests/test_autonomy/test_cli/
test_analyse/test_logs.py for autonomy-analyse-logs assertions
(timestamps, round names, behaviour strings), so the key is redacted
in place with a <GOOGLE_API_KEY> placeholder rather than deleting
the file.

Note: the key has been publicly visible since 2023 so this scrub
alone is insufficient — the key owner should rotate/revoke the key
in GCP console. All 11 test_logs.py cases still pass after the
replacement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New unit-test files and extensions that bring every file codecov
flagged on this PR to 100% patch coverage (except small contract
casts inside docker-gated integration paths, which remain gated):

- tests/test_autonomy/test_deploy/test_http_server.py: 53 tests
  for the Flask-compatible shim — Request/Response, jsonify,
  _Args coercion, _Route, _RequestProxy, App dispatch + error
  handlers, _to_response, _TestClient/_TestResponse, App.run
  delegation, run_app server_close via finally, and an integration
  test against a real threaded HTTP server.

- packages/valory/contracts/gnosis_safe/tests/test_encode.py: 24
  tests for the EIP-712 encode helpers. Uses a lightweight
  ledger_api stub whose keccak and codec._registry.get_encoder are
  deterministic so the tests exercise every branch of encode_value
  (string / bytes / struct / array / primitive) and the schema /
  dependency walk without needing a real ethereum provider.

- tests/test_autonomy/test_chain/test_utils.py: +6 tests for
  resolve_component_id (service / agent / component dispatch,
  RPC connection error, IPFS connection error, JSON decode error),
  parse_public_id_from_metadata strip-suffix, and
  is_service_manager_token_compatible_chain.

- tests/test_autonomy/test_chain/test_subgraph.py: +2 tests for
  SubgraphClient._query — happy path plus the GraphQL-errors raise
  path.

- tests/test_autonomy/test_deploy/test_deployment_generators.py: +1
  test covering the DOCKER_INSTALLED=False branch of
  get_docker_client via monkeypatch.

Also picked up the package-hash cascade from
packages/valory/contracts/gnosis_safe/tests/test_encode.py being
added (skill/agent YAMLs touched by autonomy packages lock) plus
the auto-regenerated docs entry
docs/api/contracts/gnosis_safe/tests/test_encode.md and the
corresponding IPFS-hash refresh in docs/package_list.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Docker-images subsection to CLAUDE.md under Testing and a
Running-tests-locally section to CONTRIBUTING.md that lists the
minimum set of images needed for integration and e2e tests:

- valory/autonolas-registries:latest   (registries_scope_class)
- valory/acn-node:latest                (UseACNNode)
- tendermint/tendermint:v0.34.19        (UseTendermint, test_runtime)
- valory/slow-tendermint-server:0.1.0   (register_reset recovery)
- valory/open-autonomy-tendermint:*     (built locally from the
                                         deployments/Dockerfiles/
                                         tendermint/ Dockerfile)

Also note that the main CI workflow additionally pulls
valory/contracts-amm, valory/safe-contract-net and
trufflesuite/ganache:beta, but those fixture classes have no
callers in this repo and can be skipped locally. Flag that the two
docs should be kept in sync with main_workflow.yml when the image
set changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- packages/valory/contracts/gnosis_safe/contract.py (4 filter_params
  dicts at lines 694, 775, 820, 875): switch the filter keys from
  snake_case from_block/to_block to camelCase fromBlock/toBlock.
  web3.py v7 only normalises the address key in FILTER_PARAM_NORMALIZERS;
  snake_case variants pass straight through to the JSON-RPC server,
  which ignores unknown keys and returns logs for the full range
  rather than the requested window. Pre-existing bug on main; confirmed
  mech_marketplace/contract.py:609-611 already uses the correct form.

- autonomy/chain/subgraph/client.py: raise RuntimeError on HTTP
  4xx/5xx before attempting resp.json(). Restores the "clear HTTP
  error" behaviour we had under the gql-based client before the
  aea.helpers.http_requests swap. Added a unit test that asserts
  we do not call .json() on an error response.

- autonomy/chain/exceptions.py: update the ImportError hint to
  recommend pip install open-autonomy[chain] (the new user-facing
  extra in this PR), falling back to open-aea-ledger-ethereum.

Hash cascade for the gnosis_safe change re-locked via
autonomy packages lock; doc IPFS hashes refreshed via fix-doc-hashes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI failures on commit 7fc6512:

1. `linter_checks` bandit — 5x B310 (`urllib.request.urlopen`) flagged
   in tests/test_autonomy/test_deploy/test_http_server.py. These are
   legitimate uses against a hard-coded 127.0.0.1 test server; added
   `# nosec B310` on each call with a justifying inline comment.

2. `copyright_doc_and_dependencies_check` — the workflow runs
   `tomte format-copyright` as its FIRST step, then `tox -e
   check-api-docs`, which checks `git diff --quiet`. Two test files
   modified in this PR still had stale copyright years, so
   format-copyright bumped them (2023-2024 -> 2023-2026 and 2024 ->
   2024-2026), dirtying the tree and failing check-api-docs.

   The underlying issue is that my pre-commit routine was missing a
   `tox -e fix-copyright` step. CLAUDE.md Pre-commit section now
   spells the full ordered sequence out, with a note pointing at
   this exact failure mode so the next pass catches it before push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@DhairyaPatel7
Copy link
Copy Markdown
Collaborator

Review — dependency cleanup PR

Scope note: 100 files / 3701+/1635- / 38 commits. Bundled intentionally per the description; that's defensible but makes regression bisects harder. Findings below, blocking first.

Blocking

1. pyproject.tomlsetup.py drift — the PyPI-facing manifest is missing runtime deps

pyproject.toml declares as hard main deps: web3, requests, aiohttp, certifi, multidict, asn1crypto, ecdsa, py-ecc, grpcio, open-aea-ledger-cosmos (plus protobuf/pytest-asyncio shims).

setup.py install_requires lists only open-aea[all]==2.2.1 and open-aea-cli-ipfs==2.2.1.

Verified against the installed 2.2.1 metadata:

  • open-aea[all] brings only click, coverage, packaging, pytest, pyyaml
  • open-aea-cli-ipfs brings only click, open-aea

None of the other pyproject-declared deps arrive transitively. The comment in pyproject.toml says "setup.py is the authoritative distribution manifest" — which is exactly why the omission matters: pip install open-autonomy (or [all]) from PyPI won't ship open-aea-ledger-cosmos, aiohttp, certifi, multidict, asn1crypto, grpcio, py-ecc, ecdsa, etc. If the intent is that the lean install never reaches those imports, please add a CI smoke test: fresh venv + pip install open-autonomy[all] + python -c "import autonomy.cli.core" + a minimal skill import. Otherwise, add them to setup.py.

2. packages/valory/contracts/squads_multisig/contract.py:626 — no install path pulls the Solana plugin

The call ledger_api.api.get_transfer_tx(from_pubkey, to_pubkey, lamports) is correct — I confirmed SolanaApi.api returns SolanaApiClient which exposes get_transfer_tx(from_account, to_account, amount). The concern is downstream: open-aea-ledger-solana is commented out in both pyproject.toml and setup.py (anchorpy/cachetools conflict). Any consumer of the squads_multisig contract has no declared install path for the plugin. Confirm the package YAML declares the plugin as a dep and that the re-enable is tracked as a known follow-up in the description (it is — fine) and in an issue.

Non-blocking

3. autonomy/chain/subgraph/client.py:86payload["data"] raises KeyError if the response has neither errors nor data. Guard it: if "data" not in payload: raise RuntimeError(...).

4. autonomy/deploy/_http_server.py:441body = self.rfile.read(content_length) has no cap. Malicious Content-Length wastes memory before dispatch. Localhost-only sidecar so low risk, but a constant MAX_BODY with 413 is cheap defense-in-depth (matches Flask's MAX_CONTENT_LENGTH).

5. autonomy/deploy/_http_server.py:_to_response — accepts 2-tuple only; Flask also supports (body, status, headers). Not needed today, but stricter-than-Flask means a handler surprise later is silent. Either document the restriction or support the 3-tuple form.

6. autonomy/deploy/generators/localhost/tendermint/app.py:347-354 — 404/500 errorhandlers return plain-text bodies ("Not Found", "Error Closing Node") with mimetype="application/json". Use jsonify({"error": ...}) for consistency with the other handlers. Pre-existing, but touched by this PR.

7. deployments/Dockerfiles/tendermint/Dockerfile:21requests==2.28.1 still pinned (CVE-2023-32681, CVE-2024-35195). PR description claims "Dependabot 15 → 0" but this container pin was not updated. Defensible if the container only talks to localhost tendermint RPC, but worth noting the inconsistency with the description.

8. packages/valory/contracts/gnosis_safe/encode.py — reach-through to ledger_api.api.codec._registry.get_encoder(typ). Point of the PR is to avoid eth_abi direct dep, but _registry is private API. Mock-based tests in tests/test_encode.py won't catch a real eth_abi refactor. Add an integration test against a real EthereumApi (or point to the parity check already in CI, which the description references).

9. autonomy/chain/exceptions.py:40-48except get_requests_connection_error() as e: evaluates the function every time the except clause is tested. If the plugin is missing AND the try body raises for any other reason, the ImportError replaces the original exception. Accept as-is (matches the documented pattern), but note the debuggability cost.

10. pyproject.toml lines 68-74 — the protobuf/pytest-asyncio entries that only exist to satisfy check-dependencies. TODO comment acknowledges this; please file a tracking issue for the checker patch and reference it.

11. packages/valory/contracts/gnosis_safe/encode.py:86 — docstring typo ("method struction defintion") in a file touched by this PR.

12. [tool.poetry.dependencies] pattern ledger_api = cast(EthereumApi, ledger_api) at 16 classmethod entries — noisy; a single _as_eth(ledger_api) helper would tighten it. Style-level, not blocking.

PR description

  • "CI green on py3.10-linux through py3.14-linux" is still a TODO — confirm on current HEAD before merge given the version-sensitive plugin interactions.
  • Install matrix is clear; consider adding a line noting that [all] does not include [docker] or [hwi] (it's in the prose but not in the matrix table).

@DavidMinarsch
Copy link
Copy Markdown
Contributor Author

Thanks @DhairyaPatel7 — worked through each point. Audit results and disposition below. No code changes in this PR for the remaining items; tracking issues + a follow-up PR listed at the bottom.

Blocking

1. pyproject.tomlsetup.py drift — not a regression.

Verified against installed 2.2.1 metadata — your reading of open-aea[all] is correct (click, coverage, packaging, protobuf, pytest, pyyaml + pywin32). The lean pip install open-autonomy really does ship only open-aea[all] + open-aea-cli-ipfs + whatever the requested extra adds.

Cross-checked the actual import surface:

  • No module under autonomy/ has a top-level import web3 / import requests / import aiohttp / import grpc / import ecdsa / import py_ecc / import asn1crypto / import multidict / import certifi / import aea_ledger_ethereum / from eth_account .... grep -rE '^(import|from) (web3|aea_ledger_ethereum|eth_account|requests|aiohttp|grpc|ecdsa|py_ecc|asn1crypto|multidict|certifi) ' autonomy/ returns empty.
  • autonomy/cli/core.py + its import tree (including autonomy.chain.config, autonomy.cli.helpers.chain) is pure stdlib + aea.* + internal. autonomy --help works on a fully lean install.
  • Packages that DO import those at top level (abci, http_client, p2p_libp2p_client connections; abstract_round_abci/utils.py) declare their runtime deps in the per-package YAML, and aea install pulls them inside the agent container at deploy time. This is the same model main uses — same gap existed there (main's setup.py was missing grpcio/ecdsa/py-ecc/asn1crypto/multidict/certifi too). Our PR moved a few deps (aiohttp, requests, protobuf) from setup.py into pyproject.toml only; none of those are reached by the lean-install CLI surface.
  • CI's install_check job already does pip install .[all] --no-cache && autonomy --help on Ubuntu 3.14 — it has been passing on every PR push, which is exactly the smoke test you proposed.

So the lean install isn't broken. What IS worth tightening is the comment in pyproject.toml above the "TODO(cleanup)" block — it should say explicitly "these entries satisfy check-dependencies against the dev environment; setup.py remains the authoritative PyPI manifest and is intentionally narrower". I'll include that in the follow-up PR along with the CI smoke-test expansion you suggested (add a matched pip install open-autonomy — no extras — smoke test alongside the [all] one).

2. packages/valory/contracts/squads_multisig/contract.py:626 — correct as-is.

Verified contract.yaml already declares:

dependencies:
  open-aea-ledger-solana:
    version: ==2.2.1

So downstream consumers pulling the contract get the plugin via aea install. The framework-side gap (commented-out plugin in pyproject.toml/setup.py) is an anchorpy→cachetools conflict with tomte[tox]'s tox 4.46. PR description's "Known follow-ups" section mentions this, but there is no tracked issue — will open one.

Non-blocking

3. subgraph/client.py:86 — accepted. GraphQL spec guarantees one of errors/data, so the KeyError path is narrow, but the guard is cheap. Follow-up.

4. _http_server.py:441 body cap — accepted. Localhost-only, but constant + 413 response is trivial. Follow-up.

5. _to_response 3-tuple — declining. Zero current callers use the 3-tuple form. The module docstring already says "minimal Flask-compatible"; will add a one-line explicit mention of supported return shapes so the restriction is documented. Follow-up.

6. 404/500 handler mimetype mismatch — accepted. Affects both copies (autonomy/deploy/generators/localhost/tendermint/app.py:347-354 and deployments/Dockerfiles/tendermint/app.py:322, 328). Pre-existing from before this PR (we only touched the from flask import ...from autonomy.deploy._http_server import ... lines in the localhost copy). Follow-up.

7. deployments/Dockerfiles/tendermint/Dockerfile:24 requests==2.28.1 — I missed this, will be handled in a follow-up PR. The sidecar's app.py:32, 225, 285 actively uses requests.get(...), so bumping the pin (to >=2.33.0,<3) is a real CVE fix. PR description's "Dependabot 15 → 0" claim is correct for the open-autonomy-dev image + poetry.lock; the tendermint image was a separate miss.

8. encode.py codec._registry private API — acknowledged, pre-existing. Main also used default_codec._registry directly (same private access, just via eth_abi). Our refactor changed the access path, not the private-ness. The byte-parity check vs the old path is in the test suite; real-EthereumApi integration coverage would catch an eth_abi refactor and is a good addition — follow-up.

9. except get_requests_connection_error() — accept. Consistent with load_hwi_plugin in autonomy.chain.config. The replacement-on-plugin-missing scenario is self-consistent (web3 itself wouldn't have imported successfully if the plugin is missing). A cache-once variant would tighten it stylistically — low priority.

10. pyproject.toml shim entries — will file tracking issue for aea-helpers check-dependencies to understand optional = true / dev-group entries so the shims can go away.

11. encode.py:73 "method struction defintion" — accepted. Pre-existing typo. Follow-up.

12. cast(EthereumApi, ledger_api) x41 — declining. Style-level, reviewer agrees non-blocking. A single helper would tighten but at the cost of a one-level-deeper stack frame in all chain-path exceptions. Trade-off not worth the churn this round.

PR description

Updated:

  • Ticked the "CI green py3.10-3.14" item — test (ubuntu, 3.10-3.14) all green; e2e 3.14 green on rerun.
  • Added a line on the install matrix clarifying [all] excludes [docker]/[hwi] (it was in the prose, agreed it should be on the table row).

Follow-up plan

I'll open a dedicated PR for:

And tracking issues for:

@DavidMinarsch DavidMinarsch merged commit a06883c into main Apr 20, 2026
40 of 42 checks passed
@DavidMinarsch DavidMinarsch deleted the chore/dependency-cleanup-clean branch April 20, 2026 08:27
@DhairyaPatel7 DhairyaPatel7 mentioned this pull request Apr 21, 2026
10 tasks
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.

4 participants