AI / CrewAI Interview Questions II
1. Which is better and why: a single Crew vs combining multiple Crews inside a Flow for a complex pipeline?
| Single Crew | Multiple Crews inside a Flow |
| Simpler to set up for a self-contained task | More setup, but handles genuinely multi-stage pipelines |
| One process governs the whole task, sequential or hierarchical | Each stage can use whichever process fits it best |
| Less explicit control over what happens between stages | Flow's @start/@listen/@router give explicit control over transitions between crews |
| Harder to add persistence or human review mid-pipeline | Naturally supports @persist and @human_feedback at stage boundaries |
Neither is universally better. A single crew is the right choice when a task is genuinely self-contained and doesn't need distinct stages with different coordination needs. As soon as a pipeline has clearly separate stages, like research, then drafting, then review, that benefit from different processes, explicit state, or a human checkpoint between them, combining multiple crews inside a Flow is the pattern CrewAI's own architecture is built to support, described as the point where its power truly shows.
2. Explain the internal working of CrewAI's memory system when memory=True is set?
- When a Crew is instantiated with
memory=True, CrewAI automatically constructs default instances of ShortTermMemory, LongTermMemory, and EntityMemory rather than requiring each to be built manually - The crew's embedder configuration is passed into the ShortTermMemory and EntityMemory constructors, since both rely on embeddings for similarity-based retrieval
- LongTermMemory is initialized without an embedder, since it isn't built around embedding-based similarity search the way the other two are
- ChromaDB serves as the default vector storage backend underlying this memory system, persisting the embedded data
This automatic wiring is what lets a single boolean flag produce a fully functioning three-tier memory system, while still leaving the door open to override any individual memory type with a custom instance when the defaults don't fit.
3. Explain the lifecycle of state persistence in a Flow using the @persist decorator?
- Initialization: a Flow instance is created and automatically assigned a unique identifier, a UUID, as part of its state
- Execution: as @start, @listen, and @router methods run, they read from and write to the Flow's state, whether unstructured as a dictionary or structured as a Pydantic model
- Persistence: with @persist applied to the Flow class, this state is written out to a backing store, SQLite by default, or PostgreSQL for multi-instance deployments, as execution proceeds
- Interruption: if the Flow is interrupted, whether by a crash, a deliberate pause such as @human_feedback, or a restart, its state isn't lost
- Recovery: on resumption, the Flow reloads its persisted state and continues rather than starting over from the beginning
This lifecycle is specifically what makes long-running or human-in-the-loop Flows viable in production, without it, any interruption would force the entire workflow to restart from scratch, discarding whatever progress had already been made.
