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();
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:
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.
Agent Knowledge Manager: Captures and stores AI-generated knowledge in a centralized, organization-owned repository, preventing data silos and vendor lock-in.
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
- Agent Card: A JSON metadata file describing the agent's capabilities
- Message Endpoint: HTTP endpoint receiving A2A protocol messages
-
Task Lifecycle:
submitted→working→completed(orfailed) - 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)
Key Components
-
Agent Card (
card.ts): Defines agent metadata for discovery -
A2A Executor (
executor.ts): Handles A2A protocol lifecycle -
Kaiban Controller (
kaiban-controller.ts): Manages workflow state and card updates -
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,
},
});
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();
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,
});
}
}
}
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);
};
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`,
};
};
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_CREATEDactivity via A2A protocol
2. Processing Started (DOING)
- A2A executor receives the activity and routes it to the Kaiban controller
- Controller moves the card to
DOINGcolumn - 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
DONEcolumn - All activities are logged for audit trail
4. Error Handling (BLOCKED)
- If processing fails (invalid Excel, missing route, etc.)
- Card moves to
BLOCKEDcolumn - 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
2. Install Dependencies
npm install
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
4. Start the Server
npm run dev
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
- Log into your Kaiban.io dashboard
- Navigate to Agents section
- 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
- Agent Card URL:
- Assign the agent to a Kanban board
6. Test the Integration
- Create a card in your Kaiban board with a description like:
Analyze route LHR-SLC using data from https://example.com/pricing-analysis.xlsx
- 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.
Top comments (0)