DEV Community

Cover image for Integrating KaibanJS Teams with Kaiban.io: Enterprise Workflow Automation via A2A Protocol
Dariel Vila for KaibanJS

Posted on

Integrating KaibanJS Teams with Kaiban.io: Enterprise Workflow Automation via A2A Protocol

Introduction

In today's enterprise landscape, AI agents need to seamlessly integrate with existing workflow management systems. While building intelligent agents is powerful, their true value is unlocked when they can participate in collaborative workflows, update task statuses automatically, and provide visibility across teams.

This article explores how to integrate KaibanJS—a multi-agent framework for building collaborative AI teams—with Kaiban.io—an enterprise workflow management platform—using the standardized A2A (Agent-to-Agent) protocol.

We'll build a real-world example: an Airline Revenue Management Agent that processes cards from a Kanban board, analyzes Excel data, and automatically updates card statuses through the workflow lifecycle.

What is KaibanJS?

KaibanJS is an open-source TypeScript framework for building multi-agent AI systems. It enables developers to create collaborative teams of AI agents that work together to solve complex problems through structured workflows.

Key features:

  • Multi-agent collaboration: Define teams of specialized agents working together
  • Workflow-driven execution: Create sequential or parallel workflows using WorkflowDrivenAgent
  • Type-safe schemas: Built-in support for Zod schemas for validation
  • Tool integration: Agents can use custom tools for external operations
  • Flexible orchestration: Supports both simple task execution and complex multi-step workflows

Example: A Simple KaibanJS Team

import { Agent, Task, Team } from 'kaibanjs';

const analystAgent = new Agent({
  name: 'Data Analyst',
  role: 'Business Intelligence Specialist',
  goal: 'Analyze revenue data and provide insights',
});

const analysisTask = new Task({
  title: 'Analyze Revenue Data',
  description: 'Process Excel data and generate revenue insights',
  agent: analystAgent,
  expectedOutput: 'Revenue analysis report',
});

const team = new Team({
  name: 'Revenue Analysis Team',
  agents: [analystAgent],
  tasks: [analysisTask],
  inputs: { excelUrl: 'https://example.com/data.xlsx' },
});

const { result } = await team.start();
Enter fullscreen mode Exit fullscreen mode

What is Kaiban.io?

Kaiban.io is an AI Agent Management System for airlines and enterprise organizations. As described on kaiban.io, it serves as a "command center for your AI workforce," providing a unified platform to safely deploy, train, and manage AI agents alongside existing teams and systems.

The platform addresses the challenge of AI agent fragmentation in enterprise environments by providing governance, visibility, and control over agent deployments. Kaiban.io integrates directly into existing systems and workflows without requiring costly infrastructure migrations, enabling organizations to start small and scale safely into connected multi-agent ecosystems.

Core Management Modules

Kaiban.io is built around three core management modules:

  1. Agent Workflow Manager: Provides Kanban boards with card-based task management, real-time visibility into agent activities, and automatic status transitions (TODO → DOING → DONE → BLOCKED). This is the primary interface for our integration.

  2. Agent Knowledge Manager: Captures and stores AI-generated knowledge in a centralized, organization-owned repository, preventing data silos and vendor lock-in.

  3. Agent Lifecycle Manager: Manages the complete agent lifecycle—from recruitment and training to monitoring, enhancement, and retirement—with standardized processes and performance benchmarks.

A2A Protocol Integration

Kaiban.io supports the standardized A2A (Agent-to-Agent) protocol, enabling seamless integration with any agent framework, including KaibanJS, LangChain, AutoGen, and others. This SDK-agnostic approach eliminates vendor lock-in.

The platform acts as an orchestration layer:

  • Sends card activities to agents via A2A protocol messages when cards are created, moved, or updated
  • Receives status updates from agents, automatically updating card states and workflow progress
  • Provides discovery through agent cards that describe agent capabilities
  • Enables interoperability between agents built with different SDKs using the same standard

For our integration, the Agent Workflow Manager is the primary interaction point, managing the Kanban board where agents process cards and update their status automatically.

The A2A Protocol

The Agent-to-Agent (A2A) protocol is a standardized specification for agent communication. It defines how agents discover each other, exchange messages, and report execution status.

A2A Protocol Components

  1. Agent Card: A JSON metadata file describing the agent's capabilities
  2. Message Endpoint: HTTP endpoint receiving A2A protocol messages
  3. Task Lifecycle: submittedworkingcompleted (or failed)
  4. Event Bus: Communication channel for status updates

The protocol enables interoperability—agents built with different SDKs can communicate using the same standard.

Architecture Overview

When integrating KaibanJS with Kaiban.io, the architecture follows this flow:

Kaiban.io Platform
    ↓ (Card created/moved)
    ↓ (A2A message with KaibanActivityPart)
A2A Executor
    ↓ (Extract activity)
Kaiban Controller
    ↓ (Process workflow)
KaibanJS Team
    ↓ (Execute agents)
Business Logic
    ↓ (Update card status)
Kaiban SDK
    ↓ (API calls)
Kaiban.io Platform (Card updated)
Enter fullscreen mode Exit fullscreen mode

Key Components

  1. Agent Card (card.ts): Defines agent metadata for discovery
  2. A2A Executor (executor.ts): Handles A2A protocol lifecycle
  3. Kaiban Controller (kaiban-controller.ts): Manages workflow state and card updates
  4. KaibanJS Team (agent.ts): Contains the business logic with AI agents

Implementation: Airline Revenue Management Agent

Let's build a complete integration example. This agent processes cards from a Kaiban board, extracts Excel URLs and route information, downloads the data, and performs revenue management analysis.

Step 1: Agent Card Configuration

The agent card is served at /.well-known/agent-card.json and provides discovery information:

// src/agents/airline-revenue-management/card.ts
import { AgentCard } from '@a2a-js/sdk';

export const revenueManagementAgentCard = (url: string): AgentCard => ({
  name: 'Airline Revenue Management Agent',
  description:
    'Agent that analyzes airline route data from Excel files and generates optimal fare recommendations',

  protocolVersion: '0.3.0',
  version: '0.1.0',
  url,

  defaultInputModes: ['text'],
  defaultOutputModes: ['text'],

  skills: [
    {
      id: 'revenue-management',
      name: 'Revenue Management Analysis',
      description: 'Analyzes airline route data and generates fare recommendations',
      tags: ['revenue-management', 'airline', 'pricing', 'excel-analysis'],
    },
  ],

  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: false,
  },
});
Enter fullscreen mode Exit fullscreen mode

Step 2: A2A Executor

The executor implements the A2A protocol, handling task lifecycle and routing activities to the Kaiban controller:

// src/agents/airline-revenue-management/executor.ts
import { AgentExecutor, ExecutionEventBus, RequestContext } from '@a2a-js/sdk/server';
import { A2ADataPartType, KaibanActivityPart } from '@kaiban/sdk';
import { RevenueManagementKaibanController } from './controller/kaiban-controller';

class RevenueManagementAgentExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: ExecutionEventBus): Promise<void> {
    const { taskId, contextId, userMessage } = requestContext;

    // Phase 1: Acknowledge task receipt
    eventBus.publish({
      kind: 'task',
      id: taskId,
      contextId,
      status: {
        state: 'submitted',
        timestamp: new Date().toISOString(),
      },
    });

    // Phase 2: Extract Kaiban activities from message
    const userMessageData = userMessage.parts.filter((part) => part.kind === 'data');

    if (userMessageData.length > 0) {
      eventBus.publish({
        kind: 'status-update',
        taskId,
        contextId,
        status: {
          state: 'working',
          timestamp: new Date().toISOString(),
        },
        final: false,
      });

      const kaibanController = await RevenueManagementKaibanController.build();

      // Phase 3: Process each Kaiban activity
      for (const messageData of userMessageData) {
        if (messageData.data.type === A2ADataPartType.KAIBAN_ACTIVITY) {
          const part = messageData as KaibanActivityPart;
          await kaibanController.processKaibanActivity(part.data.activity);
        }
      }
    }

    // Phase 4: Signal completion
    eventBus.publish({
      kind: 'status-update',
      taskId,
      contextId,
      status: {
        state: 'completed',
        timestamp: new Date().toISOString(),
      },
      final: true,
    });

    eventBus.finished();
  }
}

export const revenueManagementAgentExecutor = new RevenueManagementAgentExecutor();
Enter fullscreen mode Exit fullscreen mode

Step 3: Kaiban Controller

The controller manages the workflow lifecycle, updating cards as they progress through stages:

// src/agents/airline-revenue-management/controller/kaiban-controller.ts
import { Activity, ActivityType, CardStatus, createKaibanClient, KaibanClient } from '@kaiban/sdk';
import { processRevenueManagementRequest } from './agent';

const TODO_COLUMN_KEY = 'todo';
const DOING_COLUMN_KEY = 'doing';
const DONE_COLUMN_KEY = 'done';
const BLOCKED_COLUMN_KEY = 'blocked';

export class RevenueManagementKaibanController {
  constructor(
    private readonly kaibanActor: ActivityActor,
    private readonly kaibanClient: KaibanClient,
  ) {}

  static async build() {
    const tenant = process.env.KAIBAN_TENANT;
    const token = process.env.KAIBAN_API_TOKEN;
    const agentId = process.env.KAIBAN_AGENT_ID;
    const baseUrl = process.env.KAIBAN_API_URL || `https://${tenant}.kaiban.io/api`;

    const kaibanClient = createKaibanClient({ baseUrl, tenant, token });
    const agent = await kaibanClient.agents.get(agentId);

    return new RevenueManagementKaibanController(
      { id: agent.id, type: 'agent', name: agent.name },
      kaibanClient,
    );
  }

  async processKaibanActivity(activity: Activity) {
    switch (activity.type) {
      case ActivityType.CARD_CREATED:
      case ActivityType.CARD_CLONED:
      case ActivityType.CARD_AGENT_ADDED:
      case ActivityType.CARD_COLUMN_CHANGED:
        await this.processCardCreatedActivity(activity);
        break;
    }
  }

  private async processCardCreatedActivity(activity: Activity) {
    const card = await this.kaibanClient.cards.get(activity.card_id);

    // Skip if card doesn't meet requirements
    if (
      !card?.description ||
      card.column_key !== TODO_COLUMN_KEY ||
      activity.actor.id === this.kaibanActor.id
    ) {
      return;
    }

    // Stage 1: Move to DOING
    await this.kaibanClient.cards.update(card.id, {
      column_key: DOING_COLUMN_KEY,
      status: CardStatus.DOING,
    });

    try {
      // Stage 2: Process with KaibanJS team
      const result = await processRevenueManagementRequest(card.description);

      // Stage 3: Update card and move to DONE
      await this.kaibanClient.cards.update(card.id, {
        result: result,
        column_key: DONE_COLUMN_KEY,
        status: CardStatus.DONE,
      });
    } catch (error) {
      // Error handling: Move to BLOCKED
      await this.kaibanClient.cards.update(card.id, {
        column_key: BLOCKED_COLUMN_KEY,
        status: CardStatus.BLOCKED,
      });
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: KaibanJS Team with Workflow

The team uses a WorkflowDrivenAgent with three sequential steps:

// src/agents/airline-revenue-management/controller/agent.ts
import { Agent, Task, Team } from 'kaibanjs';
import { createStep, createWorkflow } from '@kaibanjs/workflow';
import { z } from 'zod';
import * as XLSX from 'xlsx';

// Step 1: Extract URL and routes from user message
const extractUrlAndRoutesStep = createStep({
  id: 'extract-url-and-routes',
  inputSchema: z.object({ userMessage: z.string() }),
  outputSchema: z.object({
    excelUrl: z.string().url(),
    route: z.string(),
  }),
  execute: async ({ inputData }) => {
    const { userMessage } = inputData;
    // Use an extraction team to parse the message
    const extractionTeam = createExtractionTeam(userMessage);
    const result = await extractionTeam.start();
    return result.result;
  },
});

// Step 2: Download and parse Excel file
const downloadParseAndExtractRouteStep = createStep({
  id: 'download-parse-extract-route',
  inputSchema: z.object({
    excelUrl: z.string().url(),
    route: z.string(),
  }),
  outputSchema: z.object({
    route: z.string(),
    origin: z.string(),
    destination: z.string(),
    cyForecast: z.string(),
    pyData: z.string(),
    competitorFares: z.string(),
  }),
  execute: async ({ inputData }) => {
    const { excelUrl, route } = inputData;

    // Download Excel file
    const response = await fetch(excelUrl);
    const arrayBuffer = await response.arrayBuffer();
    const workbook = XLSX.read(new Uint8Array(arrayBuffer), { type: 'array' });

    // Parse sheets and extract route data
    const cyForecast = workbook.Sheets['CY Forecast'];
    const pyData = workbook.Sheets['PY Data'];
    const competitorFares = workbook.Sheets['Competitor Fares'];

    // Find route-specific data...
    // Return extracted data
    return {
      route,
      origin: route.split('-')[0],
      destination: route.split('-')[1],
      cyForecast: JSON.stringify(/* parsed data */),
      pyData: JSON.stringify(/* parsed data */),
      competitorFares: JSON.stringify(/* parsed data */),
    };
  },
});

// Step 3: Execute revenue management analysis
const executeAnalysisStep = createStep({
  id: 'execute-analysis',
  inputSchema: z.object({
    route: z.string(),
    origin: z.string(),
    destination: z.string(),
    cyForecast: z.string(),
    pyData: z.string(),
    competitorFares: z.string(),
  }),
  outputSchema: z.unknown(),
  execute: async ({ inputData }) => {
    // Execute the revenue management analysis team
    const analysisTeam = revenueManagementAnalysisTeam;
    const { result } = await analysisTeam.start(inputData);
    return result;
  },
});

// Create workflow
const analysisWorkflow = createWorkflow({
  id: 'revenue-management-analysis-workflow',
  inputSchema: z.object({ userMessage: z.string() }),
  outputSchema: z.record(z.unknown()),
});

// Chain steps
analysisWorkflow
  .then(extractUrlAndRoutesStep)
  .then(downloadParseAndExtractRouteStep)
  .then(executeAnalysisStep);
analysisWorkflow.commit();

// Create WorkflowDrivenAgent
const workflowAnalysisAgent = new Agent({
  type: 'WorkflowDrivenAgent',
  name: 'Revenue Management Workflow Agent',
  workflow: analysisWorkflow,
});

export const processRevenueManagementRequest = async (userMessage: string) => {
  const team = new Team({
    name: 'Airline Revenue Management Team',
    agents: [workflowAnalysisAgent],
    tasks: [
      /* tasks */
    ],
    inputs: { userMessage },
  });

  const { result } = await team.start();
  return JSON.stringify(result);
};
Enter fullscreen mode Exit fullscreen mode

Step 5: Request Handler Setup

Finally, wire everything together in the Express server:

// src/agents/airline-revenue-management/handler.ts
import { DefaultRequestHandler } from '@a2a-js/sdk/server';
import { A2AExpressApp } from '@a2a-js/sdk/server/express';
import express from 'express';
import { revenueManagementAgentCard } from './card';
import { tasksStore, revenueManagementAgentExecutor } from './executor';

export const createRevenueManagementAgentHandler = (agentUrl: string) => {
  return new DefaultRequestHandler(
    revenueManagementAgentCard(agentUrl),
    tasksStore,
    revenueManagementAgentExecutor,
  );
};

export const setupRevenueManagementAgentRoutes = (app: express.Express, baseUrl: string) => {
  const agentPath = '/airlineRevenueManagement/a2a';
  const agentUrl = `${baseUrl}${agentPath}`;

  new A2AExpressApp(createRevenueManagementAgentHandler(agentUrl)).setupRoutes(app, agentPath);

  return {
    agentUrl,
    cardUrl: `${agentUrl}/.well-known/agent-card.json`,
  };
};
Enter fullscreen mode Exit fullscreen mode

Workflow Lifecycle

When a card is created in Kaiban.io, the following lifecycle occurs:

1. Card Created (TODO)

  • User creates a card in the Kanban board with a description containing Excel URL and route
  • Kaiban.io sends a CARD_CREATED activity via A2A protocol

2. Processing Started (DOING)

  • A2A executor receives the activity and routes it to the Kaiban controller
  • Controller moves the card to DOING column
  • KaibanJS team begins processing:
    • Extracts Excel URL and route from card description
    • Downloads and parses Excel file
    • Executes revenue management analysis

3. Analysis Complete (DONE)

  • Team completes analysis and generates recommendations
  • Controller updates card with results
  • Card moves to DONE column
  • All activities are logged for audit trail

4. Error Handling (BLOCKED)

  • If processing fails (invalid Excel, missing route, etc.)
  • Card moves to BLOCKED column
  • Error details are logged for manual review

Setup Instructions

1. Clone the Starter Repository

git clone https://github.com/kaiban-ai/kaiban-agents-starter.git
cd kaiban-agents-starter/examples/airline-revenue-management-kaibanjs
Enter fullscreen mode Exit fullscreen mode

2. Install Dependencies

npm install
Enter fullscreen mode Exit fullscreen mode

3. Configure Environment Variables

Create a .env file:

# Kaiban.io Platform Configuration
KAIBAN_TENANT=your-tenant
KAIBAN_API_TOKEN=your-api-token
KAIBAN_AGENT_ID=your-agent-id
KAIBAN_API_URL=https://your-tenant.kaiban.io/api

# A2A Protocol Configuration
A2A_BASE_URL=http://localhost:4000
PORT=4000

# AI Configuration
OPENAI_API_KEY=your-openai-api-key
Enter fullscreen mode Exit fullscreen mode

4. Start the Server

npm run dev
Enter fullscreen mode Exit fullscreen mode

The server will start on port 4000 with these endpoints:

  • Agent Card: http://localhost:4000/airlineRevenueManagement/a2a/.well-known/agent-card.json
  • Agent Endpoint: POST http://localhost:4000/airlineRevenueManagement/a2a

5. Register Agent in Kaiban.io

  1. Log into your Kaiban.io dashboard
  2. Navigate to Agents section
  3. Register your agent using:
    • Agent Card URL: http://your-public-url/airlineRevenueManagement/a2a/.well-known/agent-card.json
    • Agent Endpoint URL: http://your-public-url/airlineRevenueManagement/a2a
  4. Assign the agent to a Kanban board

6. Test the Integration

  1. Create a card in your Kaiban board with a description like:
   Analyze route LHR-SLC using data from https://example.com/pricing-analysis.xlsx
Enter fullscreen mode Exit fullscreen mode
  1. The agent will automatically:
    • Extract the URL and route
    • Download and parse the Excel file
    • Perform revenue management analysis
    • Update the card with results

Benefits of This Integration

1. SDK Agnostic

The A2A protocol works with any agent framework. You can build agents with KaibanJS, LangChain, AutoGen, or any other SDK.

2. Standardized Communication

The A2A protocol provides a standard way for agents to communicate, reducing integration complexity.

3. Automatic Workflow Management

Cards automatically transition through workflow states based on agent execution, providing visibility and traceability.

4. Enterprise Visibility

Full audit trail of all activities, status changes, and agent interactions in a centralized platform.

5. Real-time Collaboration

Teams can collaborate on cards, assign agents, and track progress in real-time through the Kaiban board interface.

Conclusion

Integrating KaibanJS with Kaiban.io via the A2A protocol enables powerful enterprise workflow automation. Agents built with KaibanJS can seamlessly participate in Kanban workflows managed by Kaiban.io's Agent Workflow Manager, automatically update card statuses, and provide full visibility into AI-driven processes.

The standardized A2A protocol ensures interoperability between KaibanJS agents and the Kaiban platform, while KaibanJS provides a powerful framework for building multi-agent AI systems. Together, they enable developers to:

  • Integrate naturally with existing enterprise workflows and systems
  • Maintain full governance and visibility into agent execution
  • Scale safely from single agents to connected multi-agent ecosystems
  • Deliver measurable value through standardized processes and performance tracking

This integration demonstrates how KaibanJS can work alongside enterprise platforms like Kaiban.io to transform AI agents from isolated experiments into reliable, governed, and high-impact operational capabilities—all without disrupting existing operations.

Additional Resources

Top comments (0)