Files
j-sanaa 02813aa703 Feat/agentflow Add support for create credential (#6048)
* Initial flow

* Fix styling to look the same as v2

* Add new atoms - SwitxhInput, Dropdown and ToolTipWithParser similar to v2

* Add test cases for all changes

* Refactor input default value handling and consolidate utility functions

* Allow imports from utils for atoms

* Fix gemini comments

* Fixed buold issues

* FIx styling and create credentiall behavior

* Add support for edit credentials

* Fix bug to display tool and vector embeddign parameters

* Add CredentialTypeSelector for HTTP node

* Fix to add falback icon in case of error

* Move inputDefaults under core/primitives

* Added fix to check if all mandatory fields have value before submittign a credential

* Fix new credential not being selected on creating

* Fixes made to address comments

* Gemini comment fix

* Fix test error by adding theme

* Refactor getDefaultValueForType to remove null/undefined handling

* Fixed getDefaultValueForType to be generic

* Fixed getDefaultValueForType to take single destructured object parameter
2026-03-25 15:00:22 -07:00

14 KiB

@flowiseai/agentflow - Architecture

This document describes the internal architecture of the @flowiseai/agentflow package.

Overview

The package follows a Domain-Driven Modular Architecture with clear separation of concerns. The goal is to separate low-level UI primitives from high-level business logic to ensure high reusability and easy testing.

src/
├── index.ts                    # Public Package API ("Public Face")
├── Agentflow.tsx               # Main component
├── AgentflowProvider.tsx       # Root provider (composition)
├── useAgentflow.ts             # Primary public hook
│
├── atoms/                      # ⚛️ UI Primitives ("What it looks like" (Dumb))
├── features/                   # 🧩 Domain Features ("What it does" (Smart))
├── core/                       # 🧠 Business Logic ("Business Rules" (Types/Logic))
└── infrastructure/             # 🌐 External Services ("Outside World" (API/Storage))

Directory Structure

atoms/ - UI Primitives

"What it looks like." Tiny, irreducible UI components with no business logic. These are the building blocks used by features.

atoms/
├── MainCard.tsx            # Styled card wrapper
├── NodeInputHandler.tsx    # Form input for node properties
├── ...                     # Other UI primitives
└── index.ts                # Central export

Rules:

  • Must be "dumb" and stateless
  • No business logic
  • No API calls
  • Stateless or minimal local state
  • Imported by features, never the reverse
  • Forbidden: Importing from features/ or infrastructure/ (except types from core/types for prop definitions, design tokens from core/theme, and primitives from core/primitives)

Goal: 100% visual consistency.


features/ - Domain Features

"What it does." Complex, self-contained domain modules (silos) that house the application's core functionality. Each feature owns its components, hooks, and utilities.

features/
├── canvas/                 # Core ReactFlow canvas
│   ├── containers/         # Smart components with state/logic
│   │   ├── AgentFlowNode.tsx
│   │   ├── AgentFlowEdge.tsx
│   │   ├── ...             # Other node containers
│   │   └── index.ts
│   ├── components/         # Presentational components
│   │   ├── ConnectionLine.tsx
│   │   ├── NodeOutputHandles.tsx
│   │   ├── ...             # Other presentational components
│   │   └── index.ts
│   ├── hooks/              # Canvas-related hooks
│   │   ├── useFlowHandlers.ts
│   │   ├── useDragAndDrop.ts
│   │   ├── ...             # Other canvas hooks
│   │   └── index.ts
│   ├── styled.ts           # Styled components
│   └── index.ts            # Public API
│
├── node-palette/           # Add nodes drawer
│   ├── AddNodesDrawer.tsx
│   ├── search.ts           # Feature-specific utility (private)
│   ├── ...
│   └── index.ts
│
├── generator/              # AI flow generation
│   ├── GenerateFlowDialog.tsx
│   ├── ...
│   └── index.ts
│
└── node-editor/            # Node property editing
    ├── EditNodeDialog.tsx
    └── index.ts

Rules:

  • Each feature has an index.ts gatekeeper
  • Features never import from other features directly - If canvas needs logic from generator, move that logic to core/
  • Feature-specific utils stay in the feature folder
  • Styles are co-located with their feature
  • Use containers/ for smart components (with state, hooks, side effects)
  • Use components/ for presentational components (props in, JSX out)

Goal: High cohesion. Should be able to delete a feature folder without breaking others.


core/ - Business Logic

"The Brain." Framework-agnostic logic, types, and utilities. No React, no UI - pure TypeScript. Contains validation schemas, node registries, domain constants, and shared types.

core/
├── types/                  # Global interfaces (Node, Edge, Flow)
│   └── index.ts
├── primitives/             # Domain-free utilities (safe for atoms)
│   ├── inputDefaults.ts    # getDefaultValueForType
│   └── index.ts
├── node-config/            # Node configuration (icons, colors, default types)
│   ├── nodeIcons.ts        # AGENTFLOW_ICONS, DEFAULT_AGENTFLOW_NODES
│   └── ...
├── node-catalog/           # Node catalog and filtering logic
│   ├── nodeFilters.ts      # filterNodesByComponents, isAgentflowNode
│   └── ...
├── theme/                  # Design tokens and MUI theming
│   ├── tokens.ts           # Color palettes, spacing, shadows
│   ├── createAgentflowTheme.ts
│   └── ...
├── validation/             # Flow validation logic
│   ├── flowValidation.ts   # validateFlow, validateNode
│   ├── connectionValidation.ts  # isValidConnectionAgentflowV2
│   └── ...
├── utils/                  # Domain-aware utilities (NOT importable by atoms)
│   ├── nodeFactory.ts      # initNode, getUniqueNodeId
│   └── ...
└── index.ts                # Barrel export (use sparingly)

Rules:

  • No React components allowed - Pure TypeScript only
  • No browser-specific APIs if possible
  • No side effects
  • Pure functions where possible
  • Can be tested in isolation

core/primitives/ vs core/utils/

core/ contains two utility directories with different import permissions:

  • primitives/ — Domain-free, general-purpose functions with no knowledge of nodes, flows, or any business concept. These are pure data transformations (e.g., computing a default value from a type string). Safe to import from atoms/.
  • utils/ — Domain-aware utilities that understand node structures, flow data, or validation logic (e.g., initNode, buildDynamicOutputAnchors). Only importable by features/ and infrastructure/.

When adding a new utility, ask: "Does this function need to know what a Node or Flow is?" If no → primitives/. If yes → utils/.

Goal: To be the framework-agnostic source of truth.


infrastructure/ - External Services

"The Outside World." Handles communication with external systems: data persistence, network requests, and global state management.

infrastructure/
├── api/                    # API client layer (network requests)
│   ├── client.ts           # Axios factory
│   ├── ...                 # Endpoint modules (nodes, chatflows, etc.)
│   └── index.ts
│
└── store/                  # State management
    ├── AgentflowContext.tsx # Flow state context
    ├── agentflowReducer.ts # Reducer for flow state actions
    ├── ...                 # Other contexts (ApiContext, ConfigContext)
    └── index.ts

Rules:

  • All external communication goes here
  • Contexts are internal (composed in AgentflowProvider)
  • API hooks live with their API modules

Goal: To wrap external dependencies so they can be easily swapped or mocked in tests.


Dependency Flow

Dependencies must only flow downwards.

┌─────────────────────────────────────────────────────────┐
│                  Root Files (Public API)                │
│    (index.ts, Agentflow.tsx, AgentflowProvider.tsx)     │
│                   "The Public Face"                     │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│                      features/                          │
│   (canvas, node-palette, generator, node-editor)        │
│                   "What it does"                        │
└─────────────────────────────────────────────────────────┘
          │                                    │
          ▼                                    ▼
┌──────────────────┐              ┌────────────────────────┐
│      atoms/      │              │    infrastructure/     │
│  (UI primitives) │              │    (api, store)        │
│ "What it looks   │              │ "The Outside World"    │
│     like"        │              │                        │
└──────────────────┘              └────────────────────────┘
          │                                    │
          └──────────────┬─────────────────────┘
                         ▼
              ┌─────────────────────┐
              │        core/        │
              │  (types, constants, │
              │   validation, etc.) │
              │     "The Brain"     │
              └─────────────────────┘

Import Rules:

  • features → atoms, infrastructure, core ✅
  • infrastructure → core ✅
  • atoms → core/types, core/theme, and core/primitives only ✅
  • core → nothing (leaf node) ✅
  • Atoms and Core are "leaf" nodes - they cannot import from features/ or infrastructure/

Gatekeeper Pattern

Each module exposes only what's needed via its index.ts:

// features/canvas/index.ts
// ✅ Public API
export const nodeTypes = { ... }
export const edgeTypes = { ... }
export { ConnectionLine, AgentflowHeader, createHeaderProps }
export { useFlowNodes, useFlowHandlers, useDragAndDrop }

// Container components are re-exported for advanced usage
export { AgentFlowNode, AgentFlowEdge, StickyNote, IterationNode }

// ❌ Internal sub-components stay private within containers/components

This enables:

  • Encapsulation: Internal refactoring doesn't break consumers
  • Tree-shaking: Bundlers can eliminate unused code
  • Clarity: Clear contract of what each module provides

Adding a New Feature

  1. Create folder under features/:

    features/my-feature/
    ├── containers/         # Smart components (optional)
    │   └── MyContainer.tsx
    ├── components/         # Presentational components (optional)
    │   └── MyComponent.tsx
    ├── hooks/              # Feature-specific hooks (optional)
    │   └── useMyHook.ts
    ├── helper.ts           # Feature-specific util
    └── index.ts            # Public exports only
    
  2. Export only what's needed:

    // index.ts
    export { MyContainer } from './containers'
    export { MyComponent } from './components'
    export { useMyHook } from './hooks'
    export type { MyComponentProps } from './components'
    
  3. Import from infrastructure/core, never from other features:

    // ✅ Good
    import { useApiContext } from '../../infrastructure/store'
    import type { NodeData } from '../../core/types'
    
    // ❌ Bad - cross-feature import
    import { AgentFlowNode } from '../canvas/containers/AgentFlowNode'
    

Root Files (src/*.ts)

"The Public Face." The entry point of the package.

  • AgentflowProvider.tsx: Injects infrastructure (stores/api) into the app
  • Agentflow.tsx: The primary component users will drop into their apps
  • useAgentflow.ts: Primary public hook for accessing flow state and actions
  • index.ts: The "Barrel" that exports the public API for npm

Public API

The package exposes a minimal public API via src/index.ts:

// Components
export { Agentflow } from './Agentflow'
export { AgentflowProvider } from './AgentflowProvider'

// Hooks
export { useAgentflow } from './useAgentflow'
export { useApiContext, useConfigContext, useAgentflowContext } from './infrastructure/store'

// Types
export type { AgentflowProps, FlowData, NodeData, ... } from './core/types'

// Utilities (for advanced usage)
export { AGENTFLOW_ICONS, validateFlow, ... } from './core/...'

Everything else is internal implementation detail.


Development Principles

Barrel Exports

Every directory must have an index.ts that acts as a gatekeeper.

✅ Good:

import { Button } from '@atoms'
import { useFlowHandlers } from '@features/canvas'

❌ Bad:

// Never deep-link into files
import { Button } from '@atoms/Button/Button'
import { useFlowHandlers } from '@features/canvas/hooks/useFlowHandlers'

Prop Drilling vs. Context

  • Atoms: Use props for all configuration
  • Features: Use context/state for shared data

Naming Convention

Type Convention Example
Component PascalCase.tsx AgentFlowNode.tsx
Hook camelCase.ts (use prefix) useFlowHandlers.ts
Logic/Types camelCase.ts flowValidation.ts, nodeFilters.ts
Styles kebab-case (co-located) canvas.css