This guide shows you how to add custom tools to your agents using SubagentNode. We’ll build a lead collection agent as an example.

Overview

Kapso agents can be extended with custom tools:
  • App integrations - OAuth-based connections to popular apps (Google, Slack, etc.)
  • Functions - Serverless JavaScript functions for custom logic
  • Webhook tools - Direct HTTP calls to any API
You can build agents entirely through the web interface or programmatically using the CLI.

What we’re building

We’ll create a Lead Collection Agent that can:
  • Capture lead information through natural conversation
  • Send notifications to your Slack channel
  • Store lead data in Google Sheets for tracking
Example conversation:
User: "I'm interested in learning more about your product"
Agent: "Great! I'd be happy to help. Could you share your name and 
       company?"
User: "I'm Sarah from TechCorp"
Agent: "Thanks Sarah! What's the best email to reach you at?"
User: "sarah@techcorp.com"
Agent: "Perfect! I've recorded your information and our team will 
       reach out soon."

How it works

The agent uses:
  1. App Integrations: Connections to Slack and Google Sheets
  2. Function: Orchestrates both integrations into a single tool
  3. SubagentNode: Handles the conversation and calls the function

Prerequisites

  • A Kapso project
  • A Slack workspace
  • A Google account with Google Sheets

Method 1: Using the Web Interface

This method requires no coding - everything is configured through the Kapso web app.

Step 1: Enable the App integrations addon

  1. Go to Project Settings → Billing
  2. In the Addons section, toggle on App integrations
  3. Click Save

Step 2: Connect app integrations

We’ll need two integrations:

Integration 1: Google Sheets - Add Row

  1. Navigate to Code & integrations → App integrations
  2. Click Configure New Action
  3. Search for “Google Sheets” and select it
  4. Choose the Add Single Row action
  5. Click Connect Account and authorize your Google account
  6. Configure the action:
    • Name: “Save Lead to Sheet”
    • Drive: Select your Google Drive
    • Spreadsheet: Select or create a spreadsheet for leads
    • Worksheet Name: Sheet1 (or your preferred sheet) Map the columns to variables:
    • Name: {{name}}
    • Email: {{email}}
    • Company: {{company}}
    • Timestamp: {{timestamp}}
    • Source: {{source}}
    Variables explained: The {{variableName}} syntax creates placeholders that your agent will fill in. When the agent calls this integration with {name: "Sarah", email: "sarah@techcorp.com"}, those values replace the variables.
  7. Click Save
  8. Note the Integration ID (shown at the top of the page)

Integration 2: Slack - Send Message

  1. Click Configure New Action again
  2. Search for “Slack” → Send Message to a Public Channel action
  3. Click Connect Account and authorize your Slack workspace
  4. Configure the action:
    • Name: “Notify Sales Team”
    • Channel: Select your sales/leads channel
    • Message Text:
    🎉 New Lead!
    Name: {{name}}
    Company: {{company}}
    Email: {{email}}
    Source: {{source}}
    
  5. Click Save
  6. Note this Integration ID too

Step 3: Create a function to orchestrate both integrations

This function will handle both saving to Google Sheets and notifying Slack in a single call.
  1. Navigate to Code & integrations → Functions
  2. Click Create Function
  3. Name it capture-lead
  4. Add this code:
async function handler(request, env) {
  // Get lead data from the agent
  const { name, email, company } = await request.json();
  
  // Add timestamp and source
  const leadData = {
    name,
    email,
    company,
    timestamp: new Date().toISOString(),
    source: "Website Chat"
  };
  
  try {
    // Save to Google Sheets
    const sheetsResponse = await fetch(`https://app.kapso.ai/api/v1/integrations/${env.SHEETS_INTEGRATION_ID}/invoke`, {
      method: 'POST',
      headers: {
        'X-API-Key': env.KAPSO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(leadData)
    });
    
    if (!sheetsResponse.ok) {
      throw new Error('Failed to save to Google Sheets');
    }
    
    // Notify Slack
    const slackResponse = await fetch(`https://app.kapso.ai/api/v1/integrations/${env.SLACK_INTEGRATION_ID}/invoke`, {
      method: 'POST',
      headers: {
        'X-API-Key': env.KAPSO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: leadData.name,
        company: leadData.company,
        email: leadData.email,
        source: leadData.source
      })
    });
    
    if (!slackResponse.ok) {
      throw new Error('Failed to notify Slack');
    }
    
    return new Response(JSON.stringify({
      success: true,
      message: `Lead ${name} from ${company} has been captured and the team has been notified.`
    }), {
      headers: { 'Content-Type': 'application/json' }
    });
    
  } catch (error) {
    return new Response(JSON.stringify({
      success: false,
      message: `Error capturing lead: ${error.message}`
    }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' }
    });
  }
}
  1. Click SettingsEnvironment Variables and add:
    • SHEETS_INTEGRATION_ID = your Google Sheets integration ID
    • SLACK_INTEGRATION_ID = your Slack integration ID
  2. Click Save and Deploy
  3. Note the Function ID (e.g., fn_capture123)

Step 4: Create an agent with SubagentNode

Now we’ll create an agent that uses the function as a single webhook tool.
  1. Navigate to Agents & Flows → Agents
  2. Click Create Agent
  3. Name it “Lead Collector”
  4. In the canvas, add a SubagentNode:
    • Name: lead_collector
    • Prompt:
    You are a friendly lead collection assistant. Help capture visitor information through natural conversation.
    
    Your capability:
    - capture_lead: Saves lead to Google Sheets AND notifies the team via Slack in one call
    
    Workflow:
    1. Greet visitors warmly and ask how you can help
    2. If they express interest, collect:
       - Name
       - Company
       - Email
       - Their specific needs/interests
    3. Use capture_lead tool with the collected information
    4. Thank them and set expectations for follow-up
    
    Keep responses conversational and friendly.
    Always get explicit consent before collecting information.
    Only call capture_lead once you have name, email, and company.
    

Step 5: Add webhook tool to the SubagentNode

  1. Click on the SubagentNode to edit it
  2. In the Tools section, click Add Tool
  3. Select Webhook Tool and configure:
    • Name: capture_lead
    • URL: https://app.kapso.ai/api/v1/functions/YOUR_FUNCTION_ID/invoke (Replace with your function ID from Step 3)
    • Method: POST
    • Headers:
    {
      "X-API-Key": "#{KAPSO_API_KEY}"
    }
    
    • Body Schema:
    {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Lead's full name"
        },
        "email": {
          "type": "string",
          "description": "Lead's email address"
        },
        "company": {
          "type": "string",
          "description": "Lead's company name"
        }
      },
      "required": ["name", "email", "company"]
    }
    
    • Description: “Capture lead by saving to Google Sheets and notifying Slack”

Step 6: Connect nodes and test

  1. Connect the nodes: Startlead_collectorEnd
  2. Click Save
  3. Click Test to try your agent
  4. Example conversations to test:
    • “I’m interested in your product”
    • “Can you tell me more about your services?”
    • “I’d like to schedule a demo”

Step 7: Deploy and integrate

Once testing is complete:
  1. Click Deploy in the agent editor
  2. Integrate with your website chat widget or messaging platform
  3. Your lead collection agent is now live!

Method 2: Using CLI and Builder SDK

This method gives you full programmatic control over your agent.

Step 1: Set up your environment

# Install Kapso CLI
pip install kapso

# Authenticate
kapso login

# Initialize a new project
kapso init lead-collector
cd lead-collector

Step 2: Enable addon and connect app integrations

Even when using the CLI, app integrations must be configured through the web interface:
  1. Go to app.kapso.aiProject Settings → Billing
  2. Enable App integrations addon
  3. Navigate to Code & integrations → App integrations
  4. Configure Google Sheets and Slack integrations as described in Method 1
  5. Note both Integration IDs

Step 3: Create and deploy the function

Create functions/capture-lead.js:
async function handler(request, env) {
  const { name, email, company } = await request.json();
  
  const leadData = {
    name,
    email,
    company,
    timestamp: new Date().toISOString(),
    source: "Website Chat"
  };
  
  try {
    // Save to Google Sheets
    const sheetsResponse = await fetch(`https://app.kapso.ai/api/v1/integrations/${env.SHEETS_INTEGRATION_ID}/invoke`, {
      method: 'POST',
      headers: {
        'X-API-Key': env.KAPSO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(leadData)
    });
    
    if (!sheetsResponse.ok) {
      throw new Error('Failed to save to Google Sheets');
    }
    
    // Notify Slack
    const slackResponse = await fetch(`https://app.kapso.ai/api/v1/integrations/${env.SLACK_INTEGRATION_ID}/invoke`, {
      method: 'POST',
      headers: {
        'X-API-Key': env.KAPSO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: leadData.name,
        company: leadData.company,
        email: leadData.email,
        source: leadData.source
      })
    });
    
    if (!slackResponse.ok) {
      throw new Error('Failed to notify Slack');
    }
    
    return new Response(JSON.stringify({
      success: true,
      message: `Lead ${name} from ${company} has been captured and the team has been notified.`
    }), {
      headers: { 'Content-Type': 'application/json' }
    });
    
  } catch (error) {
    return new Response(JSON.stringify({
      success: false,
      message: `Error capturing lead: ${error.message}`
    }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' }
    });
  }
}
Deploy it:
# Deploy with environment variables
kapso functions push functions/capture-lead.js \
  --env SHEETS_INTEGRATION_ID=YOUR_SHEETS_ID \
  --env SLACK_INTEGRATION_ID=YOUR_SLACK_ID

# Note the Function ID from the output

Step 4: Build the agent

Create agent.py:
from kapso.builder import Agent
from kapso.builder.nodes import SubagentNode
from kapso.builder.nodes.subagent import WebhookTool
from kapso.builder.agent.constants import START_NODE, END_NODE

# Replace with your function ID from Step 3
CAPTURE_LEAD_FUNCTION_ID = "fn_capture123"

# Create the agent
agent = Agent(
    name="lead_collector",
    system_prompt="You are a friendly lead collection assistant"
)

# Create SubagentNode
lead_collector = SubagentNode(
    name="lead_collector",
    prompt="""You are a friendly lead collection assistant. Help capture visitor information through natural conversation.
    
    Your capability:
    - capture_lead: Saves lead to Google Sheets AND notifies the team via Slack in one call
    
    Workflow:
    1. Greet visitors warmly and ask how you can help
    2. If they express interest, collect:
       - Name
       - Company
       - Email
       - Their specific needs/interests
    3. Use capture_lead tool with the collected information
    4. Thank them and set expectations for follow-up
    
    Keep responses conversational and friendly.
    Always get explicit consent before collecting information.
    Only call capture_lead once you have name, email, and company."""
)

# Add webhook tool for capturing leads
lead_collector.add_tool(WebhookTool(
    name="capture_lead",
    url=f"https://app.kapso.ai/api/v1/functions/{CAPTURE_LEAD_FUNCTION_ID}/invoke",
    http_method="POST",
    description="Capture lead by saving to Google Sheets and notifying Slack",
    headers={"X-API-Key": "#{KAPSO_API_KEY}"},
    body_schema={
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "description": "Lead's full name"
            },
            "email": {
                "type": "string",
                "description": "Lead's email address"
            },
            "company": {
                "type": "string",
                "description": "Lead's company name"
            }
        },
        "required": ["name", "email", "company"]
    }
))

# Build the graph
agent.add_node(START_NODE)
agent.add_node(lead_collector)
agent.add_node(END_NODE)

agent.add_edge(START_NODE, "lead_collector")
agent.add_edge("lead_collector", END_NODE)

# Validate the agent
agent.validate()

Step 5: Test locally

# Test in cloud with visual debugger
kapso run --cloud

Step 6: Deploy to production

kapso deploy

Key Takeaways

This example demonstrates how functions can orchestrate multiple app integrations:
  1. Single tool for the agent: Instead of giving the agent two separate tools, we created one function that handles both operations
  2. Error handling: The function can handle failures gracefully and provide meaningful error messages
  3. Data transformation: The function adds timestamp and source information automatically
  4. Simplified agent logic: The agent only needs to understand one tool instead of coordinating multiple calls
This pattern is especially useful when:
  • You need to perform multiple related actions together
  • You want to add business logic between API calls
  • You need to transform or enrich data before sending to integrations
  • You want to provide a simpler interface for your agents