AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Rasa Setting Up React Agents

skill-rasahq-rasa-agent-skills-rasa-setting-up-react-agents · by RasaHQ

>

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-rasahq-rasa-agent-skills-rasa-setting-up-react-agents

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-rasahq-rasa-agent-skills-rasa-setting-up-react-agents)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Rasa Setting Up React Agents? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Configuring ReAct Sub Agents

ReAct sub agents are built-in autonomous agents that dynamically choose which MCP tools to invoke based on conversation context. They operate in a ReAct (Reasoning + Acting) loop — the agent reasons about the user's request, picks a tool, observes the result, and repeats until the task is done.

MCP servers must be defined in endpoints.yml before configuring a ReAct sub agent. See the rasa-configuring-mcp-server skill for server setup and authentication.

This feature is in beta and available starting from Rasa 3.14.0.

Workflow

  1. Ensure the MCP server is defined in endpoints.yml (see rasa-configuring-mcp-server

skill).

  1. Create the sub agent directory with a config.yml

(see "Directory structure" and "Configuration").

  1. Choose between general-purpose or task-specific agent type

(see "General-purpose vs task-specific").

  1. Optionally filter which MCP tools the agent can access

(see "Tool filtering").

  1. Invoke the sub agent from a flow using a call step

(see "Invoking from a flow").

  1. Optionally customize the prompt, input/output processing, or add custom tools

(see "Customization").

  1. Validate the project.

Directory structure

Each ReAct sub agent lives in its own subdirectory under sub_agents/. Both rasa train and rasa run scan this directory by default; pass --sub-agents to either command to use a different directory.

The agent name must be unique across all sub agents and all flow IDs.

your_project/
├── config.yml
├── endpoints.yml
├── domain/
├── data/flows/
└── sub_agents/
    └── stock_explorer/
        ├── config.yml              # required
        ├── prompt_template.jinja2  # optional
        └── custom_agent.py         # optional

Configuration

The sub agent's config.yml connects the agent to one or more MCP servers defined in endpoints.yml. The protocol defaults to RASA — do not set it to A2A.

# sub_agents/stock_explorer/config.yml
agent:
  name: stock_explorer
  description: "Agent that helps users research and analyze stock options"

configuration:
  llm:                                   # optional, default model is provided by Rasa codebase
    model_group: my_llm
  prompt_template: sub_agents/stock_explorer/prompt_template.jinja2  # optional
  timeout: 30                            # optional, seconds before timing out
  max_retries: 3                         # optional, MCP connection retries
  include_date_time: true                # optional, default: true
  timezone: "America/New_York"           # optional, default: "UTC"

connections:
  mcp_servers:
    - name: trade_server
      include_tools:
        - find_symbol
        - get_company_news
        - fetch_live_price

| Key | Required | Description | |-----|----------|-------------| | agent.name | yes | Unique name — must not clash with any flow ID or other sub agent | | agent.description | yes | Brief description of the agent's capabilities | | configuration.llm | no | LLM to power the agent's reasoning. Has a default model | | configuration.prompt_template | no | Path to a Jinja2 prompt template | | configuration.timeout | no | Seconds before timing out. No timeout by default | | configuration.max_retries | no | MCP connection retry attempts. Default: 3 | | configuration.include_date_time | no | Include current date/time in prompts. Default: true | | configuration.timezone | no | IANA timezone (e.g. "UTC", "Europe/London"). Default: "UTC" | | configuration.module | no | Python class path for customization | | connections.mcp_servers | yes | List of MCP servers this agent connects to. At least one required |

Tool filtering

For each MCP server entry under connections.mcp_servers, use include_tools or exclude_tools to control which tools the agent can access. These are mutually exclusive — use one or the other per server, never both.

  • include_tools — only these tools are available to the agent.
  • exclude_tools — all tools except these are available.
connections:
  mcp_servers:
    - name: trade_server
      include_tools:
        - find_symbol
        - get_company_news
    - name: analytics_server
      exclude_tools:
        - admin_analytics

General-purpose vs task-specific

Rasa supports two types of ReAct sub agents. Choose based on how the agent signals completion.

| | General-purpose | Task-specific | |---|---|---| | When to use | Open-ended tasks where the agent decides when it's done | Structured data collection (form filling, booking) | | Completion | Agent calls a built-in task_completed tool | Automatic when exit_if slot conditions are met | | Built-in tools | task_completed only | set_slot_ for each slot in exit_if | | Final response | Sends a summary message to the user | Completes silently — flow continues to next step | | Base class | MCPOpenAgent | MCPTaskAgent |

Invoking from a flow

General-purpose (no exit conditions)

The agent runs autonomously until it calls task_completed:

flows:
  stock_research:
    description: helps research and analyze stock investment options
    steps:
      - call: stock_explorer

Task-specific (with exit conditions)

The agent runs until the specified slot conditions are met. Rasa automatically provides set_slot_ tools for each slot in exit_if:

flows:
  appointment_booking:
    description: helps users book appointments
    steps:
      - call: booking_agent
        exit_if:
          - slots.appointment_time is not null
      - collect: final_confirmation

Customization

Customization is optional. Only create a custom class when you need to:

  • Customize the prompt — add specific instructions or pass slot values as context.
  • Filter input — limit which slots reach the agent.
  • Map output to slots — extract structured data from the agent's tool results.
  • Add custom Python tools — tools that run alongside MCP tools.

Custom prompt template

Create a Jinja2 file and reference it in configuration.prompt_template. Available variables:

  • {{ description }} — the agent's description from config.yml.
  • {{ slots. }} — any slot value.
  • {{ conversation_history }} — full dialogue transcript.
  • {{ current_datetime }} — datetime object (when include_date_time is enabled).

Use methods like {{ current_datetime.strftime("%d %B, %Y") }}.

Creating a custom ReAct agent class

  1. Create a Python file in the sub agent directory (e.g.

sub_agents/stock_explorer/custom_agent.py).

  1. Subclass MCPOpenAgent (general-purpose) or MCPTaskAgent (task-specific).
  2. Override process_input, process_output, and/or get_custom_tool_definitions.
  3. Point configuration.module to the class.
from rasa.agents.protocol.mcp.mcp_open_agent import MCPOpenAgent
from rasa.agents.schemas import AgentInput, AgentOutput, AgentToolResult
from rasa.sdk.events import SlotSet

class StockAnalysisAgent(MCPOpenAgent):
    async def process_input(self, input: AgentInput) -> AgentInput:
        input.slots = [s for s in input.slots if s.name in {"portfolio_id", "risk_level"}]
        return input

    async def process_output(self, output: AgentOutput) -> AgentOutput:
        if output.structured_results:
            results = output.structured_results[-1]
            output.events = output.events or []
            output.events.append(SlotSet("analysis_result", results))
        return output
# sub_agents/stock_explorer/config.yml
agent:
  name: stock_explorer
  description: "Agent that helps users research and analyze stock options"

configuration:
  module: "sub_agents.stock_explorer.custom_agent.StockAnalysisAgent"

connections:
  mcp_servers:
    - name: trade_server

What you can modify

process_input(input: AgentInput) -> AgentInput — modify what the agent receives. Key fields on AgentInput:

| Field | Type | What to do with it | |-------|------|--------------------| | slots | List[AgentInputSlot] | Filter to only relevant slots | | user_message | str | Rewrite or augment the user message | | conversation_history | str | Trim or redact sensitive history | | metadata | Dict[str, Any] | Inject custom metadata |

process_output(output: AgentOutput) -> AgentOutput — modify what comes back into Rasa. Key fields on AgentOutput:

| Field | Type | What to do with it | |-------|------|--------------------| | events | Optional[List[SlotSet]] | Add SlotSet events to store data in Rasa slots | | structured_results | Optional[List] | Read raw results from agent tool calls | | response_message | Optional[str] | Rewrite the message sent to the user |

Adding custom tools

Implement get_custom_tool_definitions to add Python tools alongside MCP tools. Each tool definition follows the OpenAI function calling spec and must include a tool_executor key pointing to an async method.

The tool_executor method receives arguments as a dict and must return an AgentToolResult:

| Field | Type | Description | |-------|------|-------------| | tool_name | str | Name of the tool | | result | Optional[str] | The tool's output | | is_error | bool | Whether the execution failed. Default: False | | error_message | Optional[str] | Error details if execution failed |

Tool executors must be async. Do not use blocking calls (time.sleep, synchronous requests). Use httpx.AsyncClient, asyncio.to_thread, etc.

from typing import Any, Dict, List

class StockAnalysisAgent(MCPOpenAgent):
    def get_custom_tool_definitions(self) -> List[Dict[str, Any]]:
        return [{
            "type": "function",
            "function": {
                "name": "recommend_stocks",
                "description": "Analyze results and return stock recommendations",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "search_results": {
                            "type": "string",
                            "description": "The search results to analyze",
                        },
                    },
                    "required": ["search_results"],
                    "additionalProperties": False,
                },
                "strict": True,
            },
            "tool_executor": self._recommend_stocks,
        }]

    async def _recommend_stocks(self, arguments: Dict[str, Any]) -> AgentToolResult:
        results = arguments["search_results"]
        return AgentToolResult(tool_name="recommend_stocks", result=results)

Common pitfalls

  • Agent name clashes with flow IDs — the sub agent name must be unique across all

flows and all other sub agents.

  • Using exit_if with general-purpose agentsexit_if is only for task-specific

agents. General-purpose agents signal completion via task_completed.

  • include_tools and exclude_tools on the same server — these are mutually

exclusive per MCP server entry. Using both causes a validation error.

  • MCP server name mismatch — the name under connections.mcp_servers must

exactly match a name in endpoints.yml.

  • Blocking calls in custom tool executors — tool executors are async. Using

time.sleep or synchronous HTTP clients blocks the event loop.

  • Invalid timezoneconfiguration.timezone must be a valid IANA timezone name.

Invalid values raise a ValidationError during agent initialization.

  • User messages during processing — messages sent while the sub agent is still

processing are not handled. Users must wait for the agent to complete or reach INPUT_REQUIRED.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.