Unnamed Skill

Core ChainGraph domain concepts - flows, nodes, ports, edges, and execution. Use for ANY ChainGraph development to understand the fundamental abstractions. Explains what flows are, how nodes process data, port types (9 types), edge data transfer, and execution lifecycle. 19 FlowEventTypes, 21 ExecutionEventEnums. Triggers: chaingraph, flow, node, port, edge, execution, what is, how does, concept, architecture, event types.

$ Installieren

git clone https://github.com/chaingraphlabs/chaingraph /tmp/chaingraph && cp -r /tmp/chaingraph/.claude/skills/chaingraph-concepts ~/.claude/skills/chaingraph

// tip: Run this command in your terminal to install the skill


name: chaingraph-concepts description: Core ChainGraph domain concepts - flows, nodes, ports, edges, and execution. Use for ANY ChainGraph development to understand the fundamental abstractions. Explains what flows are, how nodes process data, port types (9 types), edge data transfer, and execution lifecycle. 19 FlowEventTypes, 21 ExecutionEventEnums. Triggers: chaingraph, flow, node, port, edge, execution, what is, how does, concept, architecture, event types.

ChainGraph Core Concepts

ChainGraph is a flow-based programming framework for building visual computational graphs. This skill covers the fundamental domain concepts that ALL agents need to understand.

The Four Core Abstractions

┌─────────────────────────────────────────────────────────────┐
│                         FLOW                                │
│  (Directed Acyclic Graph - the container)                   │
│                                                             │
│   ┌─────────┐         ┌─────────┐         ┌─────────┐      │
│   │  NODE   │         │  NODE   │         │  NODE   │      │
│   │ ┌─────┐ │  EDGE   │ ┌─────┐ │  EDGE   │ ┌─────┐ │      │
│   │ │PORT │─┼────────▶│ │PORT │─┼────────▶│ │PORT │ │      │
│   │ └─────┘ │         │ └─────┘ │         │ └─────┘ │      │
│   └─────────┘         └─────────┘         └─────────┘      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1. Flow

A Flow is a directed acyclic graph (DAG) containing interconnected nodes and edges that define a computational workflow.

Key Properties

PropertyTypeDescription
idstringUnique identifier
metadataFlowMetadataName, description, timestamps, version, owner
nodesMap<string, INode>All nodes in the flow
edgesMap<string, IEdge>All edges connecting nodes

Key Methods

// Add a node to the flow
flow.addNode(node: INode): Promise<INode>

// Connect two ports via edge
flow.connectPorts(sourceNodeId, sourcePortId, targetNodeId, targetPortId): Edge

// Subscribe to flow events
flow.onEvent(handler: (event: FlowEvent) => void): () => void

// Validate entire flow
flow.validate(): Promise<FlowValidationResult>

Key Files

FilePurpose
packages/chaingraph-types/src/flow/flow.ts:42Flow class implementation
packages/chaingraph-types/src/flow/interface.ts:19-193IFlow interface
packages/chaingraph-types/src/flow/types.ts:12-54FlowMetadata type

2. Node

A Node is a discrete computational unit that performs a specific operation on input data and produces output. Nodes are the building blocks of flows.

Node Lifecycle

Idle → Ready → Executing → Completed
                    ↓
                  Error

NodeStatus Enum

enum NodeStatus {
  Idle = 'idle',           // Initial state
  Initialized = 'initialized',
  Ready = 'ready',         // Ready to execute
  Pending = 'pending',     // Waiting for dependencies
  Executing = 'executing', // Currently running
  Completed = 'completed', // Successfully finished
  Skipped = 'skipped',     // Skipped (condition not met)
  Error = 'error',         // Failed with error
  Disposed = 'disposed',   // Cleaned up
}

Key Properties

PropertyTypeDescription
idstringUnique identifier
metadataNodeMetadataType, title, category, description
statusNodeStatusCurrent execution status
portsMap<string, IPort>Input and output ports

Key Methods

// Execute the node
node.execute(context: ExecutionContext): Promise<NodeExecutionResult>

// Get a port by ID
node.getPort(portId: string): IPort | undefined

// Validate configuration
node.validate(): Promise<NodeValidationResult>

// Reset to initial state
node.reset(): Promise<void>

NodeMetadata

interface NodeMetadata {
  type: string           // Node class name (required)
  title?: string         // Display name
  category?: NodeCategory // e.g., 'math', 'flow-control', 'ai'
  description?: string
  version?: number
  icon?: string
  tags?: string[]
  parentNodeId?: string  // If nested in group
  ui?: NodeUIMetadata    // Position, dimensions, etc.
}

Key Files

FilePurpose
packages/chaingraph-types/src/node/base-node.tsBaseNode abstract class
packages/chaingraph-types/src/node/interface.ts:11-14INode interface
packages/chaingraph-types/src/node/node-enums.ts:12-22NodeStatus enum
packages/chaingraph-types/src/node/types.ts:17-31NodeMetadata type

3. Port

A Port is a typed input or output connector on a Node through which data flows. Ports are strongly typed and support primitives, arrays, objects, and streams.

Port Direction

type PortDirection = 'input' | 'output' | 'passthrough'
  • Input: Receives data from connected output ports
  • Output: Sends data to connected input ports
  • Passthrough: Both input and output

Port Types (9 Total)

TypeDescriptionExample Use
stringText valuesNames, prompts, API keys
numberNumeric valuesCounts, scores, coordinates
booleanTrue/falseFlags, conditions
arrayList of typed itemsData batches, collections
objectStructured data with schemaComplex configs, records
streamAsync multi-channel dataReal-time data, LLM tokens
enumFixed set of optionsDropdown selections
secretEncrypted sensitive dataAPI keys, passwords
anyUntyped (avoid if possible)Dynamic data

Port Configuration

Each port type has a specific config interface:

interface StringPortConfig {
  type: 'string'
  defaultValue?: string
  minLength?: number
  maxLength?: number
  pattern?: RegExp  // Validation regex
}

interface NumberPortConfig {
  type: 'number'
  defaultValue?: number
  min?: number
  max?: number
  step?: number
  integer?: boolean
}

interface ArrayPortConfig<Item> {
  type: 'array'
  itemConfig: IPortConfig  // Type of each item
  minLength?: number
  maxLength?: number
  isMutable?: boolean      // Can items be added/removed?
}

interface ObjectPortConfig<Schema> {
  type: 'object'
  schema: IObjectSchema    // Properties definition
  isSchemaMutable?: boolean
}

Key Methods

// Get/set port value
port.getValue(): T | undefined
port.setValue(value: T): void

// Validation
port.validate(): boolean

// Serialization
port.serialize(): JSONValue
port.deserialize(data: JSONValue): IPort

// Connection management
port.addConnection(nodeId: string, portId: string): void
port.removeConnection(nodeId: string, portId: string): void

Key Files

FilePurpose
packages/chaingraph-types/src/port/base/IPort.ts:30-187IPort interface
packages/chaingraph-types/src/port/base/types.ts:84-213Port config types
packages/chaingraph-types/src/port/instances/Port implementations
packages/chaingraph-types/src/port/plugins/Validation plugins

4. Edge

An Edge is a directed connection from an output port of one node to an input port of another node, enabling data flow.

Edge Status

enum EdgeStatus {
  Active = 'active',     // Connection working
  Inactive = 'inactive', // Disabled
  Error = 'error',       // Transfer failed
}

Key Properties

PropertyTypeDescription
idstringUnique identifier
sourceNodeINodeNode with output port
sourcePortIPortOutput port
targetNodeINodeNode with input port
targetPortIPortInput port
metadataEdgeMetadataLabel, anchors, version

EdgeMetadata

interface EdgeMetadata {
  label?: string              // Display label
  anchors?: EdgeAnchor[]      // Control points for custom paths
  version?: number            // For optimistic updates
}

interface EdgeAnchor {
  id: string
  x: number                   // Coordinate
  y: number
  index: number               // Order in path
}

Key Files

FilePurpose
packages/chaingraph-types/src/edge/edge.ts:18Edge implementation
packages/chaingraph-types/src/edge/interface.ts:16-65IEdge interface
packages/chaingraph-types/src/edge/types.ts:12-54EdgeStatus, EdgeMetadata

5. Execution

ExecutionContext

The runtime context provided to every executing node:

class ExecutionContext {
  readonly executionId: string      // Unique run ID
  readonly rootExecutionId?: string // Root workflow ID
  readonly parentExecutionId?: string // Parent ID (for children)
  readonly flowId?: string
  readonly userId?: string
  readonly startTime: Date
  readonly abortController: AbortController
  readonly integrations: IntegrationContext  // AI, wallet, etc.
  readonly executionDepth: number  // Prevents infinite recursion (max 100)

  // Event emission (for event-driven execution)
  emitEvent(eventType: string, data: any, nodeId: string): void

  // Port resolution (for stream ports)
  resolvePort(nodeId: string, portId: string): void
  isPortResolved(nodeId: string, portId: string): boolean

  // Get integration data
  getIntegration<T>(type: string): T | undefined
}

ExecutionEngine

Orchestrates flow execution:

class ExecutionEngine {
  constructor(flow: Flow, context: ExecutionContext, options?: ExecutionOptions)

  async execute(): Promise<void>

  // Control flow
  pause(): void
  resume(): void
  stop(reason?: string): void

  // Event handling
  onEvent(eventType: ExecutionEventEnum, callback): void
  onError(callback): void
}

ExecutionOptions

interface ExecutionOptions {
  execution?: {
    maxConcurrency?: number    // Default: 50
    nodeTimeoutMs?: number     // Default: 3600000 (1 hour)
    flowTimeoutMs?: number     // Default: 10800000 (3 hours)
  }
  debug?: boolean              // Enable debugger
  breakpoints?: string[]       // Node IDs to break on
}

Key Files

FilePurpose
packages/chaingraph-types/src/execution/execution-context.ts:37-320ExecutionContext
packages/chaingraph-types/src/flow/execution-engine.ts:49ExecutionEngine

6. Events

Flow Events (FlowEventType)

Events emitted during flow editing (19 total):

EventDescription
FlowInitStartSubscription started
FlowInitEndInitial state sent
MetadataUpdatedFlow metadata changed
NodesAddedBatch nodes added
NodeAddedSingle node added
NodeRemovedNode deleted
NodesUpdatedBatch nodes updated
NodeUpdatedNode data changed
NodeParentUpdatedNode parent changed
PortCreatedPort added
PortUpdatedPort value/config changed
PortRemovedPort deleted
EdgesAddedBatch edges added
EdgeAddedConnection created
EdgeRemovedConnection deleted
EdgeMetadataUpdatedEdge metadata changed
NodeUIPositionChangedNode moved
NodeUIDimensionsChangedNode resized
NodeUIChangedGeneral UI changed

Execution Events (ExecutionEventEnum)

Events emitted during execution (21 total):

EventDescription
EXECUTION_CREATEDExecution initialized (index -1)
FLOW_SUBSCRIBEDFlow subscription confirmed
FLOW_STARTEDExecution began
FLOW_COMPLETEDExecution finished
FLOW_FAILEDExecution errored
FLOW_CANCELLEDExecution cancelled
FLOW_PAUSEDExecution paused
FLOW_RESUMEDExecution resumed
NODE_STARTEDNode began executing
NODE_COMPLETEDNode finished
NODE_FAILEDNode errored
NODE_SKIPPEDNode skipped
NODE_STATUS_CHANGEDNode status changed
NODE_DEBUG_LOG_STRINGDebug log from node
EDGE_TRANSFER_STARTEDData transfer started
EDGE_TRANSFER_COMPLETEDData transferred
EDGE_TRANSFER_FAILEDData transfer failed
CHILD_EXECUTION_SPAWNEDChild workflow spawned
CHILD_EXECUTION_COMPLETEDChild workflow completed
CHILD_EXECUTION_FAILEDChild workflow failed
DEBUG_BREAKPOINT_HITDebugger breakpoint hit

Key Files

FilePurpose
packages/chaingraph-types/src/flow/events.ts:17-47FlowEventType enum
packages/chaingraph-types/src/flow/execution-events.ts:15-48ExecutionEventEnum

Quick Reference

Creating a Node (with decorators)

import { Node, Input, Output, PortString, PortNumber } from '@badaitech/chaingraph-types'

@Node({
  title: 'Add Numbers',
  category: 'math',
  description: 'Adds two numbers',
})
class AddNode extends BaseNode {
  @Input()
  @PortNumber({ defaultValue: 0 })
  a: number = 0

  @Input()
  @PortNumber({ defaultValue: 0 })
  b: number = 0

  @Output()
  @PortNumber()
  result: number = 0

  async execute(context: ExecutionContext): Promise<NodeExecutionResult> {
    this.result = this.a + this.b
    return {}
  }
}

Data Flow Summary

1. Flow loads nodes and edges
2. ExecutionEngine resolves dependencies (topological sort)
3. Nodes execute in parallel where possible
4. Output port values transfer to connected input ports
5. Events stream in real-time
6. Flow completes or fails

Related Skills

  • types-architecture - Deep dive into the types package
  • port-system - Detailed port types and decorators
  • effector-patterns - Frontend state management
  • dbos-patterns - Backend durable execution