Preload agents with documents so they reason over your data — without writing a retrieval tool.
When people want a CrewAI agent to answer questions about their own documents, the instinct is usually to build a retrieval tool: wire up a vector store, write a search function, and hand it to the agent. CrewAI has a lower-friction path for a large class of these cases — knowledge sources. You point an agent (or the whole crew) at some files or strings, CrewAI chunks and embeds them, and the relevant snippets are retrieved and injected automatically at execution time. No retrieval tool, no explicit search step. This article covers the built-in source types, the difference between agent- and crew-level knowledge, how to configure embedders, and where knowledge fits relative to tools and memory.
The mental model
Knowledge is a reference library your agents consult while they work. CrewAI ingests your sources once, splits them into chunks, embeds them into a vector store, and at runtime retrieves the chunks most relevant to the current task — injecting them into the agent's context automatically. The key distinction from tool-based retrieval: an agent preloaded with knowledge doesn't need a dedicated retrieval role or a separate search step in your task. Retrieval just happens.
The built-in source types
CrewAI ships a source class for each common format. The string source takes content inline; the file-based sources take a file_paths list. All are importable from crewai.knowledge.source:
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource
from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource
from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource
from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource
from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource
from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource
# Inline content
string_source = StringKnowledgeSource(
content="Acme's return policy allows refunds within 30 days of purchase."
)
# File-based sources (paths are relative to the ./knowledge directory)
pdf_source = PDFKnowledgeSource(file_paths=["handbook.pdf"])
csv_source = CSVKnowledgeSource(file_paths=["pricing.csv"])
excel_source = ExcelKnowledgeSource(file_paths=["q3_targets.xlsx"])
json_source = JSONKnowledgeSource(file_paths=["config.json"])
text_source = TextFileKnowledgeSource(file_paths=["faq.txt", "terms.txt"])For file-based sources, place your files in a knowledge/ directory at the root of your project and pass paths relative to that directory — file_paths=["handbook.pdf"] resolves to ./knowledge/handbook.pdf, not a path relative to your script.There is also CrewDoclingSource for web pages and richer document formats, which accepts URLs in its file_paths. Use it when your knowledge lives online or in formats the simpler loaders don't handle.
Agent-level vs crew-level knowledge
You can attach knowledge at two scopes, and they compose. Pass knowledge_sources to an Agent to give that one agent a private reference library. Pass knowledge_sources to the Crew to share a library across every agent. When both are present, an agent sees the union: crew knowledge plus its own.
from crewai import Agent, Task, Crew, Process, LLM
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource
specialist_knowledge = StringKnowledgeSource(
content="Internal API rate limits: 1000 req/min on the enterprise tier."
)
crew_knowledge = StringKnowledgeSource(
content="Company support hours are 9-5 ET, Monday to Friday."
)
# Native CrewAI LLM class (not LangChain)
llm = LLM(model="gpt-4o-mini", temperature=0)
specialist = Agent(
role="API Specialist",
goal="Answer technical API questions accurately",
backstory="Expert on the internal platform APIs.",
llm=llm,
knowledge_sources=[specialist_knowledge], # private to this agent
)
generalist = Agent(
role="Support Assistant",
goal="Help with general customer questions",
backstory="Friendly first-line support.",
llm=llm,
)
crew = Crew(
agents=[specialist, generalist],
tasks=[...],
process=Process.sequential,
knowledge_sources=[crew_knowledge], # shared by all agents
)In this setup the specialist can draw on both the crew's support-hours knowledge and its own API rate-limit knowledge, while the generalist sees only the crew-level knowledge. Agent-level knowledge works independently — you don't need any crew-level sources for it to function.
Configuring the embedder
Knowledge retrieval is a vector search, so it needs an embedding model. By default CrewAI uses OpenAI's text-embedding-3-small, even if your agents' LLM is a different provider. That means a knowledge-enabled crew needs an OpenAI key unless you configure a different embedder. You set the embedder with the embedder parameter, at either the crew or the agent level:
# Crew-level embedder (OpenAI, explicit)
crew = Crew(
agents=[agent],
tasks=[...],
knowledge_sources=[knowledge_source],
embedder={
"provider": "openai",
"config": {"model": "text-embedding-3-small"},
},
)
# Agent-level embedder using local Ollama embeddings (no external API)
agent = Agent(
role="Researcher",
goal="Research internal docs",
backstory="Domain expert.",
knowledge_sources=[knowledge_source],
embedder={
"provider": "ollama",
"config": {
"model": "mxbai-embed-large",
"url": "http://localhost:11434/api/embeddings",
},
},
)Keep your embedder consistent across ingestion runs. Switching embedding models changes the vector space, so previously stored chunks won't match new queries — re-embed your sources when you change providers or models.Tuning retrieval
How many chunks are retrieved, and how strict the relevance filter is, is controlled by KnowledgeConfig. Attach it to an agent to override the defaults:
from crewai.knowledge.knowledge_config import KnowledgeConfig
knowledge_config = KnowledgeConfig(results_limit=10, score_threshold=0.5)
agent = Agent(
role="Researcher",
goal="Answer from the knowledge base",
backstory="Careful analyst.",
knowledge_sources=[knowledge_source],
knowledge_config=knowledge_config,
)| Parameter | Default | Effect |
|---|---|---|
| results_limit | 3 | How many relevant chunks to retrieve per query. Raise for broader recall. |
| score_threshold | 0.35 | Minimum relevance score to include a chunk. Raise to cut weak matches. |
Where the vectors live, and re-ingestion
CrewAI persists the embedded chunks so it doesn't re-embed your sources on every run. By default the vector store lives in a platform-specific application-support directory keyed by project name — for example ~/.local/share/CrewAI/{project}/knowledge/ on Linux and the equivalent AppData location on Windows. You can override the base location by setting the CREWAI_STORAGE_DIR environment variable, which is useful for containerized deployments where you want the store on a mounted volume:
import os
os.environ["CREWAI_STORAGE_DIR"] = "./my_project_storage"Because the store is cached, editing a source file doesn't automatically refresh what the agent knows. When your underlying documents change, clear the knowledge storage so CrewAI re-ingests and re-embeds them on the next run — otherwise agents answer from the stale, previously embedded version.Knowledge vs tools vs memory
CrewAI gives agents three different ways to work with information, and they solve different problems. It helps to keep them straight:
- Knowledge — a preloaded reference library the agent consults automatically during a task. Best for relatively stable documents (policies, product docs, specs) that many tasks read from.
- Tools — external functions the agent chooses to call at runtime (search an API, run a query, hit a live system). Best for dynamic or on-demand data the agent must actively fetch.
- Memory — context that persists across a run or across conversations, so the agent remembers earlier interactions. Best for continuity, not for bulk reference material.
A practical guideline: if the information is a corpus the agent should always be able to draw on, use knowledge; if it must be fetched live or on demand, use a tool; if it's about remembering what happened earlier, use memory. These are not mutually exclusive — a support agent might have product docs as knowledge, a live order-lookup tool, and memory of the current conversation all at once.
There is also a scale consideration. Knowledge injects retrieved chunks into the agent's context on every relevant task, which is cheap and predictable for a moderate corpus but can crowd the context window if you point it at very large document sets with a high results_limit. If your reference material is enormous or changes constantly, a retrieval tool the agent calls deliberately — fetching only when it decides it needs to — often scales better than preloading everything as knowledge. Match the mechanism to how stable and how large the data is.
A minimal end-to-end example
from crewai import Agent, Task, Crew, Process, LLM
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource
facts = StringKnowledgeSource(
content="John is 30 years old and lives in San Francisco."
)
llm = LLM(model="gpt-4o-mini", temperature=0)
agent = Agent(
role="User Expert",
goal="Answer questions about the user",
backstory="You know everything about the user.",
llm=llm,
verbose=True,
)
task = Task(
description="Answer this question: {question}",
expected_output="A concise, correct answer.",
agent=agent,
)
crew = Crew(
agents=[agent],
tasks=[task],
process=Process.sequential,
knowledge_sources=[facts], # crew-level knowledge
)
result = crew.kickoff(inputs={"question": "What city does John live in?"})
print(result) # -> San FranciscoWrapping up
Knowledge sources are the fastest way to make a CrewAI agent reason over your own data. You pick a source type for your format, drop files in the knowledge/ directory (or pass strings inline), choose crew- or agent-level scope, and — if you don't want the OpenAI default — configure an embedder. CrewAI handles chunking, embedding, and retrieval so you never write a search tool. Reserve tools for live data and memory for continuity, and use knowledge for the stable reference material your agents should always have at hand.