rasa-sdk

Python SDK for building the custom action server that connects a Rasa chatbot to your own APIs and business logic.

SDK
PyPI
v3.19.0
317stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
91/100Excellent
Development Activity96
Maintenance100
Community88
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture85
Code Quality90
Innovation82
Learning Curve50

Rasa SDK is the official Python toolkit for implementing custom actions that Rasa’s dialogue engine calls when a conversation needs to reach outside built-in NLU and rules — hitting an internal API, updating slots, or querying a database. It ships as a standalone action server: a Sanic-based HTTP webhook by default, with a full gRPC server as an alternative transport, so custom business logic and credentials run in a separate process from the core Rasa model.

Built around Action and FormValidationAction base classes, a Tracker for reading conversation state, and a CollectingDispatcher for returning responses, the SDK gives custom-action authors the same primitives whether the transport is a single HTTP request or a persistent gRPC stream. It also bundles OpenTelemetry-based tracing, a pluggy-based plugin system for extending the Sanic app, and a small knowledge-base module for FAQ-style lookups.

What You Get

  • A standalone action server (rasa_sdk.endpoint.run) exposing /webhook, /actions, and /health over Sanic, callable by any Rasa assistant over the network
  • An alternative gRPC server (rasa_sdk.grpc_server) for teams that want a persistent, typed connection instead of unary HTTP webhooks
  • Action and FormValidationAction base classes plus a Tracker object for reading slots, intents, and conversation history inside custom logic
  • CollectingDispatcher with both a batched API (utter_message) and a streaming API (stream_start/stream_chunk/stream_end) for incremental responses
  • Built-in OpenTelemetry tracing hooks and a pluggy-based plugin system for extending the Sanic app at startup

Common Use Cases

  • Calling an internal REST API or database from within a Rasa conversation to fetch account or order data before responding
  • Validating and normalizing form slots (e.g. an email format or a zip code lookup) before a Rasa form proceeds
  • Running custom business logic — pricing calculations, entitlement checks, escalation rules — that shouldn’t live inside the NLU model
  • Streaming partial responses (e.g. from an LLM call made inside a custom action) back to the end user as they’re generated
  • Answering FAQ-style queries via the bundled knowledge-base module against a small stored graph of facts

Under The Hood

Architecture The SDK follows a layered, transport-agnostic design: rasa_sdk.endpoint.create_app builds a Sanic application exposing /webhook, /actions, and /health, delegating request handling to executor.ActionExecutor, which discovers Action subclasses via pkgutil/importlib scanning of user action packages and dispatches to their async run() methods with a Tracker (conversation state) and CollectingDispatcher (response collection) injected as arguments. A parallel grpc_server.py implements the same dispatch contract over gRPC using generated protobuf stubs, so the executor’s core dispatch logic is decoupled from transport. Cross-cutting concerns — OpenTelemetry tracing (tracing/) and a pluggy-based plugin system (plugin.py) — are layered on top of both transports rather than baked into ActionExecutor, and forms.py builds a FormValidationAction abstraction on top of the base Action class for structured slot validation. Because actions are loaded dynamically at runtime rather than compiled against a pinned SDK version, changes to the core Action/Tracker contract would ripple into every user-authored action package across all Rasa deployments.

Tech Stack The project targets Python >=3.10,<3.15 and is built with Poetry. The HTTP action server runs on Sanic ~25.12 with Sanic-Cors for CORS handling and multidict for header manipulation; the gRPC alternative depends on grpcio ~1.80 and grpcio-health-checking, with protobuf ~5.29 for wire messages. Distributed tracing runs on the full opentelemetry-sdk/opentelemetry-exporter-otlp/opentelemetry-api ~1.33 stack; pydantic ~2.13 validates request/response payloads; pluggy powers the plugin-hook system; coloredlogs, ruamel.yaml, websockets, and typing-extensions round out smaller utility dependencies. No database dependency is bundled — the knowledge_base module ships its own lightweight in-memory/file-backed storage rather than an ORM. Deployment targets Docker, via an official rasa/rasa-sdk image built from the repo’s own Dockerfile, fronting a Rasa assistant over the network.

Code Quality The project carries an extensive test suite spanning thousands of lines across tests/, mirroring nearly every module — test_executor.py, test_forms.py, test_grpc_server.py, test_interfaces.py, test_tracker.py — plus dedicated knowledge_base/ and tracing/ test subdirectories, run via pytest with pytest-asyncio’s auto mode and coverage reporting. Type checking is enforced via mypy, and the codebase is comprehensively type-hinted throughout interfaces.py, executor.py, and events.py. Style is enforced via ruff (lint and format, with docstring rules selected), and CI runs the full test/lint/typecheck matrix alongside separate gRPC standalone and Docker-based integration test jobs. Error handling is explicit and typed — custom exceptions such as ActionExecutionRejection, ActionNotFoundException, and ActionMissingDomainException are raised deliberately and mapped to specific HTTP status codes in endpoint.py rather than being swallowed.

API Design Custom actions are authored by subclassing Action and implementing name() and async run(dispatcher, tracker, domain) — a minimal, consistent contract that stays identical whether the action server is invoked via HTTP webhook or gRPC. FormValidationAction further reduces boilerplate for multi-turn slot collection by letting authors define one validate_<slot_name> method per slot instead of hand-rolling a state machine. The CollectingDispatcher is the standout ergonomic choice: it exposes the same utter_message-style API regardless of transport, while its stream_start/stream_chunk/stream_end API lets an action stream partial responses (for example, from an LLM call) without the author needing to branch on which transport invoked them — that complexity is absorbed by the executor instead. Getting started requires minimal boilerplate: a bare action package with one __init__.py and a single Action subclass is runnable via rasa_sdk.endpoint immediately.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search