kaman.ai

PricingTemplatesBlogPapersDocs

Documentation

Guides, use cases & API reference

  • Overview
    • Getting Started
    • Platform Overview
  • Features
    • Features Overview
    • AI Assistant
    • Workflow Automation
    • Intelligent Memory
    • Data Management
    • Universal Integrations
    • Communication Channels
    • Collective Agent Memory (CAML)
    • Security & Control
  • Use Cases Overview
  • Financial Services
  • Fraud Detection
  • Supply Chain
  • Technical Support
  • Software Development
  • Smart ETL
  • Data Governance
  • ESG Reporting
  • TAC Management
  • Reference
    • API Reference
  • Guides
    • Getting Started
    • Authentication
  • Endpoints
    • Workflows API
    • Tools API
    • KDL (Data Lake) API
    • OpenAI-Compatible API
    • A2A Protocol
    • Skills API
    • Knowledge Base (RAG) API
    • Communication Channels
    • DSL Import API
Release Notes

DSL Import API

The DSL Import API lets you programmatically create complete agents, tools, knowledge bases, and data lake structures from a single JSON definition. Instead of manually creating each resource through the UI, you define everything in one DSL file and import it in a single API call.

Base URL

POST /api/dsl/import

For self-hosted installations: https://kaman.in/api/dsl/import

Authentication

The endpoint supports two authentication methods:

MethodHeaderUse Case
Cookie authCookie: kaman_access_token=...Browser / logged-in user
Service headersx-client-id + x-user-idService-to-service calls

For KDL (data lake) creation and file uploads, also include a Bearer token:

Authorization: Bearer <your_token>

Content Types

The endpoint accepts two content types:

Content-TypeUse Case
application/jsonDSL JSON body only (no file uploads)
multipart/form-dataDSL JSON + file attachments for KB documents

Multipart Upload

To upload files alongside the DSL, send multipart/form-data with:

  • A dsl field containing the JSON definition
  • One or more file fields with the actual files

KB documents reference attachments by filename:

json
{
  "knowledgeBase": {
    "name": "My KB",
    "documents": [
      { "type": "file", "name": "User Guide", "attachment": "guide.pdf" },
      { "type": "file", "name": "Remote Doc", "fileUrl": "https://example.com/doc.pdf" }
    ]
  }
}
bash
curl -X POST "https://kaman.in/api/dsl/import" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "x-client-id: 1" \
  -H "x-user-id: 1" \
  -F "dsl=<my-agent.json" \
  -F "files=@guide.pdf;filename=guide.pdf"

The importer uploads attached files to storage and resolves URLs automatically. For fileUrl documents, kaman-agent downloads and processes the file on its end.

Quick Start

1. Create a DSL file

json
{
  "tools": [
    {
      "name": "My Tool",
      "description": "Does something useful",
      "functions": [
        {
          "name": "doSomething",
          "description": "Performs the operation and returns the result",
          "inputFields": {
            "query": {
              "type": "string",
              "description": "What to look up",
              "required": true
            }
          },
          "outputFields": {
            "result": { "type": "string", "description": "The result" }
          },
          "callCode": "return { result: 'Hello ' + data.query };"
        }
      ]
    }
  ],
  "agent": {
    "name": "My Agent",
    "description": "A helpful assistant with custom tools",
    "options": [
      {
        "systemPrompt": "You are a helpful assistant. Use the doSomething tool when asked.",
        "model": "gpt-4",
        "tools": [{ "ref": "My Tool" }],
        "faqs": ["What can you do?"]
      }
    ]
  }
}

2. Import it

bash
curl -X POST "https://kaman.in/api/dsl/import" \
  -H "Content-Type: application/json" \
  -H "x-client-id: YOUR_ORG_ID" \
  -H "x-user-id: YOUR_USER_ID" \
  -d @my-agent.json

3. Check the response

json
{
  "imported": 2,
  "updated": 0,
  "skipped": 0,
  "errors": 0,
  "details": [
    { "name": "My Tool", "type": "tool", "status": "imported", "pluginId": 142 },
    { "name": "My Agent", "type": "agent", "status": "imported", "pluginId": 143 }
  ]
}

Your agent and tool are now live and accessible in the platform.

DSL Structure

A DSL file is a JSON object with up to four top-level blocks. At least one must be present:

BlockPurposeCreates
kdlData lake structureLakes, schemas, tables, seed data (via KDL API)
toolsTool/function definitionsPlugin records (type=tool) with functions
knowledgeBaseRAG knowledge basePlugin record (type=kb) with documents
agentAgent configurationPlugin record (type=app) with full config

Resources are imported in dependency order: KDL -> Tools -> Knowledge Base -> Agent. The agent can reference tools and KBs defined in the same file using ref.


Tools Block

An array of tool definitions. Each tool becomes a plugin with one or more callable functions.

json
{
  "tools": [
    {
      "name": "Weather Lookup",
      "description": "Looks up current weather for any city",
      "version": "1.0.0",
      "category": "Utilities",
      "functions": [
        {
          "name": "getWeather",
          "description": "Gets current weather for a city. Returns temperature, conditions, humidity.",
          "inputFields": {
            "city": {
              "type": "string",
              "description": "City name (e.g., 'London', 'Tokyo')",
              "required": true
            },
            "units": {
              "type": "string",
              "description": "Temperature units: 'celsius' or 'fahrenheit'",
              "required": false,
              "default": "celsius"
            }
          },
          "outputFields": {
            "temperature": { "type": "number", "description": "Current temperature" },
            "conditions": { "type": "string", "description": "Weather conditions" }
          },
          "callCode": "const resp = await axios.get(`https://api.weather.example/${data.city}`); return resp.data;",
          "sync": true
        }
      ]
    }
  ]
}

Function Definition

FieldTypeRequiredDescription
namestringYesFunction name in camelCase (e.g., getWeather, sendEmail)
descriptionstringYesWhat it does and returns. The LLM reads this to decide when to use the tool.
callCodestringOne ofInline JavaScript. Available vars: data, axios, _ (lodash), crypto, f, config
urlstringOne ofHTTP endpoint to call instead of callCode
inputFieldsobjectNoParameters the LLM provides at runtime (become the Zod schema)
userFieldsobjectNoCredentials/config the user stores once (NOT visible to LLM)
outputFieldsobjectNoWhat the function returns (documentation only)
syncbooleanNoWhen true, results are cached for identical inputs

Field Types

Fields in inputFields, userFields, and outputFields use the same format:

json
{
  "<fieldName>": {
    "type": "string | number | boolean | object | array | date | file | binary",
    "description": "Human-readable description",
    "required": true,
    "default": "optional default value",
    "innerFields": { }
  }
}

Important: inputFields are what the LLM fills in at runtime. userFields are credentials or configuration that the user sets up once (API keys, passwords, tokens) — these are never exposed to the LLM.

Credentials & User Fields

Tools that need API keys or authentication should use userFields, not inputFields:

json
{
  "functions": [
    {
      "name": "searchCRM",
      "description": "Searches the CRM for contacts",
      "inputFields": {
        "query": { "type": "string", "description": "Search query", "required": true }
      },
      "userFields": {
        "apiKey": {
          "type": "string",
          "description": "Your CRM API key",
          "required": true,
          "config": { "type": "apikey" }
        }
      },
      "callCode": "const resp = await axios.get('https://crm.example/api/search', { params: { q: data.query }, headers: { 'X-API-Key': data.apiKey } }); return resp.data;"
    }
  ]
}

Triggers

Tools can also define event triggers:

json
{
  "triggers": [
    {
      "name": "onNewLead",
      "description": "Fires when a new lead is created",
      "outputFields": {
        "leadId": { "type": "string", "description": "New lead ID" }
      },
      "registrationCallCode": "return axios.post('https://crm.example/webhooks', { url: f.url });",
      "checkCallCode": "return axios.get('https://crm.example/webhooks/status');",
      "checkInterval": 60000
    }
  ]
}

Knowledge Base Block

A single knowledge base definition with documents for RAG (retrieval-augmented generation).

json
{
  "knowledgeBase": {
    "name": "Product Documentation",
    "description": "Product guides and FAQ content",
    "documents": [
      {
        "type": "file",
        "name": "User Guide",
        "fileUrl": "https://storage.example.com/docs/user-guide.pdf",
        "mimeType": "application/pdf"
      },
      {
        "type": "text",
        "name": "FAQ Content",
        "content": "# Frequently Asked Questions\n\n## How do I reset my password?\nGo to Settings > Security > Reset Password...",
        "metadata": { "category": "faq", "last_updated": "2026-03-01" }
      }
    ]
  }
}

Document Types

TypeRequired FieldsDescription
filefileId, fileUrl, or attachmentReference to a file. Automatically parsed and embedded.
textcontentInline text content. Note: text documents are stored but may require file upload for full embedding support.

File Document Sources

There are three ways to provide files for KB documents:

1. Direct attachment (multipart upload) — best for local files:

json
{ "type": "file", "name": "Guide", "attachment": "guide.pdf" }

Include the actual file in the multipart form data. The importer uploads it to storage and resolves the fileId automatically.

2. URL reference — best for files hosted online:

json
{ "type": "file", "name": "Guide", "fileUrl": "https://example.com/guide.pdf" }

The platform downloads the file and processes it during KB creation.

3. Pre-existing fileId — for files already in platform storage:

json
{ "type": "file", "name": "Guide", "fileId": "s3://bucket/org/hash.pdf" }

Agent Block

The complete agent configuration including system prompt, model, tool bindings, and settings.

json
{
  "agent": {
    "name": "Sales Assistant",
    "description": "Helps sales teams with CRM lookups and email drafting",
    "slug": "sales-assistant",
    "category": "Sales",
    "version": "1.0.0",

    "options": [
      {
        "name": "default",
        "systemPrompt": "You are a sales assistant. Help users look up contacts and draft emails.",
        "model": "gpt-4",

        "tools": [
          { "ref": "CRM Tool" },
          { "ref": "Email Tool" }
        ],

        "knowledgeBases": [
          { "ref": "Sales Playbook" }
        ],

        "datasources": [
          { "ref": "sales_lake.crm.deals" }
        ],

        "faqs": [
          "Look up contact info for Acme Corp",
          "Draft a follow-up email",
          "Show me this quarter's deals"
        ],

        "settings": {
          "maxIterations": 10,
          "toolCallTimeout": 15000,
          "toolCallRetries": 2,
          "llmThinkingMode": "quick"
        }
      }
    ],

    "pricing": {
      "model": "free"
    }
  }
}

Agent Options

Each agent has at least one options entry (persona). Most agents have one.

FieldTypeRequiredDescription
systemPromptstringYesThe main instruction prompt for the LLM
modelstringNoLLM model ID (default: gpt-4). Examples: gpt-4, claude-sonnet-4-5-20250514
toolsarrayNoTool references (see below)
knowledgeBasesarrayNoKB references
datasourcesarrayNoKDL data source references
faqsstring[]NoQuick-prompt suggestions shown to users
settingsobjectNoExecution settings (timeouts, retries, etc.)

Tool References

Tools in agent options can reference resources three ways:

json
{ "ref": "My Tool" }

References a tool defined in the same DSL file by name.

json
{ "id": 42 }

References an existing tool in the platform by ID.

json
{ "name": "existingToolFunction" }

References an existing function by name.

Datasource References

json
{ "ref": "my_lake.analytics.deals" }

References a KDL table defined in the same DSL file (lakeName.schema.table format).

json
{ "lakeName": "my_lake", "schemaName": "analytics", "tableName": "deals" }

Explicit KDL coordinates for an existing data source.

Knowledge Base References

json
{ "ref": "My KB Name" }

References a knowledge base defined in the same DSL file.

json
{ "id": "123" }

References an existing knowledge base by ID.


KDL Block

Creates data lake structures: lakes, schemas, tables with column definitions, and optional seed data.

json
{
  "kdl": {
    "lakeName": "analytics_lake",
    "description": "Company analytics data",
    "schemas": [
      {
        "name": "sales",
        "tables": [
          {
            "name": "deals",
            "description": "Sales deal pipeline",
            "columns": {
              "id": { "type": "INTEGER", "primaryKey": true, "autoIncrement": true },
              "company": { "type": "VARCHAR(255)" },
              "amount": { "type": "DOUBLE" },
              "stage": { "type": "VARCHAR(50)" },
              "created_at": { "type": "TIMESTAMP", "default": "CURRENT_TIMESTAMP" }
            },
            "seedData": {
              "rows": [
                { "company": "Acme Corp", "amount": 50000, "stage": "negotiation" },
                { "company": "Globex Inc", "amount": 120000, "stage": "closed_won" }
              ]
            }
          }
        ]
      }
    ]
  }
}

Column Types

Supported SQL types: VARCHAR, INTEGER, BIGINT, DOUBLE, FLOAT, BOOLEAN, TIMESTAMP, DATE, TEXT, JSON, JSONB, BLOB, BINARY. Size suffixes are supported (e.g., VARCHAR(255)).

Column Properties

PropertyTypeDefaultDescription
typestringrequiredSQL column type
primaryKeybooleanfalsePrimary key column
nullablebooleantrueAllow NULL values
uniquebooleanfalseUnique constraint
autoIncrementbooleanfalseAuto-incrementing
defaultany-Default value expression

Response Format

Success (200)

json
{
  "imported": 3,
  "updated": 0,
  "skipped": 0,
  "errors": 0,
  "details": [
    { "name": "Weather Lookup", "type": "tool", "status": "imported", "pluginId": 142 },
    { "name": "Weather Tips KB", "type": "kb", "status": "imported", "pluginId": 143 },
    { "name": "Weather Buddy", "type": "agent", "status": "imported", "pluginId": 144 }
  ]
}

Validation Error (400)

json
{
  "error": "DSL validation failed",
  "validationErrors": [
    { "path": "tools/0/functions/0", "message": "Must have property \"callCode\" or \"url\"" },
    { "path": "agent/options/0/systemPrompt", "message": "Must be a non-empty string" }
  ]
}

Partial Failure (207)

When some resources fail but others succeed:

json
{
  "imported": 1,
  "updated": 0,
  "skipped": 0,
  "errors": 1,
  "details": [
    { "name": "My Tool", "type": "tool", "status": "imported", "pluginId": 142 },
    { "name": "My Agent", "type": "agent", "status": "error", "error": "..." }
  ]
}

Status Values

StatusDescription
importedNew resource created successfully
updatedExisting resource updated (same name + type + org)
skippedResource already exists and didn't need changes (KDL only)
errorResource failed to import

Idempotency

The import is idempotent. Running the same DSL file twice will update existing resources on the second run instead of creating duplicates. Resources are matched by name + type within your organization — different organizations can have resources with the same name without conflict.

Code Examples

TypeScript

typescript
const BASE_URL = 'https://kaman.in';

async function importDsl(dsl: object, orgId: number, userId: number) {
  const response = await fetch(`${BASE_URL}/api/dsl/import`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-client-id': String(orgId),
      'x-user-id': String(userId),
    },
    body: JSON.stringify(dsl),
  });
  return response.json();
}

// Import from a file
const dsl = await import('./my-agent.json');
const result = await importDsl(dsl, 1, 1);
console.log(`Imported: ${result.imported}, Updated: ${result.updated}, Errors: ${result.errors}`);

Python

python
import requests
import json

BASE_URL = "https://kaman.in"

def import_dsl(dsl: dict, org_id: int, user_id: int) -> dict:
    response = requests.post(
        f"{BASE_URL}/api/dsl/import",
        json=dsl,
        headers={
            "Content-Type": "application/json",
            "x-client-id": str(org_id),
            "x-user-id": str(user_id),
        },
    )
    return response.json()

# Load and import
with open("my-agent.json") as f:
    dsl = json.load(f)

result = import_dsl(dsl, org_id=1, user_id=1)
print(f"Imported: {result['imported']}, Updated: {result['updated']}, Errors: {result['errors']}")

cURL

bash
# Import from a file
curl -X POST "https://kaman.in/api/dsl/import" \
  -H "Content-Type: application/json" \
  -H "x-client-id: 1" \
  -H "x-user-id: 1" \
  -d @my-agent.json

# Import inline JSON
curl -X POST "https://kaman.in/api/dsl/import" \
  -H "Content-Type: application/json" \
  -H "x-client-id: 1" \
  -H "x-user-id: 1" \
  -d '{
    "agent": {
      "name": "Quick Bot",
      "options": [{
        "systemPrompt": "You are a helpful assistant.",
        "model": "gpt-4"
      }]
    }
  }'

Error Handling

StatusErrorDescription
400Validation errorDSL JSON doesn't match the schema
401UnauthorizedMissing authentication (no cookie or x-client-id)
207Partial failureSome resources imported, some failed
500Server errorUnexpected internal error

Best Practices

  1. Start small: Import just a tool or just an agent first, then add more blocks
  2. Use ref for cross-references: When your DSL has both tools and an agent, use { "ref": "Tool Name" } to link them
  3. Test idempotency: Run your import twice to verify updates work correctly
  4. Include descriptions: Good descriptions on tools and functions help the LLM use them effectively
  5. Use userFields for secrets: Never put API keys in inputFields — use userFields instead so the LLM doesn't see credentials

Next Steps

  • Tools API - Search and execute individual tools
  • Knowledge Base API - Manage knowledge bases and RAG
  • KDL API - Query your data lake directly
  • Authentication - Learn about API authentication methods

On this page

  • Base URL
  • Authentication
  • Content Types
  • Multipart Upload
  • Quick Start
  • 1. Create a DSL file
  • 2. Import it
  • 3. Check the response
  • DSL Structure
  • Tools Block
  • Function Definition
  • Field Types
  • Credentials & User Fields
  • Triggers
  • Knowledge Base Block
  • Document Types
  • File Document Sources
  • Agent Block
  • Agent Options
  • Tool References
  • Datasource References
  • Knowledge Base References
  • KDL Block
  • Column Types
  • Column Properties
  • Response Format
  • Success (200)
  • Validation Error (400)
  • Partial Failure (207)
  • Status Values
  • Idempotency
  • Code Examples
  • TypeScript
  • Python
  • cURL
  • Error Handling
  • Best Practices
  • Next Steps