Core Paradigms

The Pocket Flow Framework is built around several key paradigms that enable flexible and powerful workflow orchestration.

1. Node-Based Processing

The fundamental unit of computation is the BaseNode, which follows a three-phase execution pattern:

abstract class BaseNode {
    async prep(sharedState: any): Promise<any>;     // Prepare data
    async execCore(prepResult: any): Promise<any>;  // Execute core logic
    async post(prepResult: any, execResult: any, sharedState: any): Promise<string>;  // Post-process
}

This pattern enables: - Clear separation of concerns - Predictable data flow - Flexible state management

2. Action-Based Transitions

Nodes connect through action-based transitions, where each node's post() method returns an action string that determines the next node:

// Define transitions based on actions
nodeA.addSuccessor(nodeB, "success");
nodeA.addSuccessor(errorNode, "error");

This enables: - Dynamic workflow paths - Conditional branching - Error handling patterns

3. Shared State Management

The framework uses a shared state object that flows through the entire execution:

// Each node can read/write to shared state
async post(prepResult: any, execResult: any, sharedState: any): Promise<string> {
    sharedState.results.push(execResult);
    return "default";
}

4. Flow Composition

Flows can be nested and composed, treating complex workflows as single nodes:

// Create a sub-flow
const subFlow = new Flow(startNode);

// Use it in a larger flow
mainFlow.addSuccessor(subFlow);

5. Parallel Processing

The BatchFlow enables parallel processing of multiple items:

class BatchFlow extends Flow {
    async prep(sharedState: any): Promise<any[]> {
        return sharedState.items; // Return array of items to process
    }

    async post(prepResults: any[], results: any[], sharedState: any): Promise<string> {
        sharedState.results = results;
        return DEFAULT_ACTION;
    }
}

6. Error Handling

The framework provides built-in retry mechanisms through RetryNode:

class ApiNode extends RetryNode {
    constructor() {
        super(3, 1000); // 3 retries, 1 second interval
    }
}

7. Parameter Management

Each node can maintain its own parameters separate from shared state:

class CustomNode extends BaseNode {
    constructor() {
        super();
        this.setParams({ threshold: 0.5 });
    }
}

8. Clone and Race Condition Prevention

The framework handles parallel execution safely through node cloning:

public clone(): BaseNode {
    const newNode = this._clone();
    newNode.flow_params = cloneDeep(this.flow_params);
    newNode.successors = new Map(this.successors);
    return newNode;
}

Summary

These paradigms work together to provide: - Modularity: Each node is independent and reusable - Flexibility: Workflows can be dynamically constructed - Scalability: Parallel processing and composition - Reliability: Built-in error handling and state management - Safety: Race condition prevention in parallel execution

See the child pages for detailed implementations of each paradigm.