{
  "schema_version": 2,
  "id": "develop/ai/context-engine/agent-mesh/quickstart",
  "title": "Get started with Agent Mesh",
  "url": "https://redis.io/docs/latest/develop/ai/context-engine/agent-mesh/quickstart/",
  "summary": "Create your first resumable event stream with A2A or FastAPI.",
  "tags": [
    "docs",
    "develop",
    "ai"
  ],
  "last_updated": "2026-10-29T23:46:48+01:00",
  "page_type": "content",
  "content_hash": "6f870ec96cf45cbc87a273db654ce640a06e1a0ed14445b1fae6a7a15ed73e0e",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Choose one browser demo: reconnect to Agent2Agent (A2A) task updates, or resume application-defined server-sent events (SSE) with FastAPI. Neither example needs a model account."
    },
    {
      "id": "before-you-begin",
      "title": "Before you begin",
      "role": "content",
      "text": "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."
    },
    {
      "id": "choose-your-redis-database",
      "title": "Choose your Redis database",
      "role": "content",
      "text": "Choose Redis Cloud or a local instance, then set `REDIS_URL` in the terminal where you will run the demo application. Both examples use this connection value.\n\n**Redis Cloud:**\n\n1. Use a dedicated Redis Cloud database running Redis 8.6.2 or later. See [Create a database](https://redis.io/docs/latest/operate/rc/databases/create-database) and [supported database versions](https://redis.io/docs/latest/operate/rc/databases/version-management#supported-database-versions).\n1. [Enable Transport Layer Security (TLS)](https://redis.io/docs/latest/operate/rc/security/database-security/tls-ssl#enable-tls) and download the server certificate bundle. Get your database endpoint, username, and password from the [connection guide](https://redis.io/docs/latest/operate/rc/databases/connect).\n1. Set the connection URL in your application terminal:\n\n   [code example]\n\nReplace 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](https://redis.io/docs/latest/develop/clients/connection-urls). Keep this URL out of source control and logs.\n\nThese 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](https://redis.io/docs/latest/develop/ai/context-engine/agent-mesh#requirements-and-limits).\n\n**Local Redis:**\n\nYou need a local `redis-server` executable, another terminal, and free port 6389.\n\n1. Start disposable Redis in that other terminal:\n\n   [code example]\n\n   Leave it running. If the port is in use, stop rather than reusing an existing database. Persistence is disabled for this local example.\n\n1. Set the connection URL in your application terminal:\n\n   [code example]\n\n\n\nContinue in the application terminal so that the demo can read `REDIS_URL` from its environment. If you open a new terminal to try the other example, set `REDIS_URL` there too."
    },
    {
      "id": "resume-a2a-task-updates",
      "title": "Resume A2A task updates",
      "role": "content",
      "text": "A simulated agent produces twenty numbered updates, one per second. Disconnect the browser's subscription while the agent continues, then reconnect to receive the updates you missed."
    },
    {
      "id": "install",
      "title": "Install",
      "role": "setup",
      "text": "In your application terminal, create an environment for the A2A example:\n\n[code example]"
    },
    {
      "id": "start-the-demo",
      "title": "Start the demo",
      "role": "content",
      "text": "1. Save both example files in your `agent-mesh-a2a` directory:\n\n   - \n   - \n\n1. Run the application:\n\n   [code example]\n\n1. Open <http://127.0.0.1:8000> in your browser.\n\nThis loopback-only example uses one fixed demo owner and needs no token or sign-in. In a deployed application, derive ownership from verified identity and authorize each task subscription."
    },
    {
      "id": "disconnect-and-catch-up",
      "title": "Disconnect and catch up",
      "role": "content",
      "text": "1. Select **Start task**. Numbered updates appear in the page.\n1. After a few updates arrive, select **Disconnect**. The displayed update count stops.\n1. Wait a few seconds, then select **Reconnect**. The missed updates arrive, followed by new updates as the agent continues.\n1. Wait for **Complete — all 20 updates received**.\n\nThe task keeps running while the subscription is disconnected. The page remembers the last applied event cursor and reconnects with `?after=` to receive retained updates after that cursor. Expand **What is being resumed?** to see the task ID and saved cursor.\n\nThe page uses the browser's built-in `EventSource` client. It does not restart the task on reconnect. Replay requires retained Redis history; it does not restart interrupted agent execution."
    },
    {
      "id": "connect-the-a2a-handler-to-redis",
      "title": "Connect the A2A handler to Redis",
      "role": "content",
      "text": "The downloaded application defines `CountingAgent`, its streaming agent card, and the Redis client. These are the integration points:\n\n[code example]\n\n`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()`.\n\nOn reconnect, the browser uses the same task ID and the last cursor it applied:\n\n[code example]\n\nThe request resumes event delivery for the existing task; it does not submit the work again.\n\nStop the application with Control-C before trying the FastAPI example on the same port."
    },
    {
      "id": "resume-fastapi-events",
      "title": "Resume FastAPI events",
      "role": "content",
      "text": "A simulated travel agent plans a day in Rome. It publishes twenty progress events, one per second, then returns a sample itinerary. Disconnect while it works, then reconnect to catch up and receive the answer. The agent uses scripted steps, so you need no model account or live travel service. These are application-defined events, independent of A2A tasks."
    },
    {
      "id": "install-1",
      "title": "Install",
      "role": "setup",
      "text": "In your application terminal, create an environment for the FastAPI example:\n\n[code example]"
    },
    {
      "id": "start-the-demo-1",
      "title": "Start the demo",
      "role": "content",
      "text": "1. Save both example files in your `agent-mesh-sse` directory:\n\n   - \n   - \n\n1. Run the application:\n\n   [code example]\n\n1. Open <http://127.0.0.1:8000> in your browser.\n\nThis loopback-only example uses one fixed demo owner and needs no token or sign-in. In a deployed application, authenticate callers and authorize access to each job's events."
    },
    {
      "id": "disconnect-and-catch-up-1",
      "title": "Disconnect and catch up",
      "role": "content",
      "text": "1. Select **Start agent**. Progress messages show the agent preparing its itinerary.\n1. After a few events arrive, select **Disconnect**. The displayed event count stops.\n1. Wait a few seconds, then select **Reconnect**. The missed events arrive, followed by new events as the agent continues.\n1. Wait for **Complete — all 20 events received** and the agent’s sample itinerary.\n\nThe page saves its event cursor and reconnects to the same agent run’s event stream. Expand **What is being resumed?** to see the run’s job ID and saved cursor. Your application runs the agent independently of the subscription; reconnecting does not start it again."
    },
    {
      "id": "publish-and-serve-resumable-events",
      "title": "Publish and serve resumable events",
      "role": "content",
      "text": "The downloaded application uses the FastAPI SDK's standard setup. It creates its\nRedis pools from `REDIS_URL` and manages in-process producer tasks:\n\n[code example]\n\nGive each demo job its own scope and run ID. Start the producer once, then publish\nthrough the writer it receives:\n\n[code example]\n\nThe excerpt shows the API shape; the downloadable producer loops over all twenty\nscripted steps. Reconnecting does not call `start()` again.\n\nThe event endpoint serves the authorized job's scope and run:\n\n[code example]\n\nThe browser reconnects with the last applied cursor. The demo sets\n`REDIS_STREAM_DONE_TTL=3600` unless you override it, retaining a completed run for\nup to one hour, bounded by the run's original lifetime (one hour by default).\nCompletion never extends that lifetime. Replay requires retained history; it\ndoes not restart interrupted execution."
    },
    {
      "id": "when-youre-done",
      "title": "When you're done",
      "role": "content",
      "text": "Stop the demo application with Control-C. If you started local Redis for this example, stop it with Control-C too.\n\nStopping the app leaves a Redis Cloud database running. If you created a disposable database and no longer need it, see [Delete a database](https://redis.io/docs/latest/operate/rc/databases/delete-database)."
    },
    {
      "id": "further-reading",
      "title": "Further reading",
      "role": "content",
      "text": "To add these integrations to your application, follow the [A2A SDK guide](https://redis.io/docs/latest/develop/ai/context-engine/agent-mesh/a2a-sdk) or [FastAPI SSE SDK guide](https://redis.io/docs/latest/develop/ai/context-engine/agent-mesh/fastapi-sse-sdk). See the [Agent Mesh limitations](https://redis.io/docs/latest/develop/ai/context-engine/agent-mesh#requirements-and-limits) for beta qualification."
    }
  ],
  "examples": [
    {
      "id": "choose-your-redis-database-ex0",
      "language": "bash",
      "code": "export REDIS_URL='rediss://<username>:<encoded-password>@<host>:<port>/0?ssl_ca_certs=<absolute-path-to-redis_ca.pem>'",
      "section_id": "choose-your-redis-database"
    },
    {
      "id": "choose-your-redis-database-ex1",
      "language": "bash",
      "code": "redis-server --bind 127.0.0.1 --port 6389 --save '' --appendonly no",
      "section_id": "choose-your-redis-database"
    },
    {
      "id": "choose-your-redis-database-ex2",
      "language": "bash",
      "code": "export REDIS_URL='redis://127.0.0.1:6389/0'",
      "section_id": "choose-your-redis-database"
    },
    {
      "id": "install-ex0",
      "language": "bash",
      "code": "mkdir agent-mesh-a2a\ncd agent-mesh-a2a\npython3 -m venv .venv\nsource .venv/bin/activate\npython -m pip install 'redis-iris[a2a]' uvicorn",
      "section_id": "install"
    },
    {
      "id": "start-the-demo-ex0",
      "language": "bash",
      "code": "python a2a-demo.py",
      "section_id": "start-the-demo"
    },
    {
      "id": "connect-the-a2a-handler-to-redis-ex0",
      "language": "python",
      "code": "from redis_iris.agent_mesh.a2a import RedisTaskStore\nfrom redis_iris.agent_mesh.a2a.routes import create_resumable_rest_routes\n\nstore = RedisTaskStore(\n    redis,\n    namespace=\"quickstart:a2a-browser\",\n    owner_resolver=lambda context: \"local-demo-user\",  # Loopback demo only.\n)\nevents = store.event_stream()\nhandler = store.request_handler(CountingAgent(), agent_card=card, event_stream=events)\nroutes = create_resumable_rest_routes(\n    handler, agent_card=card, store=store, event_stream=events\n)",
      "section_id": "connect-the-a2a-handler-to-redis"
    },
    {
      "id": "connect-the-a2a-handler-to-redis-ex1",
      "language": "javascript",
      "code": "new EventSource(`/tasks/${taskId}:subscribe?after=${encodeURIComponent(cursor)}`);",
      "section_id": "connect-the-a2a-handler-to-redis"
    },
    {
      "id": "install-1-ex0",
      "language": "bash",
      "code": "mkdir agent-mesh-sse\ncd agent-mesh-sse\npython3 -m venv .venv\nsource .venv/bin/activate\npython -m pip install 'redis-iris[fastapi-sse]' uvicorn",
      "section_id": "install-1"
    },
    {
      "id": "start-the-demo-1-ex0",
      "language": "bash",
      "code": "python fastapi-sse-demo.py",
      "section_id": "start-the-demo-1"
    },
    {
      "id": "publish-and-serve-resumable-events-ex0",
      "language": "python",
      "code": "from redis_iris.agent_mesh.fastapi_sse import FastAPIRedis\n\nFastAPIRedis(app).lifespan().streams()",
      "section_id": "publish-and-serve-resumable-events"
    },
    {
      "id": "publish-and-serve-resumable-events-ex1",
      "language": "python",
      "code": "async def produce(writer):\n    await writer.append(\"progress\", {\"number\": number, \"message\": message})\n    await writer.finish(\"completed\", {\"count\": 20, \"answer\": AGENT_ANSWER})\n\nawait streams.start(produce, scope=f\"job:{job_id}\", stream_id=job_id)",
      "section_id": "publish-and-serve-resumable-events"
    },
    {
      "id": "publish-and-serve-resumable-events-ex2",
      "language": "python",
      "code": "from redis_iris.agent_mesh.fastapi_sse import StreamBackendDep\n\n@app.get(\"/jobs/{job_id}/events\", response_class=StreamingResponse)\nasync def events(job_id: UUID, request: Request, streams: StreamBackendDep):\n    job = get_job(job_id)\n    return await streams.sse(str(job_id), request=request, scope=job[\"scope\"])",
      "section_id": "publish-and-serve-resumable-events"
    }
  ]
}
