Skip to content
RasaGet a free licence
Guides for AI teams

Guide · AI product engineer

Help customers prepare a claim with CrewAI and Rasa

Use CrewAI to research the documents needed for an insurance claim, and Rasa to ask customers questions and explain the checklist.

by Rod Rivera

About 5 minutes

Key takeaways (3)
  • Let CrewAI research the checklist and Rasa explain it to the customer.
  • Check the source and task results before accepting a checklist.
  • Return tool failures in the form CrewAI can recognise.

A customer wants to know which documents they need for an insurance claim. This tutorial uses an existing CrewAI research crew to prepare the checklist. Configure Rasa to ask which kind of claim they have and explain the checked result.

What happens when the crew cannot read its source? In our test, the tool returns “Synthetic source temporarily unavailable (code: source_unavailable)” as plain text. The crew still finishes, and this application accepts its checklist. Selecting the RAISE failure policy leaves that result unchanged.

The missing piece is the tool’s return type. A plain error string supplies no native failure record. Return the same wording as a ToolFailure and WARN records it; RAISE aborts. The six-case native exercise keeps the source error wording fixed and varies representation and policy.

Source tool returnsPolicyRecorded failuresNative outcomeThis application’s handoff
Plain error stringIGNORE0Both tasks finishReady
Plain error stringWARN0Both tasks finishReady
Plain error stringRAISE0Both tasks finishReady
Declared failureIGNORE0Both tasks finishReady
Declared failureWARN1Both tasks finishIncomplete
Declared failureRAISENo returned resultToolExecutionFailedErrorNo crew result

Each case observes one actual native source-tool call. The error wording and scripted source/checklist replies stay fixed. The experiment inspects SDK execution and this application’s acceptance rule. Its narrow public fixture makes the source failure repeatable without a provider request.

Before giving existing tools another customer channel, check how they report business failures. A readable error message alone leaves this failure flag empty. Keep the useful handler, adapt its unsuccessful outcomes to the native failure type, and then apply your evidence checks.

If you already have a useful research crew, keep it. This example adds a Rasa conversation around a HarborCover document checklist. CrewAI keeps the research roles, registered source tool and model. Mantle asks which public claim type the user needs, passes their question to the crew and explains the checked result. The fictional sources contain vehicle and travel document lists.

Keep the researcher and checklist writer

The existing crew has two native Agent objects and two sequential Task objects. The source researcher calls read_claim_source. The checklist writer receives the source task as context and returns the required document names. Each task has a typed JSON output.

ResponsibilityOwnerWhat stays there
Research and document listCrewAIAgents, tasks, source tool, configured model and task records
Missing input and explanationRasa MantleAsk for the public claim type, call the application tool and explain the checked result
Accepted evidenceApplicationBind the selected type, inspect task records and failures, validate the returned source and checklist

The live worker uses the crew’s configured model. Native controls replace its responses with a scripted BaseLLM, so the failure is repeatable without a provider request. Both paths construct the same research crew.

User question Mantle collects claim type Existing native CrewAI crew Source and checklist task records Application checks records and failures Checked checklist explained by Mantle accepted Incomplete: offer retry or stop evidence missing
  1. A final answer can exist alongside a failed source read. Inspect the native records before accepting its checklist.
  2. Incomplete research remains a conversation outcome. The user can retry or stop instead of receiving an invented document list.
FigureCheck research before the conversation explains it

Inspect the records, then accept the checklist

The native representation control returns either the failure object’s message or the object itself. It replaces both the agent and task tool registrations, then observes the invoked handler. The observations confirm that each matrix case invokes its selected handler once, with the same error wording.

The conversation adapter uses declared failures with WARN. The native record survives completion, allowing the application to withhold incomplete research. The matrix’s RAISE arm aborts with a native exception. If your crew uses that policy, keep the worker’s exception-to-incomplete mapping. With a legacy error string, first repair the tool’s failure signal: a guard reading an empty failure list has nothing to reject.

The acceptance function first checks the selected public type and recorded failures:

The single check that withholds failed research

Prefer: Intact application guard

    if claim_type not in PUBLIC_SOURCES or result.has_tool_failures:
        return incomplete

The failed run returns incomplete.

Avoid: One guard removed by the control

    if claim_type not in PUBLIC_SOURCES:
        return incomplete

The same failed run returns ready.

It then requires exactly the source and checklist task records. Both must parse into their expected schemas, with extra fields refused. The source ID, revision and document list must match the selected public fixture. The checklist must preserve that same claim type and document list.

This contract is deliberately small. If you adapt an existing crew, define the evidence your application needs from each task. A customer-service handoff might need source references, a timestamp and explicit missing evidence. Keep those checks in application code before the result reaches the reply.

The mutation test removes only or result.has_tool_failures from this application’s function. The failed native result still passes the other checks and becomes ready. That makes the failure check’s role visible. It also shows why adding another instruction to the conversation would leave the acceptance rule unchanged.

Keep the two runtimes separately pinned

These selected releases need different PyJWT versions. CrewAI requires >=2.15,<3; Rasa Pro requires >=2.13,<2.14. The combined dependency lock cannot satisfy both. The example therefore has two locked Python environments.

Mantle imports a small standard-library process bridge. It starts a fixed crew worker and sends the claim type and question as JSON on stdin. The worker executes the native crew in its own environment and returns one JSON result. The bridge checks the selected public source and exact checklist again before passing it to Mantle.

Customer text stays in the JSON input. The command, worker file and interpreter are application settings. The worker’s subprocess timeout is shorter than the Mantle tool allowance. Errors, malformed output and a timeout return an incomplete result.

The source protocol controls exercise a fixed command, invalid inputs, malformed output and timeout handling. Two controls also start the actual native fixture worker, including its failed-source path.

Let Rasa collect the missing choice

The Mantle skill asks for vehicle or travel and calls select_claim_type. Application state binds that choice to the conversation. The actual decorated binding controls reach the worker, keep mocked caller selections separate and withhold the recorded source failure. The research tool then accepts only the question; it gets the selected type from that mapping.

If the choice is missing, the tool returns needs_claim_type. If a different type is selected later, it returns claim_type_changed. Start another conversation for the other public example. A ready result supplies the source ID, revision and required document names for Mantle to explain. An incomplete result gives the conversation a recovery path.

The example uses process-local sender mapping. It does not authenticate an insurance customer. Add your identity and access controls before connecting private claim data; the supplied corpus is public and synthetic.

Keep filing, approval and payment operations outside this read-only research handoff. If your existing crew has write tools, give those operations their own authorisation and confirmation rules before exposing them to customers.

The failure signal is a typed native result in the pinned ReadClaimSource._run:

def _run(self):
    if self.unavailable:
        return ToolFailure(
            message="Synthetic source temporarily unavailable",
            code="source_unavailable",
            retryable=True,
        )
    return PUBLIC_SOURCES[self.claim_type].model_dump_json()

Return the ToolFailure object so the framework records the failed tool. Returning only its message changes the native signal to ordinary text. The ready-result acceptance check still checks the final checklist separately.

The Mantle tool looks up the previously selected type through the current sender. Its research argument contains only the question:

selected = SESSIONS.get(sender())
if selected is None:
    return ToolResult(llm_response={"status": "needs_claim_type"})
return ToolResult(
    llm_response=await asyncio.to_thread(WORKER.checklist, selected, question)
)

This is an excerpt of research_claim_documents. The public exercise stores its selected vehicle or travel type outside the model-supplied research input. The existing worker retains its crew, tools and task sequence.

Run the crew on its own, then add the conversation

Start with the Rasa quickstart if Mantle is new to you. Use Python 3.12 and the supplied locks. From a fresh checkout:

git clone https://github.com/RasaHQ/rasa-community-resources.git
cd rasa-community-resources
git fetch origin 413e46b3b596c2a96b8495ad6730020a90bb747f
git checkout 413e46b3b596c2a96b8495ad6730020a90bb747f
python3 scripts/workspace.py start tutorials/frameworks-with-rasa/crewai --owner claim-crew-demo
cd tutorials/frameworks-with-rasa/crewai
make test
.venv/bin/python demo_completion.py
.venv/bin/python demo_failure_signals.py

The 11 October scripted qualification ran the core suite from the crewai-mantle directory, using the separate CrewAI interpreter. This is the recorded command; set up both projects as described here before repeating it:

CREWAI_TELEMETRY_DISABLED=true OTEL_SDK_DISABLED=true ../crewai/.venv/bin/python -m unittest discover -s ../crewai/tests -p 'test_*.py'

Its literal recorded summary was:

Ran 25 tests in 0.216s

OK

The same dated scripted run continued from crewai-mantle with the transport protocol controls. This is a separate literal command and output excerpt:

CREWAI_TELEMETRY_DISABLED=true OTEL_SDK_DISABLED=true .venv/bin/python -m unittest discover -s ../crewai-transport/tests -p 'test_*.py'
Ran 7 tests in 3.081s

OK

Finally, it exercised the actual decorated Mantle binding:

CREWAI_TELEMETRY_DISABLED=true OTEL_SDK_DISABLED=true .venv/bin/python -m unittest discover -s tests -p 'test_*.py'
Ran 4 tests in 4.555s

OK

These offline tests make zero provider model requests. Each excerpt retains its own recorded timing; warnings and per-test output lie outside the excerpts.

Expected output from demo_completion.py, as defined by the pinned fixture: these are fixture expectations, not an independently preserved command receipt.

{"final_output_present": true, "handoff_status": "ready", "recorded_tool_failures": 0, "source_unavailable": false, "tasks": ["source", "checklist"]}
{"final_output_present": true, "handoff_status": "incomplete", "recorded_tool_failures": 1, "source_unavailable": true, "tasks": ["source", "checklist"]}

From the crew directory, inspect the native failure code yourself:

.venv/bin/python - <<'PY'
from claim_crew.native_fixture import create_fixture
result = create_fixture("vehicle", unavailable=True).kickoff()
print(result.tool_failures[0].failure.code)
PY

The native control checks this same code: source_unavailable. The completed tasks remain present; it is the recorded failure that makes research incomplete.

The failure-signal exercise prints six JSON records matching the opening table. Inspect tool_calls and observed_results as well: each case ran the source tool once, with the same error wording. The plain-string raise case still finishes and records zero failures.

Start the selected Rasa environment from the repository root while keeping the crew environment available for its worker:

cd ../../..
python3 scripts/workspace.py start tutorials/frameworks-with-rasa/crewai-mantle --owner claim-conversation-demo
cd tutorials/frameworks-with-rasa/crewai-mantle
make test
make validate

Export your own RASA_PRO_LICENSE and OPENAI_API_KEY using the companion .env.example as the variable list. CREW_MODEL selects the existing crew’s model; Mantle uses its separate integrations.yml configuration. Each model makes its own provider requests. Then train and start the local REST channel:

make train
make run

In another terminal, try this reader exercise:

curl -sS http://localhost:5019/webhooks/rest/webhook \
  -H 'Content-Type: application/json' \
  -d '{"sender":"claim-demo","message":"What documents do I need?"}'
curl -sS http://localhost:5019/webhooks/rest/webhook \
  -H 'Content-Type: application/json' \
  -d '{"sender":"claim-demo","message":"Use the vehicle example"}'

Keep the sender when supplying the missing choice. Check for HC-V-101, its revision and the two vehicle document names. Use another sender for travel and check HC-T-201. Record whether an incomplete result leads to a retry or stop, and whether the response stays within the read-only checklist task.

Qualification covers the native crew, process bridge and actual decorated Mantle bindings. Licensed project validation, training and a cold archive load also passed. The native tests use scripted responses; run and assess your configured models when adapting the reader exercise.

Stop your own server and finish worker operations. From the repository root, retire both selected environments with the same owners used at creation:

python3 scripts/workspace.py retire tutorials/frameworks-with-rasa/crewai-mantle --owner claim-conversation-demo --inactive
python3 scripts/workspace.py retire tutorials/frameworks-with-rasa/crewai --owner claim-crew-demo --inactive

For a worker built as a graph, the LangGraph conversation guide shows how to keep its workflow state across follow-up questions.