Skip to content

Commit e57634e

Browse files
Merge pull request #913 from valory-xyz/chore/release-v2.2.6
chore: release v2.2.6
2 parents 1696ed7 + f4cd359 commit e57634e

22 files changed

Lines changed: 68 additions & 27 deletions

File tree

HISTORY.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
# Release History - open AEA
22

3-
## Unreleased
3+
## 2.2.6 (2026-05-14)
44

5-
Plugins:
5+
Framework:
66

7-
- `open-aea-ledger-ethereum`: tightens `max_gas_fast` per chain in `CHAIN_EIP1559_OVERRIDES`. Until now low-fee chains (Gnosis, Optimism, Base, Mode, Fraxtal, Arbitrum One) inherited the chain-agnostic 1500 gwei default, so a fee-oracle anomaly could authorise a tx priced 100×+ above the chain's normal range before the cap engaged. A production market-creator deployment on Gnosis submitted a routine multisend at 694 gwei (~700× the validator floor of 1 gwei) on 2026-04-22 ([tx 0x727262d9…](https://gnosisscan.io/tx/0x727262d9238881e72eeaeb01bf88b234b380c6d3d2dc9e60fcb71b07354933bd)), paying 0.637 xDAI — ~45% of the agent's 30-day spend — while the inherited 1500 gwei ceiling did not trigger the fallback. New per-chain ceilings: Gnosis 30 gwei, Optimism / Base 100 gwei, Mode / Fraxtal 50 gwei, Arbitrum One 5 gwei. Sized to preserve operability during legitimate congestion (Base's March 2024 Dencun memecoin frenzy sustained ~24 gwei averages with bursts >100 gwei in individual blocks; Gnosis Tornado-deposit waves briefly hit 5–8 gwei) while bounding fee-oracle anomalies. Polygon (10000 gwei ceiling) and Celo (default 1500 gwei) are unchanged. #909
7+
- `aea.helpers.base.try_decorator`: enriches the swallowed-exception log line with the wrapped function's qualified name and the exception type. The previous `log(error_message.format(e))` rendered a `KeyError("maxFee")` as just `"...'maxFee'"`; the line now reads `"... [function=<qualname>, exc_type=KeyError]"` so swallowed failures are diagnosable without changing the catch semantics. The public docstring also documents the `raise_on_try=True` escape hatch. #891 #910
88

99
Packages:
1010

11-
- `valory/ledger` connection: aligns per-chain `max_gas_fast` in `connection.yaml` with the new plugin-level ceilings — Gnosis 30, Optimism / Base 100, Mode / Fraxtal 50, Arbitrum One 5. Self-documenting and defensible if the plugin defaults ever drift. #909
11+
- `valory/ledger` connection: caps the per-attempt retry sleep in `get_transaction_receipt` / `get_transaction` at `MAX_RETRY_DELAY = 60.0`. Without the cap, the linear backoff `retry_timeout * attempts` grew unboundedly across the retry budget; capping bounds the worst-case loop while preserving the retry count. #891 #910
12+
- `valory/ledger` connection: owns a dedicated `ThreadPoolExecutor` sized by a new `max_thread_workers` config (default 32) and shuts it down with `cancel_futures=True` on disconnect. Previously the dispatchers passed `executor=None` and shared Python's default asyncio thread pool with every other agent component; under sustained RPC outage `RotatingHTTPProvider.make_request`'s sync sleeps accumulated abandoned threads in the shared pool. The dedicated executor isolates ledger work and surfaces the resource cost as operator-tunable config. #891 #910
13+
- `valory/ledger` connection: lowers the shipped `retry_attempts` default in `connection.yaml` from 240 to 60 (and the in-code `MAX_ATTEMPTS` / `RequestDispatcher.retry_attempts` defaults from 120 to 60 to match). Now that `RotatingHTTPProvider` handles transport-layer rotation per call, the dispatcher budget is a layered backstop rather than the primary retry mechanism; the tighter default drops worst-case per-slot pool occupancy from ~230 minutes to ~50 minutes. Operators wanting the old budget can override in their connection config. #891 #910
14+
- `valory/ledger` connection: improves the dispatcher's retry-loop warning log to include the exception type — `self.logger.warning(e)` previously rendered a `KeyError("maxFee")` as just `"maxFee"`. Now uses `"%s: %s", type(e).__name__, e` for both the receipt and transaction loops. #891 #910
15+
- `valory/ledger` connection: typed `max_thread_workers` as `int` at the assignment site so a stringified YAML value cannot slip past mypy and explode at `ThreadPoolExecutor(max_workers=...)`. #891 #910
16+
17+
Plugins:
18+
19+
- `open-aea-ledger-ethereum`: tightens `max_gas_fast` per chain in `CHAIN_EIP1559_OVERRIDES`. Until now low-fee chains (Gnosis, Optimism, Base, Mode, Fraxtal, Arbitrum One) inherited the chain-agnostic 1500 gwei default, so a fee-oracle anomaly could authorise a tx priced 100×+ above the chain's normal range before the cap engaged. A production market-creator deployment on Gnosis submitted a routine multisend at 694 gwei (~700× the validator floor of 1 gwei) on 2026-04-22 ([tx 0x727262d9…](https://gnosisscan.io/tx/0x727262d9238881e72eeaeb01bf88b234b380c6d3d2dc9e60fcb71b07354933bd)), paying 0.637 xDAI — ~45% of the agent's 30-day spend — while the inherited 1500 gwei ceiling did not trigger the fallback. New per-chain ceilings: Gnosis 30 gwei, Optimism / Base 100 gwei, Mode / Fraxtal 50 gwei, Arbitrum One 5 gwei. Sized to preserve operability during legitimate congestion (Base's March 2024 Dencun memecoin frenzy sustained ~24 gwei averages with bursts >100 gwei in individual blocks; Gnosis Tornado-deposit waves briefly hit 5–8 gwei) while bounding fee-oracle anomalies. Polygon (10000 gwei ceiling) and Celo (default 1500 gwei) are unchanged. `valory/ledger` `connection.yaml` mirrors the plugin-level ceilings. #909 #911
20+
- `open-aea-ledger-ethereum`: gas-price strategies (Polygon EIP1559 and Eth Gas Station) broaden the `except` clause to cover `(requests.exceptions.RequestException, ValueError, KeyError, TypeError)` so malformed-response failure modes hit the documented fallback. `response.json()` raises `JSONDecodeError` (a `ValueError` subclass) on non-JSON 200; `[speed]` / `["maxFee"]` subscripts raise `KeyError` on schema drift; a non-dict 200 body (a JSON `null`, array, or string from a CDN serving an error page) raises `TypeError` on the raw subscript. The previous `except requests.exceptions.RequestException` only caught network-shaped errors, so the documented fallback was bypassed for everything else. Both strategies now also emit a `WARNING` carrying the exception type so transport failures and schema drift are distinguishable in operator logs. #891 #910
21+
- `open-aea-ledger-ethereum`: `RotatingHTTPProvider` docstring documents the interaction with the ledger connection's dedicated `ThreadPoolExecutor``make_request` is synchronous and uses `time.sleep` between retries, so worker threads in the connection's pool can be held for the duration of a retry sequence. Operators expecting high ledger concurrency under RPC degradation should size `max_thread_workers` to exceed peak concurrent retries for their RPC topology. #891 #910
22+
- `open-aea-cli-ipfs`: routes the success-path `json.loads` calls in `_api_post`, `add`, and `add_bytes` through a single `_safe_json_loads` helper that raises a typed `StatusError` (with a printable, length-capped body preview) on non-JSON 200 responses. Previously a 200 carrying a non-JSON body (CDN HTML error page, truncated payload, gzipped body) raised an unhandled `ValueError` to the caller. The body preview replaces non-printable bytes with `.` and truncates at 80 chars so an arbitrary remote response cannot inject terminal-control sequences into operator logs. #891 #910
23+
24+
Documentation:
25+
26+
- New `docs/connection-resilience.md` framework-developer guidance for choosing retry and timeout behaviour. Covers where work happens in an agent (skills / connections / protocols), the distinction between within-agent and agent-to-external failures, per-component overview (HTTP client, HTTP server, ledger read-side / write-side / thread pool, `RotatingHTTPProvider`, IPFS, P2P libp2p variants, cosmos / fetchai / solana plugins), and a "picking a policy for a new component" checklist. Indexed in `mkdocs.yml` under Development – Advanced → Topic Guides. #891 #910
1227

1328
## 2.2.5 (2026-05-08)
1429

aea/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
__title__ = "open-aea"
2424
__description__ = "Open Autonomous Economic Agent framework (without vendor lock-in)"
2525
__url__ = "https://github.com/valory-xyz/open-aea.git"
26-
__version__ = "2.2.5"
26+
__version__ = "2.2.6"
2727
__author__ = "Valory AG"
2828
__license__ = "Apache-2.0"
2929
__copyright__ = "2021 Valory AG, 2019 Fetch.AI Limited"

deploy-image/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN apk add --no-cache go
1616

1717
# aea installation
1818
RUN pip install --upgrade pip
19-
RUN pip install --upgrade --force-reinstall open-aea[all]==2.2.5 "open-aea-cli-ipfs<3.0.0,>=2.2.5"
19+
RUN pip install --upgrade --force-reinstall open-aea[all]==2.2.6 "open-aea-cli-ipfs<3.0.0,>=2.2.6"
2020

2121
# directories and aea cli config
2222
WORKDIR /home/agents

deploy-image/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The example uses the `fetchai/my_first_aea` project. You will likely want to mod
1111
Install subversion, then download the example directory to your local working directory
1212

1313
``` bash
14-
svn checkout https://github.com/valory-xyz/open-aea/tags/v2.2.5/packages packages
14+
svn checkout https://github.com/valory-xyz/open-aea/tags/v2.2.6/packages packages
1515
```
1616

1717
### Modify scripts

develop-image/docker-env.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

33
# Swap the following lines if you want to work with 'latest'
4-
DOCKER_IMAGE_TAG=valory/open-aea-develop:2.2.5
4+
DOCKER_IMAGE_TAG=valory/open-aea-develop:2.2.6
55
# DOCKER_IMAGE_TAG=valory/open-aea-develop:latest
66

77
DOCKER_BUILD_CONTEXT_DIR=..

docs/upgrading.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,32 @@ Below we describe the additional manual steps required to upgrade between differ
99

1010
### Upgrade guide
1111

12+
## `v2.2.5` to `v2.2.6`
13+
14+
This is a non-breaking patch release. It combines two streams: resilience-audit fixes across the framework / ledger connection / IPFS and ethereum plugins (cf. #891 / #910), and per-chain `max_gas_fast` tuning for low-fee chains in `open-aea-ledger-ethereum` (cf. #909 / #911).
15+
16+
### `valory/ledger` connection — bounded retry budget and dedicated executor
17+
18+
The shipped `retry_attempts` default in the connection config dropped from 240 to 60, and each per-attempt sleep is now capped at `MAX_RETRY_DELAY = 60s`. Worst-case loop time under a sustained RPC outage drops from ~6 hours to ~50 minutes. Operators who relied on the longer 240-attempt budget can override `retry_attempts` in their own connection config.
19+
20+
The connection now owns a dedicated `ThreadPoolExecutor` sized by a new `max_thread_workers` config (default 32) rather than sharing Python's default asyncio thread pool. Operators expecting high ledger concurrency should size `max_thread_workers` to exceed peak concurrent retries for their RPC topology.
21+
22+
### `open-aea-ledger-ethereum` — gas-price strategy fallback and per-chain `max_gas_fast`
23+
24+
`get_gas_price_strategy_eip1559_polygon` and `gas_station_gas_price_strategy` now route malformed-response failure modes (`JSONDecodeError`, `KeyError`, `TypeError`) through the documented fallback path. Previously these escaped the `RequestException`-only catch and could surface as transaction-signing failures.
25+
26+
`CHAIN_EIP1559_OVERRIDES` now sets a per-chain `max_gas_fast` for low-fee chains: Gnosis 30 gwei, Optimism / Base 100 gwei, Mode / Fraxtal 50 gwei, Arbitrum One 5 gwei. Until now these inherited the chain-agnostic 1500 gwei ceiling, which left the cap effectively dormant on chains whose normal operating range is 100x lower. The new ceilings are sized to preserve operability during legitimate congestion (the Base Dencun memecoin frenzy is the worst observed historical case) while bounding fee-oracle anomalies. Polygon (10000 gwei ceiling) and Celo (default 1500 gwei) are unchanged.
27+
28+
### `open-aea-cli-ipfs` — typed errors on malformed 200 responses
29+
30+
`IPFSHTTPClient.add`, `add_bytes`, and `_api_post` now raise a typed `StatusError` (with a printable, length-capped body preview) when the daemon returns a 200 status carrying a non-JSON body. Callers that previously crashed with an unhandled `ValueError` on a CDN error page or truncated payload now see the same `StatusError` class they would for any other status failure, which the existing `ipfs_utils.download()` retry loop already handles.
31+
32+
### Concrete upgrade steps
33+
34+
- `pip install --upgrade "open-aea[all]==2.2.6"` (and the same `2.2.6` pin for any `open-aea-*` plugin you use).
35+
- `aea --version` should report `2.2.6`.
36+
- No agent / package / config edits are required for the default configuration. If you previously set a custom `retry_attempts` in your `valory/ledger` connection config, review it against the new 60-attempt default and the worst-case math in `docs/connection-resilience.md`.
37+
1238
## `v2.2.4` to `v2.2.5`
1339

1440
This is a non-breaking patch release. It fixes a v2.2.4 regression where `ledger_api.api.eth.<method>(...)` returned plain dicts instead of `AttributeDict` for downstream consumers reaching into the underlying web3 handle directly (most notably open-autonomy's `TxSettler.settle()`, which crashes on `receipt.blockNumber` attribute access). The fix is a structural refactor of RPC rotation; every public surface (`EthereumApi`, `ledger_api.api`, the web3 instance, the rotation behaviour) keeps the same semantics it had before v2.2.4.

examples/tac_deploy/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ RUN apk add --no-cache go
1919

2020
# aea installation
2121
RUN python -m pip install --upgrade pip
22-
RUN pip install --upgrade --force-reinstall open-aea[all]==2.2.5
22+
RUN pip install --upgrade --force-reinstall open-aea[all]==2.2.6
2323

2424
# directories and aea cli config
2525
COPY /.aea /home/.aea

plugins/aea-ci-helpers/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def _read_long_description() -> str:
3131

3232
setup(
3333
name="open-aea-ci-helpers",
34-
version="2.2.5",
34+
version="2.2.6",
3535
author="Valory AG",
3636
license="Apache-2.0",
3737
description="CI helper utilities for AEA-based projects.",

plugins/aea-cli-benchmark/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def _read_long_description() -> str:
3232

3333
setup(
3434
name="open-aea-cli-benchmark",
35-
version="2.2.5",
35+
version="2.2.6",
3636
author="Valory AG",
3737
license="Apache-2.0",
3838
description="CLI extension for AEA framework benchmarking.",

plugins/aea-cli-ipfs/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def _read_long_description() -> str:
3434

3535
setup(
3636
name="open-aea-cli-ipfs",
37-
version="2.2.5",
37+
version="2.2.6",
3838
author="Valory AG",
3939
license="Apache-2.0",
4040
description="CLI extension for open AEA framework wrapping IPFS functionality.",

0 commit comments

Comments
 (0)