Exposing Rasa as an A2A Sub-Agent | Rasa Documentation
Build Your First Agent in Just a Few Minutes with Rasa Copilot
New in Rasa Pro 3.17
Rasa can expose your assistant as a native Agent-to-Agent (A2A) sub-agent.
Overview
In the orchestrator model, Rasa calls external A2A agents from flows. This guide covers the inverse role: your Rasa assistant runs as an A2A sub-agent that an external orchestrator discovers and invokes.
With an a2a_server block in endpoints.yml, rasa run exposes the A2A protocol on the same port as REST and channel webhooks. The orchestrator fetches your AgentCard, sends user turns over JSON-RPC, and receives structured task lifecycle updates mapped from Rasa's dialogue state.
For full configuration reference, see A2A Server.
Prerequisites
Before enabling A2A server mode:
- Train a CALM assistant with the user-facing flows you want to expose as skills.
- Set session config in
domain.yml—start_session_after_expirymust befalseso resumed orchestrator contexts do not triggeraction_session_startand reset slots.
session_config:
session_expiration_time: 60
start_session_after_expiry: false # required when a2a_server is enabled
- Plan for single-worker deployment — set
SANIC_WORKERS=1until Redis-backed A2A stores ship. Scale with additional replicas and sticky load balancing bycontextIdinstead of multiple Sanic workers per pod.
Step 1 — Add a2a_server to endpoints.yml
Only description is required. Add a public url when orchestrators reach Rasa through a load balancer or ingress rather than localhost.
a2a_server:
url: "http://localhost:5005"
description: "Banking assistant for transfers and appointments"
include_conversation_repair: true
If you use custom actions, include your action_endpoint in the same file as usual.
Step 2 — Start the Server
Run Rasa with a single Sanic worker and your trained model:
SANIC_WORKERS=1 rasa run -m models/your-model.tar.gz --endpoints endpoints.yml
To serve HTTPS directly, pass the same rasa run SSL flags used for REST and channels — not an a2a_server.tls block in endpoints.yml:
SANIC_WORKERS=1 rasa run \
--ssl-certificate /certs/server.pem \
--ssl-keyfile /certs/server-key.pem \
-m models/your-model.tar.gz \
--endpoints endpoints.yml
When Rasa sits behind a reverse proxy or ingress, set a2a_server.url to the public https://... base URL orchestrators use. See TLS in the A2A server reference.
Multi-replica Deployments
If you run more than one Rasa pod, configure your ingress or load balancer to route all A2A traffic for a given contextId to the same replica. Without this, follow-up turns, messageId deduplication, tasks/cancel, and push callbacks can break because A2A state is in-memory per pod.
Step 3 — Verify the Server is Ready
Confirm the model is loaded and the AgentCard is available:
# Model loaded (no auth configured)
curl http://localhost:5005/status
# Model loaded (Rasa auth token configured)
curl -H "Authorization: Bearer <rasa-auth-token>" http://localhost:5005/status
# Capability discovery (no A2A bearer auth configured)
curl http://localhost:5005/.well-known/agent-card.json
# Capability discovery (A2A bearer auth configured via a2a_server.auth)
curl -H "Authorization: Bearer <jwt>" http://localhost:5005/.well-known/agent-card.json
The AgentCard lists your user flows as skills. The primary signal an orchestrator uses when deciding which sub-agent to route a task to is the AgentCard.
Step 4 — Point Your Orchestrator at the Endpoint
Configure your orchestrator to use the url from the AgentCard.
Example message/send Request
curl -X POST http://localhost:5005/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "req-1",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{"kind": "text", "text": "I want to book an appointment"}],
"messageId": "msg-1",
"contextId": "ctx-user-42"
}
}
}'
Step 5 — Read Structured Results from Completed Flows
Each orchestrator message creates a new A2A task_id. Rasa maps dialogue state to A2A task states: working, input_required, completed, failed, canceled, rejected, and auth_required.