From f22a44cc0266962499f76545285392ba23823c2a Mon Sep 17 00:00:00 2001 From: Julien Ruaux Date: Thu, 29 Oct 2026 22:57:43 +0100 Subject: [PATCH 1/3] docs(agent-mesh): align guides with current SDK contracts Update A2A handler setup, JSON requirements, leases, and recovery. Document FastAPI fixed run lifetimes, silence detection, event limits, and cancellation behavior, and align the browser demos. --- .../ai/context-engine/agent-mesh/AGENTS.md | 3 +- .../ai/context-engine/agent-mesh/_index.md | 6 +- .../ai/context-engine/agent-mesh/a2a-sdk.md | 29 +++++---- .../agent-mesh/fastapi-sse-sdk.md | 62 +++++++++---------- .../context-engine/agent-mesh/quickstart.md | 17 +++-- static/code/agent-mesh/a2a-demo.py | 8 +-- static/code/agent-mesh/fastapi-sse-demo.html | 2 +- 7 files changed, 60 insertions(+), 67 deletions(-) diff --git a/content/develop/ai/context-engine/agent-mesh/AGENTS.md b/content/develop/ai/context-engine/agent-mesh/AGENTS.md index f7292eddca..4ddbd8a2ed 100644 --- a/content/develop/ai/context-engine/agent-mesh/AGENTS.md +++ b/content/develop/ai/context-engine/agent-mesh/AGENTS.md @@ -7,7 +7,8 @@ - Distinguish the independent `[a2a]` and `[fastapi-sse]` extras. The A2A integration does not require the FastAPI SSE integration. Both extras can be installed together; their shared redis-py range is `>=8.0.1,<9`. Keep Redis - server requirements (A2A 8.6+, FastAPI 8.6.2+) distinct from Python client versions. + server requirements (8.6.2+ for both, with JSON also required for A2A) distinct + from Python client versions. - Use Agent2Agent (A2A), server-sent events (SSE), Task snapshots, event replay, and application-owned execution. Explain acronyms on first use on each page. - Write for the intended released package. Use package-index installation diff --git a/content/develop/ai/context-engine/agent-mesh/_index.md b/content/develop/ai/context-engine/agent-mesh/_index.md index ab7c2a57f0..09c9b9bb27 100644 --- a/content/develop/ai/context-engine/agent-mesh/_index.md +++ b/content/develop/ai/context-engine/agent-mesh/_index.md @@ -41,7 +41,7 @@ Resumption recovers event delivery. Your application remains responsible for res | A2A server | Resume retained task updates after reconnecting, including through another server replica | `redis_iris.agent_mesh.a2a` | `pip install 'redis-iris[a2a]'` | | FastAPI event streaming | Publish an event log and replay retained server-sent events (SSE) after reconnecting | `redis_iris.agent_mesh.fastapi_sse` | `pip install 'redis-iris[fastapi-sse]'` | -These integrations are independent. Install the integration you use, or install both in one Python environment with `pip install 'redis-iris[a2a,fastapi-sse]'`. Using both selects redis-py `>=8.0.1,<9`. This is the Python client version; A2A requires Redis server 8.6+; FastAPI requires 8.6.2+. +These integrations are independent. Install the integration you use, or install both in one Python environment with `pip install 'redis-iris[a2a,fastapi-sse]'`. Using both selects redis-py `>=8.0.1,<9`. This is the Python client version. Both require Redis server 8.6.2+; A2A also requires JavaScript Object Notation (JSON) support. ## How it works @@ -53,11 +53,11 @@ For FastAPI, configure `FastAPIRedis(app).lifespan().streams()`, publish scoped ## Requirements and limits -- Both integrations require Python 3.11 or later and native producer idempotency (`XADD IDMP`). A2A requires Redis 8.6+ and FastAPI requires 8.6.2+. The A2A integration targets the official A2A Python SDK 1.2.x. +- Both integrations require Python 3.11 or later and native producer idempotency (`XADD IDMP`). Both require Redis 8.6.2+; A2A also requires JSON support. The A2A integration targets the official A2A Python SDK 1.2.x. - Derive ownership from verified identity. Task IDs and cursors grant no access; authorize requests and reconnections in your application. - Retention bounds replay. A2A can fall back to the current snapshot when event history is unavailable. If events are no longer retained, a FastAPI application must provide another way for clients to retrieve the current state. - Your application owns execution and Redis durability. Stored tasks do not restart interrupted computation or guarantee exactly-once external effects. -- Standalone Redis has local validation evidence. Cluster, Enterprise, failover, and sustained capacity remain unqualified for this preview. +- Standalone Redis and normal A2A operation on a three-primary Redis Open Source Cluster have local validation evidence. Cloud, Enterprise, failover recovery, and sustained capacity remain unqualified for this preview. ## Get started diff --git a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md index d80495c681..9c57af3f23 100644 --- a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md +++ b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md @@ -17,7 +17,7 @@ For a runnable browser example, start with the [A2A quickstart](/content/develop ## Install the integration -You need Python 3.11 or later, Redis 8.6 or later with native producer idempotency (`XADD IDMP`), and the official A2A Python SDK 1.2.x. +You need Python 3.11 or later, Redis 8.6.2 or later with native producer idempotency (`XADD IDMP`) and JavaScript Object Notation (JSON) support, and the official A2A Python SDK 1.2.x. ```bash pip install 'redis-iris[a2a]' 'a2a-sdk[http-server]>=1.2.3,<1.3' @@ -35,7 +35,6 @@ The application factory in this example accepts your existing `AgentExecutor`, ` import os from contextlib import asynccontextmanager -from a2a.server.request_handlers import DefaultRequestHandler from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from redis.asyncio import Redis from redis_iris.agent_mesh.a2a import RedisTaskEventStream, RedisTaskStore @@ -57,11 +56,8 @@ def create_app(agent_executor, agent_card, auth_backend): ) store = RedisTaskStore(commands, namespace="myapp:a2a") event_stream = RedisTaskEventStream(readers, store=store) - handler = DefaultRequestHandler( - agent_executor=store.heartbeat(agent_executor), - agent_card=agent_card, - task_store=store, - event_stream=event_stream, + handler = store.request_handler( + agent_executor, agent_card=agent_card, event_stream=event_stream ) agent_card.capabilities.extensions.append(resumable_streams_extension()) @@ -78,7 +74,7 @@ def create_app(agent_executor, agent_card, auth_backend): *create_agent_card_routes(agent_card), *create_jsonrpc_routes(handler, rpc_url="/"), *create_resumable_rest_routes( - handler, store=store, event_stream=event_stream + handler, agent_card=agent_card, store=store, event_stream=event_stream ), ], middleware=[Middleware(AuthenticationMiddleware, backend=auth_backend)], @@ -88,7 +84,7 @@ def create_app(agent_executor, agent_card, auth_backend): Use the same Redis database, namespace, and ownership policy on every replica. Use primary reads for both snapshots and events. Your application owns credentials, Transport Layer Security (TLS), connection pools, timeouts, and shutdown. -Each waiting subscription occupies a Redis connection. A separate reader pool keeps blocked subscriptions from exhausting connections needed for writes and heartbeats. Set its socket timeout above the event stream's `block_ms` interval, which defaults to 1,000 milliseconds. +Each waiting subscription occupies a Redis connection. A separate reader pool keeps blocked subscriptions from exhausting connections needed for writes and heartbeats. Set its socket timeout above the event stream's `block_ms` interval, which defaults to at most 4,000 milliseconds and adapts to a shorter client socket timeout. `RedisTaskStore` commits the Task snapshot, version, and event together. The paired event stream reads that log; its `publish()` method does not append another copy. Keep writing through the official request handler and its task store. @@ -102,7 +98,7 @@ The official handler and resumable routes check ownership before subscribing. Th ## Start and resume a subscription -`create_resumable_rest_routes()` adds event cursors to the HTTP+JSON binding's `POST /message:stream` and `GET` or `POST /tasks/{id}:subscribe` routes. Other REST routes retain the official SDK's behavior. +Pass the handler's same `agent_card` to `create_resumable_rest_routes()`; its streaming capability must be enabled. The factory adds event cursors to the HTTP+JSON binding's `POST /message:stream` and `GET` or `POST /tasks/{id}:subscribe` routes. Other REST routes retain the official SDK's behavior. To follow an existing active task, send an authenticated request to `/tasks/:subscribe` with `A2A-Version: 1.0`. Without a cursor, the response starts with the current Task snapshot and follows new updates. @@ -143,9 +139,9 @@ For cancellation, use the official handler's cancellation path. A cancellation c ## Monitor executing agents -The optional `store.heartbeat(executor, interval=5.0, alive_ttl=15.0)` wrapper refreshes liveness and retention while the agent executes. It checks stored terminal state and stops local execution when another replica cancels or finishes the Task. Set `alive_ttl` greater than `interval`. +`store.request_handler()` applies `store.heartbeat(executor, interval=5.0, alive_ttl=15.0)` to track the running agent under a process lease. It checks stored terminal state and stops local execution when another replica cancels or finishes the Task. Set `alive_ttl` greater than `interval`. -With an active store-backed subscriber, a lapsed heartbeat on a submitted or working Task marks it failed with a `producer_lost` status message. Polling task state alone does not trigger this recovery. Tasks waiting for input or authentication, and tasks without tracked heartbeats, are excluded. +A store-backed subscriber or `get()` marks a submitted or working Task failed with a `producer_lost` status message when its producer lease expires. Tasks waiting for input or authentication, and tasks without tracked heartbeats, are excluded. The wrapper does not restart computation. Without it, an agent on another replica learns of cancellation at its next write. With A2A SDK 1.2.3, continued emission after that cancellation can also leave handler shutdown waiting indefinitely; the wrapper stops the agent first. @@ -156,7 +152,7 @@ Pass these options to `RedisTaskStore`: | Option | Default | Purpose | | --- | --- | --- | | `namespace` | `iris:a2a` | Isolate applications and deployments. | -| `active_ttl` | 604,800 seconds (7 days) | Active snapshot and event retention, refreshed by saves or heartbeats. | +| `active_ttl` | 604,800 seconds (7 days) | Active snapshot and event retention, refreshed by saves. | | `terminal_ttl` | 86,400 seconds (1 day) | Terminal snapshot and event retention. | | `metadata_ttl` | 86,400 seconds | Additional ownership and version retention after snapshot expiry. | | `max_task_bytes` | 1,048,576 | Serialized snapshot size limit. | @@ -164,13 +160,16 @@ Pass these options to `RedisTaskStore`: | `max_events` | 10,000 | Approximate retained log length. | | `max_attempts` | 5 | Maximum attempts under transaction contention. | -The byte limits apply before hex encoding; stored payloads use about twice those serialized sizes. Size the event limit and log length for your memory budget. An oversized payload raises `A2ACapacityExceeded` without changing the snapshot or log. +Heartbeats do not extend Task retention. Set `active_ttl` longer than the longest interval without a saved update. + +The byte limits count serialized protocol buffer bytes; stored JSON payloads use more space. Size the event limit and log length for your memory budget. An oversized payload raises `A2ACapacityExceeded` without changing the snapshot or log. Owner metadata prevents another owner from reusing a Task ID until it expires. Deleting an owned Task removes its snapshot and events while retaining ownership metadata for `metadata_ttl`. After metadata expiry, reuse cannot be detected. | Public API | Use it to | | --- | --- | | `RedisTaskStore` | Store owner-scoped snapshots and versioned updates through the official SDK. | +| `store.request_handler()` | Build the official handler with paired events and heartbeat tracking. | | `store.event_stream()` | Build the matching event reader, with producer-loss recovery. | | `RedisTaskEventStream` | Configure a reader explicitly with `store=store` and a separate client. | | `store.heartbeat()` | Track execution liveness and notice remote cancellation. | @@ -179,6 +178,6 @@ Owner metadata prevents another owner from reusing a Task ID until it expires. D Storage and internal reader calls can raise `A2AStorageError`, `A2ACapacityExceeded`, or `A2AStreamExpired`. Stale or conflicting writes raise the official SDK's `ConcurrentTaskModificationError`. Let the handler and routes translate these into protocol responses rather than exposing storage exceptions to clients. -Task listing scans the namespace and suits modest inventories. It is not a search index or a consistent snapshot during concurrent writes. +Task listing scans an owner's Task index and suits modest inventories per owner. It is not a search index or a consistent snapshot during concurrent writes. See the [SDK API reference](https://github.com/redis/redis-iris/blob/main/docs/core/agent-mesh-a2a.md) for signatures and the [preview limits](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for deployment qualification. Redis durability remains application-owned; replay does not guarantee exactly-once external effects. diff --git a/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md b/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md index 30c034b36f..ba8b96a045 100644 --- a/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md +++ b/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md @@ -61,10 +61,9 @@ commands. There are no relay buckets or subscriber queues. ## Authorize scoped runs -A run is identified by a `scope` and `stream_id`. The scope also defines the -exclusive active-run boundary: by default, only one run is active per scope. -Choose a resource-sized scope, such as a tenant's chat or job, rather than using -one scope for every job in a tenant. +A run is identified by a `scope` and `stream_id`. Choose a scope for the resource +you authorize, such as a tenant's chat or job. Multiple runs can share a scope; +your application tracks the current run and enforces any one-run-at-a-time policy. Authenticate and authorize before passing the scope and run ID to the backend. Neither `StreamBackendDep` nor `backend.sse()` performs application access checks. @@ -129,16 +128,17 @@ without spawning a second producer. `writer.append(type, data)` and names; the `stream.` prefix is reserved for SDK events. For additional work between opening and spawning, use `await streams.open(...)` -and `streams.spawn(writer, producer)`. To read without HTTP, use +and call `streams.spawn(writer, producer)` only when `writer.created` is true. +To read without HTTP, use `async with await streams.follow(run_id, scope=scope, after=cursor)`. Events expose `id`, `type`, `data` and `final` fields. The SDK owns the producer task and generates its write-retry identities. Applications cannot supply producer/event idempotency keys. Disconnecting a -reader leaves the task running. `cancel()` requests a stop; `active()` identifies -the scope's active run; `attach()` takes over an unfinished run. These operations -do not undo external side effects or restart computation after a process exit. -Publisher-only external workers are not supported in this version. +reader leaves the task running. `cancel()` ends the run for readers and cancels +a producer in the same process. A producer in another process keeps running; +its later events are unread. Runs cannot be handed to another process or restart +after a process exit. Publisher-only external workers are not supported. ## Resume and recover @@ -150,7 +150,8 @@ A reconnect at the final cursor returns HTTP 204. Retention bounds replay. Provide an authorized application endpoint returning current state together with a matching cursor when clients need recovery. -Reload state when reconnecting returns HTTP 410 for expired or trimmed history. +Reload state when reconnecting returns HTTP 404 for an unknown or expired run, +or HTTP 410 for externally removed history. A `stream.gap` event during delivery reports missing entries and the reader continues; a client requiring complete history should recover application state. @@ -161,10 +162,8 @@ Read the top-level `code` field: | --- | --- | --- | | 401 | `credential_expired` | Refresh verified credentials. | | 404 | `stream_not_found` | Retrieve application state. | -| 410 | `stream_expired` | Reload state; history expired or was trimmed. | -| 409 | `stream_busy` | Reuse the active run or resolve the scope conflict. | +| 410 | `stream_expired` | Reload state; entries were removed externally. | | 409 | `cursor_ahead` | Reconcile application state and cursor. | -| 409 | `stream_fenced`, `stream_finished` | Stop using the old writer. | | 422 | `invalid_cursor`, `invalid_stream_name` | Correct the request. | | 503 | `stream_unavailable`, `stream_unsupported`, or reader capacity | Retry transient failures with backoff; check server requirements for unsupported features. | | 204 | Final event consumed | Stop reconnecting. | @@ -173,40 +172,41 @@ Authentication dependencies retain their own status and challenge headers. After headers, transient failures close the connection and clients reconnect. Handle SDK events `stream.end` (including `error`, `cancelled` and `producer_lost` outcomes) and `stream.error` (credential expiry or read-only -producer-loss reporting). These replace control-action frames. Native +producer-loss reporting). Native `EventSource` cannot inspect refused-connection bodies; use the application state endpoint or a fetch-based client to explain failures. ## Configure retention -Retention slides on writes. Active appends reset `stream_active_ttl`; completion -sets `stream_done_ttl`; metadata outlives payload by `stream_gone_ttl`. -Reads do not extend retention. `writer.extend(ttl)` extends a waiting run's -retention. `spawn()` runs `writer.keepalive()` around the producer, or an -application-managed producer can enter that context itself. +A run has a fixed lifetime from `open()`, bounded by `stream_max_run`. Nothing +extends it. Completion shortens remaining retention to at most `stream_done_ttl`. +Set `stream_max_run` for the longest expected run, up to 86,400 seconds. -Keep idle waits below active retention or arrange explicit extensions. Liveness -and retained history are separate: a heartbeat alone does not guarantee payload -retention in the current version. Allow for the heartbeat's own active-slot TTL -when extending a waiting run. A producer lost on a process exit is not restarted. +A reader that sees no new entries for `stream_silence_timeout` ends the run with +a `producer_lost` final event. `spawn()` runs `writer.keepalive()` around the +producer, writing hidden pings during quiet work. An application-managed producer +can enter that context itself. Pings prevent silence detection but do not extend +the run's lifetime. A producer lost on a process exit is not restarted. + +The SDK retains all events until the run expires. A writer that exceeds +`stream_maxlen` raises `ValueError` rather than trimming earlier events. | Setting (prefix with `REDIS_`) | Default | Purpose | | --- | --- | --- | -| `STREAM_ACTIVE_TTL` | 600 seconds | Retention refreshed by active writes. | -| `STREAM_DONE_TTL` | 120 seconds | Replay window after completion. | -| `STREAM_GONE_TTL` | 3,600 seconds | Expired-history recognition window. | -| `STREAM_MAXLEN` | 10,000 | Approximate retained entries. | +| `STREAM_MAX_RUN` | 3,600 seconds | Fixed run lifetime from creation. | +| `STREAM_DONE_TTL` | 120 seconds | Maximum remaining retention after completion. | +| `STREAM_MAXLEN` | 10,000 | Maximum events one writer can append. | | `STREAM_MAX_EVENT_BYTES` | 65,536 | Largest encoded event. | -| `STREAM_HEARTBEAT_INTERVAL` | 15 seconds | Producer heartbeat, SSE ping and blocking-read bound. | -| `STREAM_ALIVE_TTL` | 45 seconds | Producer-liveness field lifetime. | +| `STREAM_HEARTBEAT_INTERVAL` | 15 seconds | SSE ping, blocking-read bound and keepalive check interval. | +| `STREAM_SILENCE_TIMEOUT` | 60 seconds | Silence before a reader ends a lost producer's run; must exceed twice the heartbeat interval. | | `STREAM_MAX_READERS` | 256 | Live-reader admission per process. | | `STREAM_REPLAY_PAGE` | 100 | Events per Redis read. | | `STREAM_MAX_CONNECTION_DURATION` | 300 seconds | Connection cap before reconnect. | | `STREAM_READ_RETRY_WINDOW` | 30 seconds | Retry window for transient read failures. | | `STREAM_SEND_TIMEOUT` | 10 seconds | Bound for stalled sends. | -Set `REDIS_STREAM_DONE_TTL=3600` to retain a completed demo run for one hour. -These settings differ from the application state retained in its own database. +The demo sets `REDIS_STREAM_DONE_TTL=3600`; replay still ends at the run's +original lifetime. Application state in your own database has separate retention. See the [SDK reference](https://github.com/redis/redis-iris/blob/main/docs/core/agent-mesh-sse.md) for facade exports and upstream signatures, and the diff --git a/content/develop/ai/context-engine/agent-mesh/quickstart.md b/content/develop/ai/context-engine/agent-mesh/quickstart.md index c03e530956..dbbeb09916 100644 --- a/content/develop/ai/context-engine/agent-mesh/quickstart.md +++ b/content/develop/ai/context-engine/agent-mesh/quickstart.md @@ -15,7 +15,7 @@ Choose one browser demo: reconnect to Agent2Agent (A2A) task updates, or resume ## Before you begin -You need Python 3.11 or later, `pip`, a browser, and a Redis database running version 8.6.2 or later with native producer idempotency (`XADD IDMP`). The demo application runs locally on port 8000, whichever database option you choose. +You need Python 3.11 or later, `pip`, a browser, and a Redis database running version 8.6.2 or later with native producer idempotency (`XADD IDMP`). The A2A example also requires JavaScript Object Notation (JSON) support. Official Redis distributions with JSON enabled provide it; a source build needs the JSON module built and loaded. The demo application runs locally on port 8000, whichever database option you choose. ## Choose your Redis database @@ -106,7 +106,6 @@ The page uses the browser's built-in `EventSource` client. It does not restart t The downloaded application defines `CountingAgent`, its streaming agent card, and the Redis client. These are the integration points: ```python -from a2a.server.request_handlers import DefaultRequestHandler from redis_iris.agent_mesh.a2a import RedisTaskStore from redis_iris.agent_mesh.a2a.routes import create_resumable_rest_routes @@ -116,13 +115,10 @@ store = RedisTaskStore( owner_resolver=lambda context: "local-demo-user", # Loopback demo only. ) events = store.event_stream() -handler = DefaultRequestHandler( - agent_executor=store.heartbeat(CountingAgent()), - agent_card=card, - task_store=store, - event_stream=events, +handler = store.request_handler(CountingAgent(), agent_card=card, event_stream=events) +routes = create_resumable_rest_routes( + handler, agent_card=card, store=store, event_stream=events ) -routes = create_resumable_rest_routes(handler, store=store, event_stream=events) ``` `RedisTaskStore` saves the task and its updates together. Its paired event stream reads those updates from Redis. `create_resumable_rest_routes()` exposes subscriptions with event cursors. The agent card enables streaming and advertises `resumable_streams_extension()`. @@ -217,8 +213,9 @@ async def events(job_id: UUID, request: Request, streams: StreamBackendDep): The browser reconnects with the last applied cursor. The demo sets `REDIS_STREAM_DONE_TTL=3600` unless you override it, retaining a completed run for -one hour. Active retention and finished retention are separate. Replay requires -retained history; it does not restart interrupted execution. +up to one hour, bounded by the run's original lifetime (one hour by default). +Completion never extends that lifetime. Replay requires retained history; it +does not restart interrupted execution. ## When you're done diff --git a/static/code/agent-mesh/a2a-demo.py b/static/code/agent-mesh/a2a-demo.py index 7152278405..6f29980b59 100644 --- a/static/code/agent-mesh/a2a-demo.py +++ b/static/code/agent-mesh/a2a-demo.py @@ -7,7 +7,6 @@ import uvicorn from a2a.server.agent_execution import AgentExecutor -from a2a.server.request_handlers import DefaultRequestHandler from a2a.types import ( AgentCapabilities, AgentCard, AgentInterface, AgentSkill, Artifact, Part, Task, TaskArtifactUpdateEvent, TaskState, TaskStatus, TaskStatusUpdateEvent, @@ -90,10 +89,7 @@ async def finish(self, context, event_queue, state): protocol_version="1.0", url="http://127.0.0.1:8000/", )], ) -handler = DefaultRequestHandler( - agent_executor=store.heartbeat(CountingAgent()), agent_card=card, - task_store=store, event_stream=events, -) +handler = store.request_handler(CountingAgent(), agent_card=card, event_stream=events) @asynccontextmanager @@ -113,7 +109,7 @@ async def home(request): app = Starlette( routes=[Route("/", home), *create_resumable_rest_routes( - handler, store=store, event_stream=events, + handler, agent_card=card, store=store, event_stream=events, )], lifespan=lifespan, middleware=[ diff --git a/static/code/agent-mesh/fastapi-sse-demo.html b/static/code/agent-mesh/fastapi-sse-demo.html index bd31f0f070..2de4d16bc8 100644 --- a/static/code/agent-mesh/fastapi-sse-demo.html +++ b/static/code/agent-mesh/fastapi-sse-demo.html @@ -141,7 +141,7 @@

Your agent’s answer

}); current.addEventListener("stream.gap", () => { if (source !== current) return; - showError(new Error("Some updates were trimmed. Start a new demo run.")); + showError(new Error("Some updates are missing. Start a new demo run.")); ui.status.textContent = "History incomplete"; ui.reconnect.disabled = true; }); From 53706261faad5d6dc341a921e1e5bdffec9a9968 Mon Sep 17 00:00:00 2001 From: Julien Ruaux Date: Thu, 29 Oct 2026 23:03:10 +0100 Subject: [PATCH 2/3] docs(agent-mesh): use beta availability terminology Match the Lens banner wording and update the Agent Mesh tile, operator heading, guide links, and authoring instructions. --- content/develop/ai/context-engine/_index.md | 2 +- content/develop/ai/context-engine/agent-mesh/AGENTS.md | 4 ++-- content/develop/ai/context-engine/agent-mesh/_index.md | 4 ++-- content/develop/ai/context-engine/agent-mesh/a2a-sdk.md | 2 +- .../develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md | 2 +- content/develop/ai/context-engine/agent-mesh/quickstart.md | 4 ++-- content/operate/iris/_index.md | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/content/develop/ai/context-engine/_index.md b/content/develop/ai/context-engine/_index.md index a512ca4b26..5e72b121af 100644 --- a/content/develop/ai/context-engine/_index.md +++ b/content/develop/ai/context-engine/_index.md @@ -23,7 +23,7 @@ Redis Iris eliminates the infrastructure burden of building context-aware AI age {{< tile-card icon="images/dev/icons/icon-redis-iris-64-duotone.png" title="Agent Playbooks" description="Publish reusable answers and procedures for agents" url="/develop/ai/context-engine/agent-playbooks" >}} {{< tile-card icon="images/dev/icons/icon-redis-iris-64-duotone.png" title="Lens" description="Debug agent answers by tracing the context behind each turn" url="/develop/ai/context-engine/lens" >}} {{< tile-card icon="images/dev/icons/icon-redis-iris-64-duotone.png" title="SDK and CLI setup" description="Install redis-iris and connect it to Redis Cloud or a self-managed deployment" url="/develop/ai/context-engine/sdk-and-cli" >}} - {{< tile-card icon="images/dev/icons/icon-redis-code-64-duotone.png" title="Agent Mesh (preview)" description="Share agent-to-agent task state across Python replicas and resume event delivery" url="/develop/ai/context-engine/agent-mesh" >}} + {{< tile-card icon="images/dev/icons/icon-redis-code-64-duotone.png" title="Agent Mesh (beta)" description="Share agent-to-agent task state across Python replicas and resume event delivery" url="/develop/ai/context-engine/agent-mesh" >}} ## What is Redis Iris? diff --git a/content/develop/ai/context-engine/agent-mesh/AGENTS.md b/content/develop/ai/context-engine/agent-mesh/AGENTS.md index 4ddbd8a2ed..200e02850a 100644 --- a/content/develop/ai/context-engine/agent-mesh/AGENTS.md +++ b/content/develop/ai/context-engine/agent-mesh/AGENTS.md @@ -1,6 +1,6 @@ # Agent Mesh documentation -- Agent Mesh is a preview Python SDK integration distributed through `redis-iris`. +- Agent Mesh is a beta Python SDK integration distributed through `redis-iris`. Imports use `redis_iris.agent_mesh`. - Lead with resumable event streams on Redis. Present A2A task state storage as a supporting capability, and A2A and FastAPI SSE as two Python integration paths. @@ -25,7 +25,7 @@ quickstart. Their deployment and Redis requirements are separate. - Keep user-facing integration guides here. Link exhaustive signatures and implementation contracts to redis-iris documentation. - Preserve the product preview banner and qualification limitations. + Preserve the product beta banner and qualification limitations. - Keep an overview, one quickstart with both integrations, and one SDK guide per integration. Each quickstart example reaches one first result. Keep diff --git a/content/develop/ai/context-engine/agent-mesh/_index.md b/content/develop/ai/context-engine/agent-mesh/_index.md index 09c9b9bb27..e4f3bfe4fe 100644 --- a/content/develop/ai/context-engine/agent-mesh/_index.md +++ b/content/develop/ai/context-engine/agent-mesh/_index.md @@ -9,7 +9,7 @@ hideListLinks: true linktitle: Agent Mesh title: Redis Agent Mesh weight: 40 -bannerText: Redis Agent Mesh is currently available in preview. Features and behavior are subject to change. +bannerText: Redis Agent Mesh is currently in beta. Features and behavior are subject to change. bannerChildren: true --- @@ -57,7 +57,7 @@ For FastAPI, configure `FastAPIRedis(app).lifespan().streams()`, publish scoped - Derive ownership from verified identity. Task IDs and cursors grant no access; authorize requests and reconnections in your application. - Retention bounds replay. A2A can fall back to the current snapshot when event history is unavailable. If events are no longer retained, a FastAPI application must provide another way for clients to retrieve the current state. - Your application owns execution and Redis durability. Stored tasks do not restart interrupted computation or guarantee exactly-once external effects. -- Standalone Redis and normal A2A operation on a three-primary Redis Open Source Cluster have local validation evidence. Cloud, Enterprise, failover recovery, and sustained capacity remain unqualified for this preview. +- Standalone Redis and normal A2A operation on a three-primary Redis Open Source Cluster have local validation evidence. Cloud, Enterprise, failover recovery, and sustained capacity remain unqualified for this beta. ## Get started diff --git a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md index 9c57af3f23..f3a7b30efe 100644 --- a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md +++ b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md @@ -180,4 +180,4 @@ Storage and internal reader calls can raise `A2AStorageError`, `A2ACapacityExcee Task listing scans an owner's Task index and suits modest inventories per owner. It is not a search index or a consistent snapshot during concurrent writes. -See the [SDK API reference](https://github.com/redis/redis-iris/blob/main/docs/core/agent-mesh-a2a.md) for signatures and the [preview limits](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for deployment qualification. Redis durability remains application-owned; replay does not guarantee exactly-once external effects. +See the [SDK API reference](https://github.com/redis/redis-iris/blob/main/docs/core/agent-mesh-a2a.md) for signatures and the [beta limits](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for deployment qualification. Redis durability remains application-owned; replay does not guarantee exactly-once external effects. diff --git a/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md b/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md index ba8b96a045..30b64dc010 100644 --- a/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md +++ b/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md @@ -210,5 +210,5 @@ original lifetime. Application state in your own database has separate retention See the [SDK reference](https://github.com/redis/redis-iris/blob/main/docs/core/agent-mesh-sse.md) for facade exports and upstream signatures, and the -[preview limits](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) +[beta limits](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for deployment qualification. diff --git a/content/develop/ai/context-engine/agent-mesh/quickstart.md b/content/develop/ai/context-engine/agent-mesh/quickstart.md index dbbeb09916..a75869f391 100644 --- a/content/develop/ai/context-engine/agent-mesh/quickstart.md +++ b/content/develop/ai/context-engine/agent-mesh/quickstart.md @@ -33,7 +33,7 @@ Choose Redis Cloud or a local instance, then set `REDIS_URL` in the terminal whe Replace the placeholders with your database values and the certificate bundle's absolute path. Percent-encode special characters in the username, password, and certificate path; see [connection URLs](/content/develop/clients/connection-urls.md). Keep this URL out of source control and logs. -These are Redis database credentials. The local browser demo still needs no token or sign-in. Redis Cloud deployment and failure qualification remain separate from the [preview's tested coverage](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits). +These are Redis database credentials. The local browser demo still needs no token or sign-in. Redis Cloud deployment and failure qualification remain separate from the [beta's tested coverage](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits). -tab-sep- @@ -225,4 +225,4 @@ Stopping the app leaves a Redis Cloud database running. If you created a disposa ## Further reading -To add these integrations to your application, follow the [A2A SDK guide](/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md) or [FastAPI SSE SDK guide](/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md). See the [Agent Mesh limitations](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for preview qualification. +To add these integrations to your application, follow the [A2A SDK guide](/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md) or [FastAPI SSE SDK guide](/content/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk.md). See the [Agent Mesh limitations](/content/develop/ai/context-engine/agent-mesh/_index.md#requirements-and-limits) for beta qualification. diff --git a/content/operate/iris/_index.md b/content/operate/iris/_index.md index 3a2678ff33..b79b45f106 100644 --- a/content/operate/iris/_index.md +++ b/content/operate/iris/_index.md @@ -37,6 +37,6 @@ Deploy Redis Iris services on Kubernetes when you need to operate them on your o - [Self-managed Redis Agent Memory]({{< relref "/operate/iris/agent-memory/self-managed" >}}) - [Self-managed Redis Context Gateway]({{< relref "/operate/iris/context-gateway/self-managed" >}}) -## Agent Mesh SDK preview +## Agent Mesh SDK beta Agent Mesh provides Python SDK integrations for shared agent-to-agent task storage and resumable event delivery. Run it in your application with your own Redis connections. See the [Agent Mesh overview](/content/develop/ai/context-engine/agent-mesh/_index.md) and [quickstart](/content/develop/ai/context-engine/agent-mesh/quickstart.md). From a78bc228f1bf7d9cf84c4c708ec0fa92e1b7b63d Mon Sep 17 00:00:00 2001 From: Julien Ruaux Date: Thu, 29 Oct 2026 23:46:48 +0100 Subject: [PATCH 3/3] docs(agent-mesh): simplify A2A installation commands Use redis-iris[a2a] alone now that redis/redis-iris#43 bundles a2a-sdk HTTP server dependencies. Keep uvicorn explicit in the browser quickstart. Validated the commands with a clean A2A-only wheel installation and checked all three install locations and Markdown fences. Independent read-only review found no actionable issues. Full Hugo build was not run. --- content/develop/ai/context-engine/agent-mesh/a2a-sdk.md | 2 +- content/develop/ai/context-engine/agent-mesh/quickstart.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md index f3a7b30efe..934a6b78a4 100644 --- a/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md +++ b/content/develop/ai/context-engine/agent-mesh/a2a-sdk.md @@ -20,7 +20,7 @@ For a runnable browser example, start with the [A2A quickstart](/content/develop You need Python 3.11 or later, Redis 8.6.2 or later with native producer idempotency (`XADD IDMP`) and JavaScript Object Notation (JSON) support, and the official A2A Python SDK 1.2.x. ```bash -pip install 'redis-iris[a2a]' 'a2a-sdk[http-server]>=1.2.3,<1.3' +pip install 'redis-iris[a2a]' ``` To use both integrations in one application, install `redis-iris[a2a,fastapi-sse]`. Their shared redis-py range is `>=8.0.1,<9`; separate Python environments are not required. diff --git a/content/develop/ai/context-engine/agent-mesh/quickstart.md b/content/develop/ai/context-engine/agent-mesh/quickstart.md index a75869f391..3e5d119eca 100644 --- a/content/develop/ai/context-engine/agent-mesh/quickstart.md +++ b/content/develop/ai/context-engine/agent-mesh/quickstart.md @@ -70,7 +70,7 @@ mkdir agent-mesh-a2a cd agent-mesh-a2a python3 -m venv .venv source .venv/bin/activate -python -m pip install 'redis-iris[a2a]' 'a2a-sdk[http-server]>=1.2.3,<1.3' uvicorn +python -m pip install 'redis-iris[a2a]' uvicorn ``` ### Start the demo