Developers

Manifest Reference

Complete specification for plugin manifest files.

Overview

The manifest is a JSON file that describes your plugin — its identity, tools, and authentication requirements. The platform reads this file to understand what your plugin does and how to interact with it.

Full manifest structure

json
{
  "slug": "MY_PLUGIN",
  "version": "1.0.0",
  "name": "My Plugin",
  "description": "What this plugin does",
  "author": {
    "name": "Your Name",
    "email": "you@example.com",
    "url": "https://yoursite.com"
  },
  "tags": ["crm", "sales"],
  "homepage": "https://yoursite.com/plugin",
  "baseUrl": "https://api.yourservice.com",
  "auth": { "type": "none" },
  "tools": [],
  "configurationSchema": {}
}

Fields

Required fields

FieldTypeDescription
slugstringUnique uppercase identifier for your plugin (e.g., ACME_CRM). Must be unique across all plugins.
versionstringSemantic version number (e.g., 1.0.0, 2.1.3).
namestringHuman-readable name shown in the UI.
baseUrlstringThe base URL of your plugin's HTTP endpoint. Tool calls are sent here.
toolsarrayList of tools your plugin provides. See below.
authobjectAuthentication configuration. See below.

Optional fields

FieldTypeDescription
descriptionstringBrief description of what the plugin does. Shown to users during installation.
authorobjectAuthor info: name, email, and url.
tagsstring[]Categories for discoverability (e.g., ["payments", "finance"]).
homepagestringLink to your plugin's documentation or website.
configurationSchemaobjectJSON Schema defining installation-time configuration options.

Tools

Each tool represents an action the AI agent can perform. Define them in the tools array.

json
{
  "name": "lookup_customer",
  "description": "Look up a customer by their phone number or email. Use this when the agent needs customer information.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "phone": {
        "type": "string",
        "description": "Customer phone number (with country code)"
      },
      "email": {
        "type": "string",
        "description": "Customer email address"
      }
    },
    "required": ["phone"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "name": { "type": "string" },
      "status": { "type": "string" }
    }
  },
  "endpoint": {
    "method": "POST",
    "path": "/execute"
  }
}

Tool fields

FieldTypeRequiredDescription
namestringYesUnique name for the tool within this plugin.
descriptionstringYesDescribes what the tool does and when to use it. The AI reads this to decide when to call the tool. Write it clearly.
inputSchemaobjectYesJSON Schema describing the input parameters. The AI uses this to know what data to send.
outputSchemaobjectNoJSON Schema describing the expected response format.
endpoint.methodstringNoHTTP method (POST or GET). Defaults to POST.
endpoint.pathstringNoURL path appended to baseUrl. Defaults to /execute.
metadataobjectNoArbitrary key-value metadata for your own use.

Writing good tool descriptions

The AI agent uses the description field to decide when to call your tool. Be specific:

Good: "Look up the shipping status of an order by its tracking number. Call this when a customer asks where their package is or wants a tracking update."

Bad: "Get shipping info."

The better your description, the more accurately the agent will use your tool.

Authentication types

No authentication

json
{ "type": "none" }

Your endpoint receives requests without any authentication. The platform still includes a signed platform token in the Authorization header that you can verify (see Authentication).

Secret (Platform Token)

json
{ "type": "secret" }

Every request includes a signed platform token in the Authorization header. Your endpoint should verify this token to confirm the request came from the platform.

OAuth 2.0

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

For plugins that need to access user accounts on external services. The platform handles the full OAuth flow — redirecting users to authorize, exchanging codes for tokens, and refreshing tokens automatically.

When your tool is called, the user's access token is included in the request context. See Authentication for the full OAuth flow.

Configuration schema

If your plugin needs configuration at install time (e.g., an API key, a workspace URL), define it with configurationSchema:

json
{
  "configurationSchema": {
    "type": "object",
    "properties": {
      "workspace_url": {
        "type": "string",
        "description": "Your workspace URL"
      },
      "api_key": {
        "type": "string",
        "description": "Your API key"
      }
    },
    "required": ["workspace_url"]
  }
}

When an organization installs your plugin, they'll be asked to fill in these configuration values. The values are included in the context.config object on every tool call.

Request format

When the agent calls one of your tools, the platform sends a POST request to your endpoint:

URL: {baseUrl}{tool.endpoint.path} (defaults to {baseUrl}/execute)

Headers:

  • Authorization: Bearer {platform_token} — Signed token for verification
  • Content-Type: application/json
  • X-User-Access-Token: {oauth_token} — Only present if OAuth is configured and the user has authorized

Body:

json
{
  "tool": "lookup_customer",
  "input": {
    "phone": "+254700000000"
  },
  "context": {
    "organizationId": "org_abc123",
    "instanceId": "inst_xyz789",
    "user": {
      "id": "hashed_identifier",
      "hashVersion": 1
    },
    "config": {
      "workspace_url": "https://myworkspace.example.com"
    },
    "userAccessToken": "eyJhbG..."
  }
}

Context fields

FieldDescription
organizationIdThe organization that installed your plugin
instanceIdThe specific WhatsApp instance making the call
user.idA hashed identifier for the WhatsApp user (never the actual phone number)
configConfiguration values set during plugin installation
userAccessTokenThe user's OAuth access token (only if OAuth is configured)

Response format

Return a JSON response with your result. The agent will use the data to continue the conversation.

json
{
  "name": "John Doe",
  "status": "active",
  "lastOrder": "2024-01-15"
}

There's no required structure — return whatever makes sense for your tool. The agent will interpret the response based on the tool's description and context.

For errors, return an appropriate HTTP status code and an error message:

json
{
  "error": "Customer not found"
}

Next steps