Skip to Content
DocumentationLearnBasic Concepts

Basic Concepts

🎯

Goal: To understand the basic concepts of Cascaide and how they map to DGs

Cascaide treats your application’s dynamic logic and data flow as a single graph. You can think of every part of it, UI components, functions, API calls, database operations etc. as nodes in a graph. The logic defining which nodes should be executed when forms the edges and all the information about the application form the state.

Prerequisites

We assume knowledge of:

  • TypeScript
  • React

In addition, it is great if you understand Redux because we use it under the hood. However, it is not strictly required as you will not be directly dealing with it.


Concepts

In this section, we will dive into the basic concepts. Later, we will go deeper in the advanced concepts section.

State

State is how information in the app is stored. It has 4 parts:

PartDescription
contextData you store, typically as a sequence (array) of updates (crucial for history and immutability), to be accessible to different nodes. Nodes may read and write to context.
activeNodesTracks which nodes are currently executing and the data associated with them.
historyMaintains a record of which nodes were active in the past.
errorsKeeps track of errors thrown by failed nodes.

State is stored in two places:

  • The authoritative global state in a shared database
  • In a local redux state, which only deals with the data the local environment needs

Nodes

Nodes are units of work. They accept an input upon activation and/or read additional information from the context, execute their tasks, write back to the context and initiate the next nodes.

Nodes are just functions. They come in two main flavours: UI Nodes (which run on the client and could pause the workflow for human interaction) and Logic Nodes (which run on the server via the Workflow Engine).

// client workflow graph snippet (more on this later) const clientWorkflowGraph: ClientWorkflowGraph = { chat: { name: 'chat', isUINode: true, env: 'client' }, searchAgentNode: { name: 'searchAgentNode', isUINode: false, env: 'server' }, searchToolNode: { name: 'searchToolNode', isUINode: false, env: 'server' }, }

Node Lifecycle (Only for Logic Nodes)

Each node follows a fixed lifecycle:

StepDescription
prepA node accepts an input and/or selects data from the context and prepares it for execution.
execThe output from the prep step is used to execute core logic.
postResults are written to the context and the next node(s) are spawned.

In addition, they may be streaming nodes or not.

// server workflow graph snippet (more on this later) const serverWorkflowGraph: ServerWorkflowGraph = { searchAgentNode: { name: 'searchAgentNode', prep: searchAgentNodePrep, exec: searchAgentNodeExec, post: searchAgentNodePost, isStreaming: true, isUINode: false, env: 'server' }, searchToolNode: { name: 'searchToolNode', prep: searchToolNodePrep, exec: searchToolNodeExec, post: searchToolNodePost, isUINode: false, isStreaming: false, env: 'server' }, };

Spawning: Realising Edges

Spawning is how edges are realised. When a node decides which node(s) are to be activated, they spawn them by returning the node name, the required data for the new node and the updates (if it is a logic node), or by using the useWorkflow hook if it is a UI node (more on this later).

return { updates: { [cascadeId]: { history: toolResultsOnly, status: 'complete', }, }, spawns: { 'searchAgentNode': { history: toolResultsOnly, }, }, };

Workflow

Workflow binds all three elements — state, nodes and edges — together and realises the application. It has three parts:

  • 🔧 Workflow Engine — The core orchestrator that does all the heavy lifting (you will usually never touch this).
  • 🖥️ Client Workflow Config — A declarative object that provides node metadata and UI component registry.
  • ⚙️ Server Workflow Config — A declarative object that provides node implementations to the engine.

The Client Workflow Config tells the UI what components to render for a node, and the Server Workflow Config tells the Engine how to execute the node’s logic. They must agree on the nodeName. You build applications by creating these workflow configurations.

💡

Unlike other AI orchestration frameworks that use DGs, graph topology is not predefined explicitly in Cascaide. It emerges at runtime. This will come in handy later.

Client Workflow Config

graphs/client/config.ts
import Chat from "@/components/cascaide-ui/chat/chat" import { ClientWorkflowConfig } from '@cascaide-ts/react'; import { ClientWorkflowGraph } from "@cascaide-ts/core"; const clientWorkflowGraph: ClientWorkflowGraph = { chat: { name: 'chat', isUINode: true, env: 'client' }, searchAgentNode: { name: 'searchAgentNode', isUINode: false, env: 'server' }, searchToolNode: { name: 'searchToolNode', isUINode: false, env: 'server' }, } export const clientWorkflowConfig: ClientWorkflowConfig = { clientWorkflowGraph: clientWorkflowGraph, uiComponentRegistry: { chat: Chat, }, };

Server Workflow Config

graphs/server/config.ts
import { WorkflowHandlerConfig } from '@cascaide-ts/server-next' import { PostgresPersistor } from '@cascaide-ts/postgres-js'; import { sql } from '@/lib/connection'; import { searchAgentNodeExec, searchAgentNodePrep, searchAgentNodePost, searchToolNodePrep, searchToolNodeExec, searchToolNodePost } from '@/bubbles/search-agent/searchAgentNodes'; import { ServerWorkflowGraph } from '@cascaide-ts/core' const workflowPersistor = new PostgresPersistor(sql); const MAX_EXECUTION_TIME = 100000; const SAFE_BUFFER = 6000; const serverWorkflowGraph: ServerWorkflowGraph = { searchAgentNode: { name: 'searchAgentNode', prep: searchAgentNodePrep, exec: searchAgentNodeExec, post: searchAgentNodePost, isStreaming: true, isUINode: false, env: 'server' }, searchToolNode: { name: 'searchToolNode', prep: searchToolNodePrep, exec: searchToolNodeExec, post: searchToolNodePost, isUINode: false, isStreaming: false, env: 'server' }, }; export const serverWorkflowConfig: WorkflowHandlerConfig = { workflowGraph: serverWorkflowGraph, persistor: workflowPersistor, maxExecutionTime: MAX_EXECUTION_TIME, safeBuffer: SAFE_BUFFER }

Cascade

A cascade is a set of node executions that follow one after the other. For example, in a ReAct agent setup, llm node → tool node → llm node (or in other words, one trace) would be a cascade. When a ReAct agent gives a final reply after N tool invocations, a cascade is considered to be completed. For the next user query, you would reactivate this cascade to continue the conversation. Each cascade is assigned a unique casacdeId. Cascaide does not construct this, you are expected to create and pass it in as a uuid.

The reason cascaide doesn’t construct it is because:

  • There are ephemeral nodes that sit outside any cascades. For example, a Chat node only reads and writes cascades.
  • You can carry information within the cascadeIds. Check out conventions section for more.

💡

Next, we will learn about the client side infrastructure we need to use Cascaide — WorkflowProvider and WorkflowRenderer.

Last updated on