From eb0cc9d9d329d59a217d9d6402b2a3e39b8f5f05 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 3 Feb 2026 06:20:35 +0530 Subject: [PATCH] docs: add CrewAI integration page (#720) Co-authored-by: Claude Opus 4.5 Co-authored-by: Dhravya Shah --- apps/docs/docs.json | 1 + apps/docs/integrations/crewai.mdx | 338 ++++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 apps/docs/integrations/crewai.mdx diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 2f543b02..ace8fe43 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -155,6 +155,7 @@ "integrations/openai", "integrations/mastra", "integrations/langchain", + "integrations/crewai", "integrations/agno", "integrations/memory-graph", "integrations/claude-memory", diff --git a/apps/docs/integrations/crewai.mdx b/apps/docs/integrations/crewai.mdx new file mode 100644 index 00000000..f4fdc9c4 --- /dev/null +++ b/apps/docs/integrations/crewai.mdx @@ -0,0 +1,338 @@ +--- +title: "CrewAI" +sidebarTitle: "CrewAI" +description: "Add persistent memory to CrewAI agents with Supermemory" +icon: "users" +--- + +CrewAI agents don't remember anything between runs by default. Supermemory fixes that. You get a memory layer that stores what happened, who the user is, and what they care about. Your crews can pick up where they left off. + +## What you can do + +- Give agents access to user preferences and past interactions +- Store crew outputs so future runs can reference them +- Search memories to give agents relevant context before they start + +## Setup + +Install the required packages: + +```bash +pip install crewai supermemory python-dotenv +``` + +Configure your environment: + +```bash +# .env +SUPERMEMORY_API_KEY=your-supermemory-api-key +OPENAI_API_KEY=your-openai-api-key +``` + +Get your Supermemory API key from [console.supermemory.ai](https://console.supermemory.ai). + +## Basic Integration + +Initialize Supermemory and inject user context into your agent's backstory: + +```python +import os +from crewai import Agent, Task, Crew, Process +from supermemory import Supermemory +from dotenv import load_dotenv + +load_dotenv() + +memory = Supermemory() + +def build_context(user_id: str, query: str) -> str: + """Fetch user profile and relevant memories.""" + result = memory.profile(container_tag=user_id, q=query) + + static = result.profile.static or [] + dynamic = result.profile.dynamic or [] + memories = result.search_results.results if result.search_results else [] + + return f""" +User Profile: +{chr(10).join(static) if static else 'No profile data.'} + +Current Context: +{chr(10).join(dynamic) if dynamic else 'No recent activity.'} + +Relevant History: +{chr(10).join([m.memory or m.chunk for m in memories[:5]]) if memories else 'None.'} +""" + +def create_agent_with_memory(user_id: str, role: str, goal: str, query: str) -> Agent: + """Create an agent with user context baked into its backstory.""" + context = build_context(user_id, query) + + return Agent( + role=role, + goal=goal, + backstory=f"""You have access to the following information about the user: +{context} + +Use this context to personalize your work.""", + verbose=True + ) +``` + +--- + +## Core Concepts + +### User profiles + +Supermemory tracks two kinds of user data: + +- **Static facts**: Things that don't change often (preferences, job title, tech stack) +- **Dynamic context**: What the user is working on right now + +```python +result = memory.profile( + container_tag="user_abc", + q="project planning" # Optional: also returns relevant memories +) + +print(result.profile.static) # ["Prefers Agile methodology", "Senior engineer"] +print(result.profile.dynamic) # ["Working on Q2 roadmap", "Focused on API design"] +``` + +### Storing memories + +Save crew outputs so future runs can reference them: + +```python +def store_crew_result(user_id: str, task_description: str, result: str): + """Save crew output as a memory.""" + memory.add( + content=f"Task: {task_description}\nResult: {result}", + container_tag=user_id, + metadata={"type": "crew_execution"} + ) +``` + +### Searching memories + +Pull up past interactions before running a crew: + +```python +results = memory.search.memories( + q="previous project recommendations", + container_tag="user_abc", + search_mode="hybrid", + limit=10 +) + +for r in results.results: + print(r.memory or r.chunk) +``` + +--- + +## Example: research crew with memory + +This crew has two agents: a researcher and a writer. The researcher adjusts its technical depth based on the user's background. The writer remembers formatting preferences. Both can see what the user has asked about before. + +```python +import os +from crewai import Agent, Task, Crew, Process +from crewai_tools import SerperDevTool +from supermemory import Supermemory +from dotenv import load_dotenv + +load_dotenv() + +class ResearchCrew: + def __init__(self): + self.memory = Supermemory() + self.search_tool = SerperDevTool() + + def get_user_context(self, user_id: str, topic: str) -> dict: + """Retrieve user profile and related research history.""" + result = self.memory.profile( + container_tag=user_id, + q=topic, + threshold=0.5 + ) + + return { + "expertise": result.profile.static or [], + "focus": result.profile.dynamic or [], + "history": [m.memory for m in (result.search_results.results or [])[:3]] + } + + def create_researcher(self, context: dict) -> Agent: + """Build a researcher agent with user context.""" + expertise_note = "" + if context["expertise"]: + expertise_note = f"The user has this background: {', '.join(context['expertise'])}. Adjust technical depth accordingly." + + history_note = "" + if context["history"]: + history_note = f"Previous research on related topics: {'; '.join(context['history'])}" + + return Agent( + role="Research Analyst", + goal="Conduct research tailored to the user's expertise level", + backstory=f"""You research topics and synthesize findings into clear summaries. +{expertise_note} +{history_note}""", + tools=[self.search_tool], + verbose=True + ) + + def create_writer(self, context: dict) -> Agent: + """Build a writer agent that matches user preferences.""" + style_note = "Write in a clear, technical style." + for fact in context.get("expertise", []): + if "non-technical" in fact.lower(): + style_note = "Write in plain language, avoiding jargon." + break + + return Agent( + role="Content Writer", + goal="Transform research into readable content", + backstory=f"""You write clear, engaging content. {style_note}""", + verbose=True + ) + + def research(self, user_id: str, topic: str) -> str: + """Run the research crew and store results.""" + context = self.get_user_context(user_id, topic) + + researcher = self.create_researcher(context) + writer = self.create_writer(context) + + research_task = Task( + description=f"Research the following topic: {topic}", + expected_output="Detailed findings with sources", + agent=researcher + ) + + writing_task = Task( + description="Write a summary based on the research findings", + expected_output="A clear, structured summary", + agent=writer + ) + + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + verbose=True + ) + + result = crew.kickoff() + + # Store for future sessions + self.memory.add( + content=f"Research on '{topic}': {str(result)[:500]}", + container_tag=user_id, + metadata={"type": "research", "topic": topic} + ) + + return str(result) + + +if __name__ == "__main__": + crew = ResearchCrew() + + # Teach preferences + crew.memory.add( + content="User prefers concise summaries with bullet points", + container_tag="researcher_1" + ) + + # Run research + result = crew.research("researcher_1", "latest developments in AI agents") + print(result) +``` + +--- + +## More patterns + +### Crews with multiple users + +Sometimes you need context from several users at once: + +```python +def create_collaborative_context(user_ids: list[str], topic: str) -> str: + """Aggregate context from multiple users.""" + combined = [] + + for user_id in user_ids: + result = memory.profile(container_tag=user_id, q=topic) + if result.profile.static: + combined.append(f"{user_id}: {', '.join(result.profile.static[:3])}") + + return "\n".join(combined) if combined else "No shared context available." +``` + +### Only storing successful runs + +You might not want to save every crew output: + +```python +def store_if_successful(user_id: str, task: str, result: str, success: bool): + """Only store successful task completions.""" + if not success: + return + + memory.add( + content=f"Completed: {task}\nOutcome: {result}", + container_tag=user_id, + metadata={"type": "success", "task": task} + ) +``` + +### Using metadata to organize memories + +Metadata lets you filter memories by project, agent, or whatever else makes sense: + +```python +# Store with metadata +memory.add( + content="Research findings on distributed systems", + container_tag="user_123", + metadata={ + "project": "infrastructure-review", + "agents": ["researcher", "writer"], + "confidence": "high" + } +) + +# Search with filters +results = memory.search.memories( + q="distributed systems", + container_tag="user_123", + filters={ + "AND": [ + {"key": "project", "value": "infrastructure-review"}, + {"key": "confidence", "value": "high"} + ] + } +) +``` + +--- + +## Related docs + + + + How automatic profiling works + + + Filtering and search modes + + + Memory for LangChain apps + + + Memory middleware for Next.js + +