Developers

Manifest Reference

Define plugin identity, tools, configuration, authentication, and safe execution contracts.

Overview

The manifest is the public contract for your plugin. It tells KasiLabs what the plugin is, where it is hosted, what tools it exposes, how those tools should be called, and what configuration the installer must provide.

Think of the manifest as both:

  • A product listing for admins deciding whether to install the plugin.
  • A tool contract for the agent deciding when and how to call your endpoint.

Full structure

json
{
  "slug": "MY_PLUGIN",
  "version": "1.0.0",
  "name": "My Plugin",
  "description": "Short customer-facing explanation of what this plugin does.",
  "author": {
    "name": "Your Company",
    "email": "support@example.com",
    "url": "https://example.com"
  },
  "tags": ["support", "crm"],
  "homepage": "https://example.com/plugin-docs",
  "baseUrl": "https://plugins.example.com/my-plugin",
  "auth": {
    "type": "secret"
  },
  "permissions": [
    {
      "key": "support:tickets:create",
      "label": "Create support tickets",
      "description": "Allows the agent to create customer support tickets.",
      "default": true
    }
  ],
  "configurationSchema": {
    "type": "object",
    "properties": {
      "workspaceId": {
        "type": "string",
        "description": "Workspace to connect this plugin to."
      }
    },
    "required": ["workspaceId"]
  },
  "tools": []
}

Required fields

FieldTypeDescription
slugstringUnique uppercase identifier such as ACME_CRM
versionstringVersion number such as 1.0.0
namestringHuman-readable plugin name
baseUrlstringHTTPS base URL for tool calls
authobjectAuthentication mode
toolsarrayTools exposed to the agent

Optional fields

FieldTypeDescription
descriptionstringShort explanation shown during installation
authorobjectPlugin author or company details
tagsstring[]Discovery tags such as support, orders, crm
homepagestringDocumentation or product page
configurationSchemaobjectInstallation-time configuration fields
permissionsarrayPermission requests and disclosures for the actions your plugin can perform

Tool definition

Each tool is one specific action the AI agent can ask your plugin to perform.

For example, if a customer asks, "Where is my delivery?", the agent might call a lookup_delivery tool. If the customer says, "My order arrived damaged", the agent might call a create_support_ticket tool. The tool name, description, and input schema tell the agent when that action is appropriate and what information it must provide.

json
{
  "name": "lookup_delivery",
  "description": "Look up delivery status by order number. Use this when a customer asks where their order is, asks for delivery ETA, or provides an order reference.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "orderNumber": {
        "type": "string",
        "description": "Customer-facing order number."
      }
    },
    "required": ["orderNumber"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "status": { "type": "string" },
      "eta": { "type": "string" }
    }
  },
  "endpoint": {
    "method": "POST",
    "path": "/execute"
  }
}

Permission requests

Use the top-level permissions array to declare what your plugin is asking to do. These are shown during review and installation so admins understand the authority they are giving the plugin.

There are two categories:

CategoryExampleRuntime effect
Plugin-owned permissionsupport:tickets:createDisclosure and admin review by default; your plugin should enforce it if the external action is sensitive
Platform bridge permissionplugin:payments:initiate:current_chatEnforced by KasiLabs before the platform action runs

This means removing support:tickets:create from the manifest may not stop the create_support_ticket endpoint from running. It mainly removes the explicit declaration shown to the merchant. Removing plugin:payments:initiate:current_chat is different: the payment bridge will reject payment requests from that plugin.

json
{
  "permissions": [
    {
      "key": "support:tickets:create",
      "label": "Create support tickets",
      "description": "Allows the agent to create customer support tickets in the connected support desk.",
      "default": true
    },
    {
      "key": "delivery:jobs:create",
      "label": "Create delivery jobs",
      "description": "Allows the agent to create delivery jobs after an order is confirmed paid."
    }
  ]
}

Permission keys should be namespaced to your plugin or business domain:

PatternExample
{domain}:{resource}:readsupport:tickets:read
{domain}:{resource}:createsupport:tickets:create
{domain}:{resource}:updatedelivery:jobs:update
{domain}:{sensitive_action}:manageaccounting:invoices:manage

Use default: true only for permissions that are safe for most installs. Leave sensitive actions off by default so admins must deliberately grant or approve them.

Permission requests versus dependency-only platform capabilities

Plugin permissions describe what your plugin can do or request. Platform capabilities such as Payments, M-Pesa, E-Commerce, Scheduling, and Escalations are owned by KasiLabs.

For plugin-owned workflows, do not ask the merchant to expose raw platform tools to the AI just so your plugin can use them. Declare the bridge permissions your plugin needs, then call the platform bridges from your plugin backend. The platform capability acts as a dependency-only service: it is available to your plugin through signed bridge calls, but it is not necessarily visible as an agent-facing tool.

This keeps the mother app business-agnostic. A gas plugin can expose gas tools, a legal plugin can expose consultation tools, and a salon plugin can expose booking tools. The platform only enforces generic effects: catalog sync, order creation, checkout, payment, receipts, messaging, scheduling, escalation, and refunds.

If a plugin is granted E-Commerce bridge permissions for a WhatsApp number instance, raw platform commerce_* tools are hidden from that AI agent for the same instance. The agent should use the plugin's domain tools, and the plugin should use the E-Commerce bridge for durable order persistence.

Recommended pattern:

  1. Declare plugin-owned permissions for your own domain actions.
  2. Declare platform bridge permissions for platform-owned side effects.
  3. Make your domain plugin tools agent-facing.
  4. Use bridge calls for dependency-only platform actions.
  5. Keep payment and order state transitions idempotent and bridge-backed.

Example: a delivery plugin that should only create delivery jobs for paid orders.

json
{
  "permissions": [
    {
      "key": "delivery:jobs:create",
      "label": "Create delivery jobs",
      "description": "Allows delivery job creation after payment is confirmed."
    }
  ],
  "tools": [
    {
      "name": "create_delivery_job",
      "description": "Create a delivery job for a paid order. Use this only after the Payments or E-Commerce order status confirms that the order is paid.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "orderNumber": {
            "type": "string",
            "description": "Paid customer order number."
          },
          "deliveryAddress": {
            "type": "string",
            "description": "Customer delivery address."
          }
        },
        "required": ["orderNumber", "deliveryAddress"]
      }
    }
  ]
}

The merchant grants the plugin to the WhatsApp number instance and approves the plugin permissions. Platform bridge permissions are enforced by KasiLabs when your plugin calls a bridge.

Plugins that need Payments

Plugins cannot bypass Payments permissions. If your plugin workflow collects or verifies money, request a bridge permission such as plugin:payments:initiate:current_chat or plugin:payments:status:own.

For customer-initiated WhatsApp flows, prefer current_chat. The plugin receives a short-lived current-chat token when the agent calls the plugin tool, and sends that token to the payment bridge. The plugin should not ask for or accept a typed payer phone number unless it has a separate external-recipient permission.

Example tool description:

text
Create an external invoice record after payment succeeds. Use this only when the payment status is successful and a payment reference is available. Do not use this to request payment or verify payment.

The bridge-backed flow should be:

  1. The agent calls your plugin's domain tool.
  2. Your plugin calls the Payments bridge with the current-chat token.
  3. The platform creates the payment request using the active provider.
  4. When payment succeeds, the platform sends a payment event back to your plugin if you configured an event tool.
  5. The platform generates the standard receipt PDF and sends one WhatsApp document message with the receipt summary as the caption.

Plugins that need Scheduling

Plugins should not secretly schedule platform messages. If the workflow needs reminders, request plugin:messages:schedule:<scope> and use the scheduling bridge.

Example tool description:

text
Create an appointment record and return the appointment time. If the customer also needs a reminder, use the Scheduling toolkit after this tool returns a confirmed appointment.

The bridge-backed flow should be:

  1. Call your plugin to book the appointment.
  2. Your plugin uses the Scheduling bridge to create the reminder.
  3. The customer receives the confirmation from the agent or from the bridge, depending on the workflow.

Plugins that need E-Commerce

If your plugin depends on order state, request E-Commerce bridge permissions. Use plugin:ecommerce:catalog:sync to let merchants import your plugin's products or services into the platform catalog, then use plugin:ecommerce:orders:create:<scope> to create durable orders from those synced items.

For delivery flows, preserve the customer address exactly. If the customer says Beth House, Kasarani, House 16, send that full string as the delivery address. Do not normalize it to only the neighborhood.

Example:

text
Send a paid order to the warehouse system. Use this only after the platform order/payment event shows the order is paid and ready for fulfillment.

Plugins that need platform bridges

If your plugin needs KasiLabs to act outside the immediate agent conversation, use a documented platform bridge. Bridges are narrow, permission-gated endpoints for specific platform-owned actions.

Current bridge families:

Bridge familyUse it for
PaymentsInitiate payment, check payment status, request refunds
E-CommerceCreate durable orders, read orders, create after-sale requests
MessagingSend or schedule text messages
EscalationsCreate or assign human escalations
ObligationsRequest reminders or escalations for external obligations

Declare the bridge permissions your plugin needs:

json
{
  "permissions": [
    {
      "key": "plugin:payments:initiate:current_chat",
      "label": "Request payment from the current customer",
      "description": "Allows this plugin to ask KasiLabs to create payment requests for the customer currently chatting with the granted WhatsApp number instance."
    },
    {
      "key": "plugin:ecommerce:orders:create:current_chat",
      "label": "Create orders for the current customer",
      "description": "Allows this plugin to create durable orders for the customer currently chatting with the granted WhatsApp number instance."
    },
    {
      "key": "plugin:ecommerce:checkout:initiate",
      "label": "Start commerce checkout",
      "description": "Allows this plugin to start checkout for an order through KasiLabs payments."
    },
    {
      "key": "plugin:obligations:request",
      "label": "Request obligation reminders",
      "description": "Allows this plugin to request reminder or escalation processing for obligations it owns."
    },
    {
      "key": "plugin:messages:send:current_chat",
      "label": "Send current-customer messages",
      "description": "Allows this plugin to send text messages to the customer currently chatting with the WhatsApp number instance."
    },
    {
      "key": "plugin:messages:schedule:current_chat",
      "label": "Schedule current-customer messages",
      "description": "Allows this plugin to schedule text messages to the customer currently chatting with the WhatsApp number instance."
    }
  ]
}

Add only the platform permissions the plugin actually needs. See Plugin Permissions for the complete permission list.

Add only the scope the plugin needs. For example, use plugin:messages:send:known_contact if the plugin can message existing chats outside the current conversation, and plugin:messages:send:external_recipient only if it must target brand-new recipients. Use plugin:payments:refund:execute:own for refunds limited to payments created by this plugin, and plugin:payments:refund:execute:any only for broader finance workflows.

These are platform bridge permissions, not your external system permissions. They must be granted on the plugin's WhatsApp number instance grant before the bridge request will work.

You can also expose obligation tools that KasiLabs polls periodically.

json
{
  "tools": [
    {
      "name": "list_due_obligations",
      "description": "List due or overdue obligations that need reminder or escalation handling.",
      "metadata": {
        "capability": "obligations.list_due"
      },
      "inputSchema": {
        "type": "object",
        "properties": {
          "now": { "type": "number" },
          "limit": { "type": "number" }
        }
      }
    },
    {
      "name": "record_obligation_event",
      "description": "Record the result of a reminder or escalation handled by KasiLabs.",
      "metadata": {
        "capability": "obligations.record_event"
      },
      "inputSchema": {
        "type": "object",
        "properties": {
          "obligationId": { "type": "string" },
          "eventType": { "type": "string" },
          "occurredAt": { "type": "number" }
        },
        "required": ["obligationId", "eventType"]
      }
    }
  ]
}

The obligations.list_due tool lets KasiLabs ask your plugin for due work. The optional obligations.record_event tool lets KasiLabs report whether a reminder or escalation was sent, blocked, or failed.

Polling does not bypass permissions. The WhatsApp number instance grant still needs message and recipient permissions before KasiLabs sends anything.

Tool fields

FieldRequiredDescription
nameYesUnique tool name within the plugin
descriptionYesClear instruction telling the agent when to use the tool
inputSchemaYesJSON Schema for tool input
outputSchemaNoExpected response shape
endpoint.methodNoHTTP method, normally POST
endpoint.pathNoPath appended to baseUrl; defaults to /execute
metadataNoExtra plugin-owned metadata

Writing strong tool descriptions

The description is the most important part of tool authoring. It should answer:

  • What does this tool do?
  • When should the agent call it?
  • What customer wording should trigger it?
  • What should the agent not use it for?

Good:

text
Create a delivery booking for a paid order. Use this only after the order is confirmed paid and the customer has provided a delivery address.

Weak:

text
Book delivery.

Do not expose internal implementation details in the description. Write for the agent and the business process.

Input schemas

Use strict inputs. The more specific the schema, the less likely the agent is to send incomplete data.

Recommended:

  • Use required for fields your endpoint cannot operate without.
  • Add descriptions for every field.
  • Use enums for controlled choices.
  • Prefer customer-facing references such as order number, ticket ID, or booking ID.
  • Avoid asking the agent to invent values your system should generate.

Example:

json
{
  "type": "object",
  "properties": {
    "orderNumber": {
      "type": "string",
      "description": "Customer-facing order number."
    },
    "priority": {
      "type": "string",
      "enum": ["low", "normal", "high"]
    }
  },
  "required": ["orderNumber"]
}

Output schemas

Output schemas help document what your endpoint returns. The agent can still work with normal JSON, but consistent output improves reliability.

Return:

  • Status.
  • Customer-safe message.
  • External reference IDs.
  • Next action where helpful.

Avoid:

  • Raw logs.
  • Secrets.
  • Stack traces.
  • Large unrelated payloads.
  • Internal-only configuration.

Configuration schema

Use configurationSchema when each installing organization needs its own setup.

Examples:

  • Workspace ID.
  • Default support queue.
  • Store branch.
  • Region.
  • API key.
  • Default delivery zone.

Example:

json
{
  "configurationSchema": {
    "type": "object",
    "properties": {
      "defaultQueue": {
        "type": "string",
        "description": "Default queue for new customer tickets."
      },
      "region": {
        "type": "string",
        "enum": ["ke", "ug", "tz"]
      }
    },
    "required": ["defaultQueue"]
  }
}

Configuration values are included in the tool call context. Treat them as sensitive where appropriate.

Authentication modes

No delegated account access

Use this when your plugin only needs the installation secret and configuration.

json
{
  "auth": {
    "type": "secret"
  }
}

Your endpoint should verify the signed platform token on every request.

No plugin auth

Use only for harmless demos.

json
{
  "auth": {
    "type": "none"
  }
}

Even then, you should still inspect and verify incoming requests before taking action.

Delegated account access

Use delegated access when the customer or organization must connect an external account.

json
{
  "auth": {
    "type": "oauth2",
    "authorizationUrl": "https://provider.example.com/authorize",
    "tokenUrl": "https://provider.example.com/token",
    "scope": ["read:tickets", "write:tickets"]
  }
}

The platform handles the authorization flow and includes the resulting access token in tool calls after authorization succeeds.

Request format

Tool calls are sent to:

text
{baseUrl}{endpoint.path}

Default:

text
{baseUrl}/execute

Headers include:

  • Authorization with a signed platform token.
  • Content-Type: application/json.
  • Optional user authorization header when delegated access is configured.

Body:

json
{
  "tool": "lookup_delivery",
  "input": {
    "orderNumber": "MAT-2026-0510-0041"
  },
  "context": {
    "organizationId": "org_123",
    "instanceId": "inst_456",
    "user": {
      "id": "customer_hash",
      "hashVersion": 1
    },
    "config": {
      "defaultQueue": "support"
    }
  }
}

Response format

Return JSON.

json
{
  "status": "out_for_delivery",
  "eta": "Today between 3:00 PM and 5:00 PM",
  "message": "The order is out for delivery."
}

For errors, use clear, safe messages:

json
{
  "error": "not_found",
  "message": "No delivery was found for that order number."
}

Permissions and sensitive tools

Manifest tools can create real business side effects. Mark and design them carefully.

Sensitive examples:

  • Create payout.
  • Issue refund.
  • Cancel order.
  • Mark delivered.
  • Update invoice.
  • Delete customer data.

For sensitive tools:

  • Use narrow descriptions.
  • Require references such as paid order number or approved request ID.
  • Validate business state inside your endpoint.
  • Return refusal messages when policy is not met.
  • Prefer dashboard approval for money movement.

Next steps