You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
What's Changed
Security
Bump dev dependency pytest to ^9.0.0 (9.0.3), with pytest-asyncio to >=1.0,<2 (1.4.0) for compatibility, to remediate GHSA-6w46-j5rx-g56g (insecure tmpdir handling). Test-only; no runtime impact.
Changed
Bump fastmcp from ^2.14.0 to ^3.0.0 (resolves to 3.4.0), which pulls in authlib 1.7.2. The MCP adapter now uses Tool.to_mcp_tool() to read tool schemas, since fastmcp 3.x list_tools() returns FunctionTool objects that expose schemas via parameters/output_schema instead of inputSchema/outputSchema.
Added
Distributed tracing via OpenTelemetry: Agents now propagate a shared trace_id across every message hop. Opt-in via setup_tracing(); zero-cost when not configured.
Fixed
RedisTransport (#225): Retry and DLQ stream keys are now per-handler
({channel}.{handler_suffix}.retry / .dlq) instead of per-channel.
Previously, multiple handlers subscribing to the same channel with different
consumer groups shared a single {channel}.retry stream, so one handler's
reclaimed failure would be redelivered to every handler on that channel
via its auto-created -retry group. This caused work amplification (N
replays per nack, where N is the number of consumer groups on the channel)
and visible duplicate side-effects in downstream systems with non-idempotent
handlers.
RedisTransport: A permanently-unparseable ("poison") retry message is now
routed to the DLQ — or dropped with an error log when no DLQ is configured —
instead of being re-queued to the retry stream forever. Its retry count can
never be incremented, so it would previously livelock the per-handler retry
stream.
RedisTransport: The auto-created retry-stream subscriber now always reads
only new entries (last_id=">") regardless of the main subscription's last_id. Restarting with last_id="0" to replay the main backlog no longer
also replays the retry stream's history on every restart.
RedisTransport: A RedisTransport shared across multiple Agents no
longer spawns duplicate consumer loops or orphans its consumer-group monitor
task when each agent calls connect(). Re-entrant connect() now starts only
not-yet-running subscribers and reuses the existing monitor.
Tracing: Retry-stream consumption now emits spans with the retry stream as messaging.destination instead of the original channel, so retry attempts can
be observed separately from main-stream processing.
RedisTransport: subscribe() now rolls back the in-memory reclaimer configs
and stream-subscription entries it registered if retry-stream setup fails, so a
retried start() no longer accumulates orphaned registrations. Identical
stream-group subscriptions are also de-duplicated.
Changed
RedisTransport: retry_on_idle_ms now rejects ack_policy=AckPolicy.ACK
and AckPolicy.ACK_FIRST with a ValueError. Those acknowledge messages even
when the handler fails, emptying the PEL the reclaimer scans, which would
silently disable retries and the DLQ. Use the default NACK_ON_ERROR.
Migration
Breaking on-wire change. Existing inflight messages in {channel}.retry
and {channel}.dlq streams will not be picked up by upgraded consumers —
they will continue to exist but new retries will land in the per-handler
streams. Drain the legacy streams before deploying, or XADD any pending
entries into the new per-handler keys.