π² Blocks and Configs
Loopstack uses a block-based architecture where every component (workflow, document, tool, and workspace) is defined as a reusable, configurable block.
Core Concept
Every block in Loopstack consists of two parts:
- TypeScript (NestJS) Service: Defines data structure and houses custom code.
- YAML Configuration: Defines the runtime behavior, UI representation, and execution flow
Note, using the separate yaml configs is optional. You can also define the behaviour using the config property in the BlockConfig decorator following the same block schema. However, we recommend using the yaml configuration for better modularity, reusability and readability.
Anatomy of a Block
Hereβs a minimal example showing the essential components of a workflow block:
// making the service injectable in NestJs
@Injectable()
// Custom configuration
@BlockConfig({
// inline config (optional)
config: {
title: 'My First Workflow',
},
// external configuration file (optional)
configFile: __dirname + '/my-workflow.yaml',
})
// Arguments
@WithArguments(
// zod schema defining input arguments for the workflow
)
// State
@WithState(
// zod schema defining a custom state of the workflow
)
export class MyWorkflow extends WorkflowBase {
// injecting a tool
@Tool() myTool: MyTool;
// injecting a document
@Document() myDocument: MyDocument;
}# my-workflow.yaml
transitions:
- id: process
from: start
to: end
call:
- id: do_something
tool: myTool
args:
input: "Hello World"
assign:
customField: ${ result.data }Block Types
Loopstack includes several block types, each serving a specific purpose:
Workspaces: Group related workflows and provide organizational structureWorkflows: Orchestrate processes using state machine transitionsDocuments: Define structured data with validation and UI configurationTools: Encapsulate reusable operations (API calls, transformations, etc.)
Each block type extends a base class and uses the @BlockConfig decorator with type-specific configuration options.