Multi-Agent System Integration: KaibanJS and Kaiban.io via A2A Protocol

Community Article Published January 22, 2026

KaibanJSIntegrationIO

Abstract

This technical article presents an architecture for integrating multi-agent AI systems built with KaibanJS,a TypeScript framework for collaborative agent orchestration with Kaiban.io,an AI agent management platform,using the standardized A2A (Agent-to-Agent) protocol. We demonstrate a production-ready implementation pattern that enables LLM-powered agents to participate in workflow orchestration systems while maintaining interoperability, observability, and governance.

Introduction

Multi-agent systems represent a significant advancement in AI application architecture, enabling complex problem-solving through collaborative agent interactions. However, deploying these systems in production environments requires robust integration with existing workflow management systems, standardized communication protocols, and comprehensive observability.

This article addresses the integration challenge by presenting a concrete implementation pattern that combines:

  • KaibanJS: A framework for building multi-agent systems with workflow-driven execution
  • Kaiban.io: An agent management platform providing workflow orchestration and governance
  • A2A Protocol: A standardized specification for agent-to-agent communication

We present a case study: an Airline Revenue Management Agent that processes structured data, performs analytical reasoning using LLMs, and integrates with enterprise workflow systems.

Background: Multi-Agent Systems and Workflow Orchestration

KaibanJS: Multi-Agent Framework Architecture

KaibanJS is an open-source TypeScript framework designed for building multi-agent AI systems. It provides a structured approach to agent orchestration, enabling developers to define collaborative teams of specialized agents that work together through well-defined workflows.

Architectural Components

  1. Agent: Represents an autonomous entity with defined role, goal, and background context
  2. Task: Defines a specific objective with expected output schema
  3. Team: Orchestrates multiple agents working on related tasks
  4. Workflow: Defines sequential or parallel execution patterns using WorkflowDrivenAgent

Type-Safe Agent Definition

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

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

const analysisTask = new Task({
  title: 'Analyze Revenue Data',
  description: 'Process Excel data and generate revenue insights using statistical methods',
  agent: analystAgent,
  expectedOutput: 'Revenue analysis report with recommendations',
  outputSchema: z.object({
    insights: z.array(z.string()),
    recommendations: z.array(z.string()),
    confidence: z.number().min(0).max(1),
  }),
});

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

Workflow-Driven Execution

KaibanJS supports workflow-driven agents that execute multi-step processes with type-safe data flow:

import { createStep, createWorkflow } from '@kaibanjs/workflow';

const step1 = createStep({
  id: 'extract-data',
  inputSchema: z.object({ url: z.string().url() }),
  outputSchema: z.object({ data: z.record(z.unknown()) }),
  execute: async ({ inputData }) => {
    // Extract and validate data
    return { data: await fetchData(inputData.url) };
  },
});

const workflow = createWorkflow({
  id: 'analysis-workflow',
  inputSchema: z.object({ url: z.string().url() }),
  outputSchema: z.object({ result: z.string() }),
});

workflow.then(step1).then(step2).then(step3);
workflow.commit();

Kaiban.io: Airline-Specialized Agent Management Platform

Kaiban.io is an AI agent management system specifically designed for airline operations, addressing the unique challenges of deploying multi-agent systems in aviation environments. The platform provides workflow orchestration, governance, and observability tailored to airline operational requirements, regulatory compliance, and legacy system integration needs.

Airline Industry Specialization

Kaiban.io is built with deep understanding of airline operational realities:

  • Regulatory Compliance: Supports aviation-specific benchmarks and compliance requirements (IATA, FAA, EASA standards)
  • Legacy System Integration: Designed to integrate with existing airline systems (PSS, RMS, OMS) without costly migrations
  • Operational Context: Understands airline-specific workflows across revenue management, operations, customer service, and maintenance
  • Domain Expertise: Pre-configured agent templates for airline use cases (IROPS management, revenue optimization, crew scheduling, etc.)

Core Architecture Modules

  1. Agent Workflow Manager: Kanban-based workflow orchestration with card lifecycle management, providing real-time visibility into agent activities across airline departments
  2. Agent Knowledge Manager: Centralized knowledge repository that captures airline-specific insights, preventing data silos and ensuring organizational ownership of AI-generated knowledge
  3. Agent Lifecycle Manager: Complete agent lifecycle governance with airline-specific performance benchmarks, training protocols, and retirement procedures

A2A Protocol Integration

Kaiban.io implements the A2A protocol specification, enabling SDK-agnostic agent integration:

  • Agent Discovery: Via agent cards served at /.well-known/agent-card.json
  • Message Exchange: Standardized HTTP-based communication with support for airline-specific data formats
  • Task Lifecycle: State machine with submittedworkingcompleted transitions, aligned with airline operational workflows
  • Event Bus: Real-time status updates via Server-Sent Events (SSE) for operational monitoring

The platform acts as an orchestration layer, sending workflow activities to agents and receiving execution status updates, enabling seamless integration regardless of the agent implementation framework while maintaining airline operational standards.

The A2A Protocol: Standardized Agent Communication

The Agent-to-Agent (A2A) protocol is a standardized specification for agent communication, developed to enable interoperability between agents built with different frameworks and SDKs.

Protocol Architecture

The A2A protocol defines four core components:

  1. Agent Card: JSON-LD metadata describing agent capabilities, endpoints, and protocol version
  2. Message Endpoint: HTTP POST endpoint receiving A2A protocol messages
  3. Task Lifecycle: State machine with explicit state transitions
  4. Event Bus: Communication channel for status updates (typically SSE or WebSocket)

Message Format

A2A messages follow a structured format:

interface A2AMessage {
  taskId: string;
  contextId: string;
  userMessage: {
    parts: Array<TextPart | DataPart>;
  };
}

interface KaibanActivityPart extends DataPart {
  data: {
    type: 'kaiban.activity';
    activity: Activity;
  };
}

Task Execution Lifecycle

// State transitions
'submitted''working''completed' | 'failed'

// Event bus messages
eventBus.publish({
  kind: 'task',
  id: taskId,
  status: { state: 'submitted', timestamp: ISO8601 },
});

eventBus.publish({
  kind: 'status-update',
  taskId,
  status: { state: 'working', timestamp: ISO8601 },
  final: false,
});

System Architecture

The integration architecture follows a layered approach:

┌─────────────────────────────────────┐
│     Kaiban.io Platform              │
│  (Workflow Orchestration Layer)     │
└──────────────┬──────────────────────┘
               │ A2A Protocol (HTTP/SSE)
               │ KaibanActivityPart
               ▼
┌─────────────────────────────────────┐
│     A2A Executor                    │
│  (Protocol Implementation)          │
│  - Task lifecycle management        │
│  - Event bus communication          │
└──────────────┬──────────────────────┘
               │ Activity routing
               ▼
┌─────────────────────────────────────┐
│     Kaiban Controller               │
│  (Workflow State Management)        │
│  - Card state transitions            │
│  - API integration                  │
└──────────────┬──────────────────────┘
               │ Workflow invocation
               ▼
┌─────────────────────────────────────┐
│     KaibanJS Team                   │
│  (Multi-Agent System)               │
│  - WorkflowDrivenAgent               │
│  - LLM orchestration                │
│  - Business logic execution          │
└──────────────┬──────────────────────┘
               │ Results
               ▼
┌─────────────────────────────────────┐
│     Kaiban SDK                      │
│  (Platform API Client)              │
│  - Card updates                      │
│  - Activity logging                  │
└──────────────┬──────────────────────┘
               │ HTTP API calls
               ▼
┌─────────────────────────────────────┐
│     Kaiban.io Platform              │
│  (State persistence)                 │
└─────────────────────────────────────┘

Component Responsibilities

  1. A2A Executor: Implements protocol compliance, manages task lifecycle, routes activities
  2. Kaiban Controller: Orchestrates workflow state, manages card transitions, handles errors
  3. KaibanJS Team: Executes business logic using multi-agent workflows and LLM reasoning
  4. Kaiban SDK: Provides type-safe API client for platform interactions

Implementation: Revenue Management Agent

We present a complete implementation of an airline revenue management agent that demonstrates the integration pattern.

Agent Card Definition

The agent card provides discovery metadata following the A2A specification:

// 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 using revenue management methodology',

  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 using standardized revenue management methodology',
      tags: ['revenue-management', 'airline', 'pricing', 'excel-analysis', 'route-analysis'],
    },
  ],

  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: false,
  },
});

A2A Executor Implementation

The executor implements the AgentExecutor interface, handling protocol compliance:

// 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 (A2A protocol requirement)
    eventBus.publish({
      kind: 'task',
      id: taskId,
      contextId,
      status: {
        state: 'submitted',
        timestamp: new Date().toISOString(),
      },
    });

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

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

      const kaibanController = await RevenueManagementKaibanController.build();

      // Phase 4: 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 5: Signal completion
    eventBus.publish({
      kind: 'status-update',
      taskId,
      contextId,
      status: {
        state: 'completed',
        timestamp: new Date().toISOString(),
      },
      final: true,
    });

    eventBus.finished();
  }

  async cancelTask(taskId: string, eventBus: ExecutionEventBus): Promise<void> {
    // Implementation for task cancellation
    eventBus.publish({
      kind: 'status-update',
      taskId,
      status: {
        state: 'cancelled',
        timestamp: new Date().toISOString(),
      },
      final: true,
    });
    eventBus.finished();
  }
}

export const revenueManagementAgentExecutor = new RevenueManagementAgentExecutor();

Workflow State Management

The Kaiban controller manages card lifecycle and state transitions:

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

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.processCardActivity(activity);
        break;
    }
  }

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

    // Validation: ensure card is processable
    if (
      !card?.description ||
      card.column_key !== 'todo' ||
      activity.actor.id === this.kaibanActor.id
    ) {
      return;
    }

    // State transition: TODO → DOING
    await this.kaibanClient.cards.update(card.id, {
      column_key: 'doing',
      status: CardStatus.DOING,
    });

    try {
      // Execute KaibanJS team workflow
      const result = await processRevenueManagementRequest(card.description);

      // State transition: DOING → DONE
      await this.kaibanClient.cards.update(card.id, {
        result: result,
        column_key: 'done',
        status: CardStatus.DONE,
      });
    } catch (error) {
      // Error handling: DOING → BLOCKED
      await this.kaibanClient.cards.update(card.id, {
        column_key: 'blocked',
        status: CardStatus.BLOCKED,
      });
      throw error;
    }
  }
}

Multi-Agent Workflow Implementation

The KaibanJS team implements a three-step workflow using WorkflowDrivenAgent:

// 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: Information Extraction
const extractUrlAndRoutesStep = createStep({
  id: 'extract-url-and-routes',
  inputSchema: z.object({ userMessage: z.string() }),
  outputSchema: z.object({
    excelUrl: z.string().url(),
    route: z.string().regex(/^[A-Z]{3}-[A-Z]{3}$/), // IATA format validation
  }),
  execute: async ({ inputData }) => {
    const { userMessage } = inputData;
    // Use LLM-powered extraction agent
    const extractionTeam = createExtractionTeam(userMessage);
    const result = await extractionTeam.start();
    return result.result;
  },
});

// Step 2: Data Processing
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(), // JSON stringified
    pyData: z.string(),
    competitorFares: z.string(),
  }),
  execute: async ({ inputData }) => {
    const { excelUrl, route } = inputData;

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

    // Extract route-specific data
    const [origin, destination] = route.split('-');
    const cyForecast = extractRouteData(workbook, 'CY Forecast', origin, destination);
    const pyData = extractRouteData(workbook, 'PY Data', origin, destination);
    const competitorFares = extractRouteData(workbook, 'Competitor Fares', origin, destination);

    return {
      route,
      origin,
      destination,
      cyForecast: JSON.stringify(cyForecast),
      pyData: JSON.stringify(pyData),
      competitorFares: JSON.stringify(competitorFares),
    };
  },
});

// Step 3: LLM-Powered 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.object({
    recommendations: z.array(z.string()),
    fareRecommendation: z.number(),
    justification: z.string(),
    confidence: z.number().min(0).max(1),
  }),
  execute: async ({ inputData }) => {
    // Execute revenue management analysis using specialized team
    const analysisTeam = revenueManagementAnalysisTeam;
    const { result } = await analysisTeam.start(inputData);
    return result;
  },
});

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

analysisWorkflow
  .then(extractUrlAndRoutesStep)
  .then(downloadParseAndExtractRouteStep)
  .then(executeAnalysisStep);
analysisWorkflow.commit();

// WorkflowDrivenAgent definition
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: [/* task definitions */],
    inputs: { userMessage },
    env: {
      OPENAI_API_KEY: process.env.OPENAI_API_KEY,
    },
  });

  const { result } = await team.start();
  return JSON.stringify(result);
};

Workflow Execution Lifecycle

The complete execution lifecycle demonstrates state transitions and error handling:

State Machine

┌─────────┐
│  TODO   │ (Card created in Kanban board)
└────┬────┘
     │ CARD_CREATED activity
     ▼
┌─────────┐
│  DOING  │ (Agent processing)
└────┬────┘
     │
     ├─► Success ──► ┌─────────┐
     │               │  DONE   │ (Results updated)
     │               └─────────┘
     │
     └─► Error ────► ┌──────────┐
                     │ BLOCKED  │ (Manual intervention)
                     └──────────┘

Execution Phases

  1. Card Creation: User creates card with task description → CARD_CREATED activity sent via A2A
  2. Task Submission: A2A executor receives activity → publishes submitted state
  3. Processing: Controller transitions card to DOING → KaibanJS team executes workflow
  4. Completion: Team returns results → Controller updates card → transitions to DONE
  5. Error Handling: Exceptions caught → card transitions to BLOCKED → error logged

Technical Considerations

LLM Integration

The implementation uses OpenAI's API for LLM-powered agents. The framework supports:

  • Multiple LLM providers: Configurable via environment variables
  • Streaming responses: Real-time output via SSE
  • Token management: Automatic context window management
  • Error handling: Retry logic and fallback mechanisms

Type Safety

Type safety is enforced through:

  • Zod schemas: Runtime validation for all workflow steps
  • TypeScript: Compile-time type checking
  • Schema validation: Input/output validation at each step

Observability

The integration provides comprehensive observability:

  • Activity logging: All card state transitions logged
  • Execution traces: Complete workflow execution history
  • Error tracking: Detailed error information in blocked cards
  • Performance metrics: Execution time and resource usage

Deployment and Configuration

Environment Setup

# Clone repository
git clone https://github.com/kaiban-ai/kaiban-agents-starter.git
cd kaiban-agents-starter/examples/airline-revenue-management-kaibanjs

# Install dependencies
npm install

# Configure environment
cp .env.example .env

Environment Variables

# Kaiban.io Platform
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
A2A_BASE_URL=https://your-public-url.com
PORT=4000

# LLM Configuration
OPENAI_API_KEY=your-openai-api-key

Server Deployment

// src/index.ts
import express from 'express';
import { setupRevenueManagementAgentRoutes } from './agents/airline-revenue-management/handler';

const app = express();
const port = process.env.PORT || 4000;
const baseUrl = process.env.A2A_BASE_URL || `http://localhost:${port}`;

// Setup A2A routes
const { agentUrl, cardUrl } = setupRevenueManagementAgentRoutes(app, baseUrl);

app.listen(port, () => {
  console.log(`A2A Agent Server running on port ${port}`);
  console.log(`Agent Card: ${cardUrl}`);
  console.log(`Agent Endpoint: ${agentUrl}`);
});

Benefits and Use Cases

Interoperability

The A2A protocol enables agents built with different frameworks (KaibanJS, LangChain, AutoGen) to integrate seamlessly with the same orchestration platform.

Scalability

The architecture supports:

  • Horizontal scaling: Multiple agent instances
  • Load distribution: Workflow-based task distribution
  • Resource optimization: Efficient LLM usage through workflow orchestration

Governance

Enterprise-grade governance features:

  • Audit trails: Complete activity logging
  • Access control: Role-based permissions
  • Compliance: Standardized protocols and data handling

Conclusion

This article presents a production-ready architecture for integrating multi-agent AI systems with workflow orchestration platforms using the A2A protocol. The implementation demonstrates:

  • Standardized communication: A2A protocol ensures interoperability
  • Type-safe workflows: Zod schemas provide runtime validation
  • Observable execution: Complete audit trails and error handling
  • Scalable architecture: Supports multi-agent ecosystems

The integration pattern enables developers to build sophisticated multi-agent systems that seamlessly participate in enterprise workflows while maintaining governance, visibility, and control.

References

Code Repository

The complete implementation is available at:

https://github.com/kaiban-ai/kaiban-agents-starter

Keywords: multi-agent systems, workflow orchestration, A2A protocol, LLM integration, agent frameworks, enterprise AI, TypeScript, agent communication protocols

Community

Sign up or log in to comment