CrewAI Multi-Agents

Course Content

CrewAI Multi-Agents

9 sections · 53 lessons

How would you combine CrewAI with LangGraph or RAG systems?


Deterministic outside, autonomous insideLangGraph — state, checkpoints, approvalsNode — calls the crew, stores a schemaCrew — agents do the open-ended draftingTool — retrieval filtered by policy_id
Every seam is a Pydantic schema, so retrieval, crew and graph can each be tested and replaced on their own.

What you need to know

Pattern 1: a crew inside a LangGraph node

Python
from typing import TypedDictfrom langgraph.graph import StateGraph, START, ENDfrom langgraph.checkpoint.memory import InMemorySaverfrom langgraph.types import interruptclass State(TypedDict):    claim_id: str    draft: dict    approved: booldef draft_node(state: State) -> dict:    out = ClaimsCrew().crew().kickoff(inputs={"claim_id": state["claim_id"]})    return {"draft": out.pydantic.model_dump()}def approve_node(state: State) -> dict:    answer = interrupt({"draft": state["draft"]})   # pause for a person    return {"approved": answer == "approve"}g = StateGraph(State)g.add_node("draft", draft_node)g.add_node("approve", approve_node)g.add_edge(START, "draft")g.add_edge("draft", "approve")g.add_edge("approve", END)app = g.compile(checkpointer=InMemorySaver())   # Postgres in production

LangGraph saves state after each node, so if the approval takes two days or the server restarts, the crew does not run again. The crew returns a Pydantic model, and the node stores it as a plain dict in the graph state.

If you prefer one framework, a CrewAI Flow with @persist and @human_feedback plays the same outer role.

Pattern 2: RAG as a tool

CrewAI's knowledge_sources are quick to set up, but you get less control over how documents are split, filtered and ranked. For serious retrieval, write a tool:

Python
from crewai.tools import BaseToolfrom pydantic import BaseModel, Fieldclass PolicySearchInput(BaseModel):    query: str = Field(description="What to find in the policy wording")    policy_id: strclass PolicySearchTool(BaseTool):    name: str = "policy_search"    description: str = "Search one customer's policy wording. Returns clauses with IDs."    args_schema: type[BaseModel] = PolicySearchInput    def _run(self, query: str, policy_id: str) -> str:        hits = retriever.search(query, filter={"policy_id": policy_id}, k=5)        return "\n".join(f"[{h.clause_id}] {h.text[:400]}" for h in hits)

Then give it only to the policy agent, add sources: list[str] to that task's output_pydantic, and use a guardrail that checks every cited clause ID was actually returned by the tool.

knowledge_sources

  • Set up in a few lines
  • CrewAI chooses chunking and embedding
  • Good for small, stable reference text

Retrieval as a tool

  • You own chunking, filters and reranking
  • Retrieval can be tested on its own
  • Good for large, changing or per-customer data

A real-life example

An insurer's settlement system is a LangGraph graph: collect documents, run the claims-review crew, wait for manager approval above ₹2 lakh, then pay out. The crew's policy agent uses a policy_search tool over 40,000 policy documents in a vector store, filtered by policy_id so it never reads another customer's policy.

Before the tool had the filter, the agent sometimes cited a clause from a different product's policy. The citation guardrail caught 3% of drafts with a clause ID that did not come from the tool. After adding the filter and a reranker, that fell to 0.2%. Because retrieval is a separate tool, the team measures it on its own (the right clause in the top 5 for 96% of test questions) without running the crew at all.

Follow-up questions to expect

  • "Why not run LangGraph inside CrewAI instead?" — You can wrap a graph as a tool, but the outer layer should own durability and approvals, so graph-outside is more common.
  • "When are knowledge_sources enough?" — Small, stable reference material, like a 20-page style guide or product FAQ, where default chunking works.
  • "How do you stop a crew from running twice after a graph resume?" — The checkpointer saves the node's output, so a completed node is not rerun; keep the crew's tools idempotent anyway.