Skip to main content
FlowApps are the plugin architecture that powers Iqra AI’s integration ecosystem. They allow you to extend agent capabilities by connecting to external services and APIs.

What is a FlowApp?

A FlowApp is a self-contained plugin that provides:
  • Actions: Operations that agents can perform (e.g., “Book a Meeting”, “Send Email”)
  • Data Fetchers: Dynamic dropdown options for action inputs (e.g., fetch list of event types)
  • Schema Definitions: JSON Schema files that define input validation and UI rendering
  • Authentication: Integration with the admin dashboard for credential management

Architecture overview

FlowApps follow a structured architecture:
YourApp/
├── YourApp.cs              # Main app definition (IFlowApp)
├── Actions/
│   ├── SendEmailAction.cs  # Action implementation (IFlowAction)
│   └── SendEmail.json      # JSON Schema for inputs
├── Fetchers/
│   └── GetTemplatesFetcher.cs  # Data fetcher (IFlowDataFetcher)
└── Models/
    └── YourAppModels.cs    # Request/response models

Core interfaces

public interface IFlowApp
{
    string AppKey { get; }                    // Unique identifier (e.g., "cal_com")
    string Name { get; }                       // Display name (e.g., "Cal.com")
    string IconUrl { get; }                    // App icon URL
    string? IntegrationType { get; }           // Links to admin dashboard credentials
    IReadOnlyList<IFlowAction> Actions { get; }           // Available actions
    IReadOnlyList<IFlowDataFetcher> DataFetchers { get; } // Dynamic data sources
}

Discovery and initialization

The FlowAppManager automatically discovers all FlowApps at startup using reflection:
// From FlowAppManager.cs:59
private void InitializeApps()
{
    var appType = typeof(IFlowApp);
    var types = Assembly.GetExecutingAssembly()
        .GetTypes()
        .Where(p => appType.IsAssignableFrom(p) && !p.IsInterface && !p.IsAbstract);

    foreach (var type in types)
    {
        // Use DI to create instances
        var appInstance = (IFlowApp)ActivatorUtilities.CreateInstance(_serviceProvider, type);
        _apps.Add(appInstance.AppKey, appInstance);
    }
}
FlowApps can have constructor dependencies like IHttpClientFactory or ILogger<T> - they are resolved automatically via dependency injection.

Execution pipeline

When an agent executes a FlowApp action, the following pipeline runs:
1

Template resolution

Scriban templates in inputs are resolved:
// User input: "{{ customer.name }}"
// Becomes: "John Doe"
var renderResult = await _scribanService.RenderDictionaryAsync(rawInputs, sessionContext);
2

Schema validation

Resolved inputs are validated against the JSON Schema:
var schemaJson = action.GetInputSchemaJson();
var validationResult = await _schemaValidator.ValidateAsync(
    jsonElement, 
    schemaJson,
    $"{appKey}_{actionKey}"
);
3

Action execution

The action’s ExecuteAsync method is invoked:
return await action.ExecuteAsync(jsonElement, GetDecryptedIntegration(integration));
4

Output routing

The result’s OutputPortKey determines the next node in the flow:
return ActionExecutionResult.SuccessPort("success", bookingData);
// or
return ActionExecutionResult.SuccessPort("conflict", conflictData);
// or
return ActionExecutionResult.Failure("API_ERROR", errorMessage);

Authentication and integrations

FlowApps can require authentication credentials managed through the admin dashboard:
IqraInfrastructure/Managers/FlowApp/Apps/CalCom/CalComApp.cs:14
public string? IntegrationType => "cal_com"; // Matches admin dashboard
When IntegrationType is set:
  • Admins configure credentials in the dashboard
  • Credentials are encrypted at rest
  • ExecuteAsync receives decrypted credentials via the integration parameter
var apiKey = integration.DecryptedFields["ApiKey"];
If IntegrationType is null, the app is considered public and requires no setup. Set RequiresIntegration = false in your actions.

Permissions and feature flags

FlowApps support runtime permissions managed via the database:
  • App-level: Disable entire integration
  • Action-level: Disable specific actions
  • Fetcher-level: Disable data sources
Permissions are cached for 10 minutes and checked before execution:
IqraInfrastructure/Managers/FlowApp/FlowAppManager.cs:254-263
var permissions = await GetCachedPermissionsAsync();
var appPerm = permissions.FirstOrDefault(p => p.AppKey == appKey);

if (appPerm?.DisabledAt != null)
{
    return ActionExecutionResult.Failure(
        "APP_DISABLED", 
        appPerm.DisabledPublicReason ?? "Integration temporarily disabled."
    );
}

Next steps

Creating FlowApps

Step-by-step guide to building your first FlowApp

Schema definition

Learn how to define JSON schemas for action inputs

Examples

Explore real-world FlowApp implementations

Build docs developers (and LLMs) love