Node Architecture

Deep dive into BizFirstAI node system - the building blocks of workflow automation with extensible hooks and lifecycle management.

Node Anatomy

A node is the fundamental execution unit in BizFirstAI workflows. It combines structural, configuration, runtime, and event-driven aspects.

graph TB subgraph Structure["Node Structure"] ID["Node ID
Unique Identifier"] Type["Node Type
ProcessElementTypeCode"] Name["Name
Display Label"] end subgraph Connectors["Connectors & Connections"] Input["Input Port
(1 required)"] Output["Output Ports
(success, error, etc.)"] Edges["Connections
(to downstream nodes)"] end subgraph Configuration["Configuration
(Design-Time)"] Config["Config JSON
Node-specific settings"] Form["Config Form
UI for configuration"] Schema["JSON Schema
Validation rules"] end subgraph Runtime["Runtime
(Execution-Time)"] Executor["Executor
ProcessElementExecutor"] Services["Services
DI Injected"] Forms["Runtime Forms
User input during execution"] end subgraph EventsLayer["Events & Hooks"] Hooks["Hooks
Process & Executor lifecycle"] ExecutionEvents["Events
Pre/Post execution"] SubProcs["Sub-Processes
Triggered by hooks"] end Structure --> Connectors Connectors --> Configuration Configuration --> Runtime Runtime --> EventsLayer style Structure fill:#1f6feb,stroke:#58a6ff,color:#c9d1d9 style Connectors fill:#238636,stroke:#3fb950,color:#c9d1d9 style Configuration fill:#9e6a03,stroke:#fb8500,color:#c9d1d9 style Runtime fill:#ae3f6e,stroke:#f97583,color:#c9d1d9 style EventsLayer fill:#1158c7,stroke:#58a6ff,color:#c9d1d9

Node Structure & Connections

Structural Properties

Node Identity

id: UUID - Unique within process
processElementTypeCode: string - Type identifier (e.g., "ai-agent")
name: string - Display name
description: string - Documentation

Ports (I/O)

inputPort: Port - Single input
outputPorts: Port[] - Multiple outputs (main, error, custom)

Connections

Connection Definition

{
  "sourceElementId": "uuid-1",
  "sourcePortKey": "main",
  "targetElementId": "uuid-2"
}

Port Key Matching: ExecutionRouter matches on sourcePortKey to find next nodes.
Multiple Outputs: Node can have "main", "error", "success", custom ports

Configuration System

graph LR Design["Design Mode
User configures node"] Form["Config Form
UI Controls
20+ types"] Validate["Validation
JSON Schema
Business Rules"] Store["Store in DB
As JSON
In ProcessElement"] Runtime["Runtime
Load config
Parse to typed object"] Executor["Executor
Access via
mySettings property"] Design --> Form Form --> Validate Validate --> Store Store --> Runtime Runtime --> Executor style Design fill:#1f6feb,stroke:#58a6ff,color:#c9d1d9 style Form fill:#238636,stroke:#3fb950,color:#c9d1d9 style Validate fill:#238636,stroke:#3fb950,color:#c9d1d9 style Store fill:#1158c7,stroke:#58a6ff,color:#c9d1d9 style Runtime fill:#ae3f6e,stroke:#f97583,color:#c9d1d9 style Executor fill:#ae3f6e,stroke:#f97583,color:#c9d1d9

Design-Time Configuration

Atlas Forms Schema:

{
  "controls": [
    {
      "id": "agentId",
      "type": "select",
      "label": "Agent",
      "required": true
    }
  ]
}

Runtime Configuration Access

C# Executor Access:

// Typed property
private AiAgentConfig?
  mySettings =>
  (AiAgentConfig?)this.settings;

// Usage
var agentId = mySettings?.AgentId;
var temperature = mySettings?.Temperature;

Runtime Execution

Executor

ProcessElementExecutor - Base class for all node executors

  • ✓ 26+ built-in executors
  • ✓ ExecuteInternalAsync() override
  • ✓ Access to InputData
  • ✓ Return NodeExecutionResult
  • ✓ Fire execution events

Services

Dependency Injection - Services available to executor

  • ✓ IAgentInvoker (AI agent execution)
  • ✓ IFunctionInvoker (Function execution)
  • ✓ ILogger (Logging)
  • ✓ Custom services (registered in DI)
  • ✓ Context builders

Runtime Forms

User Input During Execution - Chat, forms, approvals

  • ✓ ChatNode - Interactive conversations
  • ✓ FormNode - Data collection
  • ✓ Approval workflows
  • ✓ Pause execution for input
  • ✓ Async/await patterns

Webhooks

External Integration - Trigger from external systems

  • ✓ WebhookTrigger node
  • ✓ Verify signatures
  • ✓ Parse request bodies
  • ✓ Extract data
  • ✓ HTTP response handling

Hooks System - Advanced Lifecycle Management

Hooks provide a powerful extension mechanism for nodes. They allow you to intercept and react to node lifecycle events, trigger sub-processes, integrate with external systems, and implement domain-specific business logic.

graph TB Node["Node Executing"] PreHook["Pre-Execution Hooks
OnBeforeExecute"] Execute["Execute Executor
ExecuteInternalAsync"] PostHook["Post-Execution Hooks
OnAfterExecute"] Complete["Result Returned"] PreHook -->|Can modify InputData
Can trigger sub-process| Execute Execute -->|Success or Error| PostHook PostHook -->|Can trigger events
Can call webhooks
Can spawn sub-processes| Complete Hook1["Blockchain Hook
Record on chain"] Hook2["Chat Group Hook
Notify team"] Hook3["Data Mgmt Hook
Archive results"] Hook4["Article Hook
Generate docs"] PostHook --> Hook1 PostHook --> Hook2 PostHook --> Hook3 PostHook --> Hook4 style Node fill:#9e6a03,stroke:#fb8500,color:#c9d1d9 style PreHook fill:#1158c7,stroke:#58a6ff,color:#c9d1d9 style Execute fill:#9e6a03,stroke:#fb8500,color:#c9d1d9 style PostHook fill:#1158c7,stroke:#58a6ff,color:#c9d1d9 style Complete fill:#238636,stroke:#3fb950,color:#c9d1d9 style Hook1 fill:#ae3f6e,stroke:#f97583,color:#c9d1d9 style Hook2 fill:#ae3f6e,stroke:#f97583,color:#c9d1d9 style Hook3 fill:#ae3f6e,stroke:#f97583,color:#c9d1d9 style Hook4 fill:#ae3f6e,stroke:#f97583,color:#c9d1d9

Hook Types & Capabilities

Process Element Hooks (All Nodes)

Pre-Execution Hook

OnBeforeExecute()

Called before executor runs
✓ Validate InputData
✓ Transform parameters
✓ Check conditions
✓ Trigger pre-flight checks

Post-Execution Hook

OnAfterExecute()

Called after executor completes
✓ Process results
✓ Notify systems
✓ Trigger workflows
✓ Record events

Executor Hooks (Node-Specific)

Executor Lifecycle

IExecutorHook

Full access to executor context
✓ Configuration details
✓ Execution state
✓ Input/output data
✓ Services & dependencies

Nested Hooks

Hook.OnHook()

Hooks can have their own hooks
✓ Composition pattern
✓ Chain of responsibility
✓ Multi-level events
✓ Event propagation

Domain-Specific Hooks

Blockchain Hook

Record execution on blockchain
✓ Immutable audit trail
✓ Compliance proof
✓ Transaction signing

Chat Group Hook

Notify teams of execution
✓ Slack notifications
✓ Teams messages
✓ Discord alerts

Data Management Hook

Archive & manage data
✓ Data retention policies
✓ GDPR compliance
✓ Storage optimization

Article Hook

Generate documentation
✓ Auto-generate articles
✓ Update knowledge base
✓ Create runbooks

Business Activity Hook

Track business metrics
✓ Process mining
✓ Analytics events
✓ BI integration

Custom Hooks

Implement domain logic
✓ Plugin pattern
✓ DI integration
✓ Async support

AI Node Hooks (Octopus Integration)

Conversation Hooks

  • OnMessageReceived - Message arrived from user/agent
  • OnMessageSent - Message sent to user/agent
  • OnConversationStarted - New conversation initiated
  • OnConversationEnded - Conversation completed
  • OnContextUpdated - Execution context changed

AI Lifecycle Hooks

  • OnAgentInvoked - Agent execution started
  • OnFunctionCalled - Function execution requested
  • OnTokensUsed - LLM tokens consumed
  • OnAgentCompleted - Agent finished
  • OnAgentFailed - Agent error occurred

Triggering Sub-Processes from Hooks

Hooks can trigger independent sub-processes, enabling complex workflows like notifications, approvals, and data synchronization.

graph TD Main["Main Process
Executing Node"] PostHook["Post-Execution Hook
OnAfterExecute"] Notify["Trigger Sub-Process
Send Notification"] Archive["Trigger Sub-Process
Archive Results"] Analytics["Trigger Sub-Process
Record Analytics"] Wait["Main Process
Waits (or continues)"] Main --> PostHook PostHook -->|Async| Notify PostHook -->|Async| Archive PostHook -->|Async| Analytics Notify --> Wait Archive --> Wait Analytics --> Wait style Main fill:#9e6a03,stroke:#fb8500,color:#c9d1d9 style PostHook fill:#1158c7,stroke:#58a6ff,color:#c9d1d9 style Notify fill:#238636,stroke:#3fb950,color:#c9d1d9 style Archive fill:#238636,stroke:#3fb950,color:#c9d1d9 style Analytics fill:#238636,stroke:#3fb950,color:#c9d1d9 style Wait fill:#9e6a03,stroke:#fb8500,color:#c9d1d9
Fire & Forget

Trigger sub-process asynchronously without waiting

await _orchestrator
  .TriggerSubProcessAsync(
    notificationProcessId,
    context,
    fireAndForget: true
  );
Wait for Completion

Trigger and wait for sub-process completion

var result = await _orchestrator
  .TriggerSubProcessAsync(
    approvalProcessId,
    context
  );
if(result.Success) { ... }

Hook Context & Access

Available Context in Hooks

Execution Context

  • ✓ ExecutionID (unique execution)
  • ✓ ProcessID (workflow definition)
  • ✓ TenantID (multi-tenant isolation)
  • ✓ UserID (who triggered)
  • ✓ Variables (scoped data)

Node Context

  • ✓ NodeID (current node)
  • ✓ Configuration (node settings)
  • ✓ InputData (from upstream)
  • ✓ OutputData (execution result)
  • ✓ Executor (node handler)

Services

  • ✓ ILogger (logging)
  • ✓ IOrchestrationProcessor (sub-processes)
  • ✓ Services (DI container)
  • ✓ Repositories (data access)
  • ✓ Custom services

Audit & Tracking

  • ✓ ExecutionHistory (all events)
  • ✓ StartedAt/CompletedAt (timing)
  • ✓ Duration (performance)
  • ✓ Error details (if failed)
  • ✓ Execution trace