pocketflow.md
March 26, 2025 · View on GitHub
Pocket Flow - Minimalist LLM Framework in 100 Lines
Pocket Flow is Open Sourced at https://github.com/The-Pocket/PocketFlow
Table 1 compares PocketFlow to existing frameworks. The primary design choices are:
- Graph-based computation model: PocketFlow does not adopt an agent oriented architecture.
- Shared store communication model: Rather than message-passing, all nodes read and write from a shared store.
- No application- or vendor-specific modules: PocketFlow focuses exclusively on core logic.
- Minimal footprint: The entire codebase is 100 lines, yielding a 56KB distribution with no external dependencies.
| Comput. Models | Comm. Models | App-Spec Models | Vendor-Spec Models | LOC | Package + Dep. Size | |
|---|---|---|---|---|---|---|
| LangChain | Agent Chain | Message | Many (e.g., QA, Summarization) | Many (e.g., OpenAI, Pinecone, etc.) | 405K | +166MB |
| LlamaIndex | Agent Graph | Message Shared | Native for RAG (Summarization, KG Indexing) | Many [Optional] (e.g., OpenAI, Pinecone, etc.) | 77K (core-only) | +189MB (core-only) |
| CrewAI | Agent Chain | Message Shared | Many (e.g., FileReadTool, SerperDevTool) | Many (e.g., OpenAI, Anthropic, Pinecone, etc.) | 18K | +173MB |
| Haystack | Agent Graph | Message Shared | Many (e.g., QA, Summarization) | Many (e.g., OpenAI, Anthropic, Pinecone, etc.) | 31K | +195MB |
| SmolAgent | Agent | Message | Some (e.g., CodeAgent, VisitWebTool) | Some (e.g., DuckDuckGo, Hugging Face, etc.) | 8K | +198MB |
| LangGraph | Agent Graph | Message Shared | Some (e.g., Semantic Search) | Some (e.g., PostgresStore, SqliteSaver, etc.) | 37K | +51MB |
| AutoGen | Agent | Message | Some (e.g., Tool Agent, Chat Agent) | Many [Optional] (e.g., OpenAI, Pinecone, etc.) | 7K (core-only) | +26MB (core-only) |
| PocketFlow | Graph | Shared | None | None | 100 | +56KB |
Table 1: Comparison of AI system frameworks for computation models, communication models, application-specific models, vendor-specific models, lines of code, and package + dependency size. PocketFlow uses a nested directed graph (instead of agent or chain) as its computation model and shared storage (instead of message passing) as its communication model, without any application or vendor-specific models, requiring only 100 lines of code and a 56KB package + dependency size.
Computation Models
We use graph as the computation model. Each node represents a logical unit of work, while flows (graphs) orchestrate the interaction among nodes through directed edges. The direction indicates how data or control moves between nodes.
- Node: A minimal unit of computation (for example, an LLM call, tool use, or human feedback).
- Flow: A subgraph that coordinates nodes to accomplish a larger task.
- Direction: Edges are directed, indicating the flow of data or decisions (e.g., for agentic decisions).
Nodes in PocketFlow can also be: (1) Nested: One flow can be embedded in another, supporting hierarchical composition of logic. (2) Batched: Nodes can process multiple items in bulk. (3) Async: Tasks may run in parallel, pausing or waiting as needed.
Why not use agent as the computation model?
- Expressibility: Agents can be expressed as graphs, since typical agent behaviors (looping or branching) map directly to cyclical or conditional edges.
- Practicality: Even for agents, the core design boils down to (1) Context Management and (2) Action Space, both of which are better handled via multi-step nodes rather than a standalone agent abstraction.
Graph Representation: Global or Local?
| Global Graph Representation | Local Graph Representation |
|
|
| A separate Graph maintains a global adjacency map. | Each individual Node tracks its successors. |
Table 2: Comparison of Global and Local Graph Representation.
Another key design choice is how to represent the graph (nodes + edges). LangGraph adopts a global graph representation: once a graph is compiled, it becomes a finalized structure that cannot be easily modified. By contrast, PocketFlow chooses a local graph representation, a design shared by popular workflow systems like Airflow, Luigi, and Prefect. This approach ensures modularity: because each subgraph is self-contained, making it easier to understand and maintain in isolation. Moreover, incremental development is simpler, since new pipelines can be introduced or updated without affecting other flows.
Communication Models
Existing frameworks let compute units communicate majorly via message passing, though some also maintain a global context as a fallback. In contrast, PocketFlow uses solely a shared store as the communication model, where each node reads and writes to the shared store. This design choice of shared store is for separation of concerns: (1) Data Schema is designed and maintained in a central place. (2) Compute logic is then operated on the designed data structure.
While message passing can be simple for smaller systems, it becomes cumbersome to maintain with many interacting components. A shared store allows developers to modify data structures freely, without refactoring communication patterns among nodes.
Application or Vendor-Specific Models
PocketFlow does not include modules that target particular vendors or use cases. While this may seem to forgo certain benefits of information hiding, it keeps the framework minimal and avoids shifting dependencies. Modern LLM systems often require integrating various APIs (for LLM calls or tool usage), which are challenging to maintain in a single framework.
From our perspective, the job of handling vendor-specific details is best left to AI assistants that can retrieve up-to-date documentation and assemble relevant code on the fly. PocketFlow remains a lightweight core, while an AI assistant—like Cursor AI—provides tailored integrations for specific business or application needs.
Other Q&A
Why introduce a Flow abstraction if Nodes already manage their successors locally?
-
Flows as Nodes: Flows encapsulate complex operations as reusable nodes. For instance, consider a flow handling natural language database queries: internally, it comprises multiple nodes for text-to-SQL conversion, database connections, SQL execution, and debugging. Each operation is simply a node within a larger flow, enabling batch execution, parallelism, asynchronous operations, and chaining with other flows.
-
Avoiding Recursive Call Stacks: Relying solely on nodes managing successors can result in deep recursive call stacks, especially problematic in large flows involving loops or batch processing. Flows orchestrate node execution, ensuring scalable and stack-safe computations.
Is a Batch Node fundamental to PocketFlow?
No. Batch nodes aren't fundamental; you can implement batch behavior using a standard node with a self-loop and tracking state via the shared store. However, batching is a frequent and practical pattern, and providing dedicated batch nodes significantly improves developer experience.