Add this to your .cursorrules or CLAUDE.md file.

## Quick Start
```bash
pip install kapso
kapso init                    # Create new project
kapso run                     # Test locally
kapso run --cloud             # Test in cloud (with visual debugger)
kapso deploy                  # Deploy to cloud
```

## Core Architecture Pattern (Recommended)
```python
from kapso.builder import Agent
from kapso.builder.nodes import SubagentNode, WarmEndNode, HandoffNode
from kapso.builder.nodes.subagent import WebhookTool, KnowledgeBaseTool
from kapso.builder.agent.constants import START_NODE, END_NODE

agent = Agent(name="my_agent", system_prompt="You are a helpful assistant")

# Main node: SubagentNode (preferred over individual nodes)
assistant = SubagentNode(
    name="assistant",
    prompt="Help users with available tools",
    global_=False,  # or True for global access
    global_condition="trigger condition if global"
)

# Add tools to SubagentNode
assistant.add_tool(WebhookTool(...))
assistant.add_tool(KnowledgeBaseTool(...))

# Global handoff
handoff = HandoffNode(
    name="human",
    global_=True,
    global_condition="if user requests human"
)

# Conversation end
end = WarmEndNode(
    name="end",
    timeout_minutes=30,
    prompt="Say goodbye message"
)

# Build graph
agent.add_node(START_NODE)
agent.add_node(assistant)
agent.add_node(handoff)
agent.add_node(end)
agent.add_node(END_NODE)

agent.add_edge(START_NODE, "assistant")
agent.add_edge("assistant", "end", condition="if conversation complete")
agent.add_edge("end", END_NODE)
```

## Node Types & Attributes

### DefaultNode
**Purpose**: Basic conversational node for simple interactions and routing
```python
DefaultNode(
    name="string",              # Required: alphanumeric + underscore
    prompt="string",            # Optional: instructions
    global_=False,              # Optional: global access
    global_condition="string"   # Required if global_=True
)
```
**Built-in tools**: send_notification_to_user, AskUserForInput, MoveToNextNode, EnterIdleState

### SubagentNode (Recommended)
**Purpose**: The preferred node type - combines multiple tools (webhooks, knowledge bases, WhatsApp, MCP) in one powerful node. Use this unless you need a very specific, tight control flow.
```python
SubagentNode(
    name="string",
    prompt="string",
    global_=False,
    global_condition="string"
)
```
**Built-in tools**: All DefaultNode tools + kb_retrieval, SendWhatsappTemplateMessage
**Add custom tools**: WebhookTool, KnowledgeBaseTool, McpServerTool, WhatsappTemplateTool

### WebhookNode
**Purpose**: Single API call node - use when you need tight control over one specific webhook
```python
WebhookNode(
    name="string",
    url="https://api.example.com/#{variable}",
    http_method="GET|POST|PUT|PATCH|DELETE",
    headers={"key": "value"},
    body_schema={...},          # JSON Schema validation
    jmespath_query="data[0]",   # Response filtering
    mock_response={...},        # Test data
    mock_response_enabled=True,
    prompt="string",
    global_=False,
    global_condition="string"
)
```
**Built-in tools**: All DefaultNode tools + webhook_request

### KnowledgeBaseNode
**Purpose**: Single knowledge base access - use when you need tight control over one specific KB
```python
KnowledgeBaseNode(
    name="string",
    key="unique_key",           # Required
    knowledge_base_text="...",  # Option 1: inline text
    knowledge_base_file="path", # Option 2: file path
    prompt="string",
    global_=False,
    global_condition="string"
)
```
**Built-in tools**: All DefaultNode tools + kb_retrieval

### HandoffNode
**Purpose**: Transfer conversation to human agent. Does NOT execute anything - just handoff and stop. Any messages to user must be in previous node.
```python
HandoffNode(
    name="string",
    global_=False,              # Usually True
    global_condition="string"
)
```
**Built-in tools**: None (forwards control)

### WarmEndNode
**Purpose**: End conversation with timeout - allows user to continue chatting within timeout window
```python
WarmEndNode(
    name="string",
    timeout_minutes=30,         # Keep conversation open
    prompt="string",
    global_=False,
    global_condition="string"
)
```
**Built-in tools**: send_notification_to_user, EnterIdleState, MoveToNextNode (no AskUserForInput)

### WhatsAppTemplateNode
**Purpose**: Send pre-approved WhatsApp template messages
```python
WhatsAppTemplateNode(
    name="string",
    template_name="string",
    phone_number="#{variable}",
    template_parameters={"1": "#{value}"},
    wait_for_response=False,
    whatsapp_config_id="string",
    whatsapp_template_id="string",
    prompt="string",
    global_=False,
    global_condition="string"
)
```
**Built-in tools**: All DefaultNode tools + SendWhatsappTemplateMessage

## SubagentNode Tools

### WebhookTool
```python
WebhookTool(
    name="api_call",
    url="https://api.example.com",
    http_method="POST",
    headers={"Authorization": "Bearer #{token}"},
    body_schema={...},
    jmespath_query="results[0]",
    mock_response={...},
    mock_response_enabled=True,
    description="Tool description"
)
```

### KnowledgeBaseTool
```python
# From text
KnowledgeBaseTool(
    name="kb",
    knowledge_base_text="Content...",
    description="Search knowledge"
)

# From file
KnowledgeBaseTool.from_file(
    name="kb",
    file_path="docs/manual.pdf",
    description="Search docs"
)
```

### McpServerTool
```python
McpServerTool(
    name="mcp",
    url="https://mcp.example.com",
    transport_kind="sse|streamable_http",
    jmespath_queries=[
        JmespathQuery(
            tool_name="calculator",
            jmespath_query="tools[?type=='math']"
        )
    ],
    description="MCP tools"
)
```

### WhatsappTemplateTool
```python
WhatsappTemplateTool(
    name="notify",
    template_name="order_update",
    phone_number="#{phone}",
    template_parameters={"1": "#{name}"},
    wait_for_response=True,
    whatsapp_config_id="config_123",
    whatsapp_template_id="template_456",
    description="Send WhatsApp"
)
```

## Graph Rules & Flow Control

### Essential Rules
1. **START_NODE and END_NODE must exist** in every agent
2. **Only ONE node can connect from START** - START → single_node
3. **Node prompts are LLM instructions**, not user-facing messages
4. **A node cannot connect to itself** - no self-loops
5. **Global nodes are NOT connected** - they're available everywhere and return to calling node
6. **HandoffNode stops execution** - put any user messages in previous node

### Edges & Flow
```python
# Simple edge
agent.add_edge("source", "target")

# Conditional edge
agent.add_edge("source", "target", condition="user says X")

# Special nodes
START_NODE  # Entry point (exactly one outgoing edge)
END_NODE    # Exit point (can have multiple incoming)

# Global nodes - no edges needed
global_node = DefaultNode(name="help", global_=True, global_condition="user asks for help")
# Automatically available from any node when condition is met
```

## CLI Commands
```bash
kapso init [--template basic|support|knowledge-base]
kapso login                   # Authenticate
kapso compile                 # Python → YAML
kapso run [--cloud] [--verbose]
kapso test ["Test Name"] [--verbose]
kapso deploy                  # Upload to cloud
kapso pull                    # Download from cloud
kapso logout
kapso version

# Global options: --verbose, --config file.yaml
```

## Testing (YAML Format)

### Test Suite Organization
```
tests/
├── customer_support/          # Suite directory (sanitized name)
│   ├── test-suite.yaml       # Suite metadata
│   │   id: suite_id          # From pull
│   │   name: Customer Support Tests
│   │   description: Test suite description
│   ├── greeting_test.yaml    # Test case files
│   └── order_test.yaml
└── product_search/
    ├── test-suite.yaml
    └── search_test.yaml
```

### Test Case Format
```yaml
# tests/suite_name/test_name.yaml
name: greeting_test
description: Test if agent greets appropriately
script: |
  1. Start by saying "Hello, how are you?"
  2. When the agent responds with a greeting, thank them
  3. If they ask how they can help, say "I need help with my order"
  4. Observe if they offer to check order status
rubric: |
  1. Warm and professional greeting (40%)
  2. Acknowledges user's greeting (30%)
  3. Offers specific help for orders (30%)
# Note: id field is auto-added during kapso deploy
# Scores range from 0.00 to 1.00
```

### Script Writing (LLM Instructions)
- Use numbered steps for clarity
- Write as instructions: "Start by...", "When agent...", "Say..."
- Include conditionals: "If agent asks X, respond with Y"
- Specify expected behaviors: "Observe if...", "Check that..."

## Environment Variables (.env)
```bash
# LLM Configuration
LLM_PROVIDER_NAME=Anthropic
LLM_PROVIDER_MODEL_NAME=claude-sonnet-4-20250514
LLM_API_KEY=your-key
LLM_TEMPERATURE=0.0
LLM_MAX_TOKENS=8096

# APIs
OPENAI_API_KEY=your-key      # For embeddings

# Custom variables
#{variable_name}             # Use in nodes/tools
```

## Node Prompts & Tool Usage

### Referencing Tools in Prompts
You can instruct the LLM to use specific built-in tools in node prompts:

```python
DefaultNode(
    name="notify",
    prompt="Use send_notification_to_user to inform the user about their order status"
)

SubagentNode(
    name="assistant",
    prompt="When the user asks about weather, use the weather_api tool. For FAQs, use the kb_search tool."
)

WarmEndNode(
    name="goodbye",
    prompt="Thank the user and use send_notification_to_user to send a follow-up message"
)
```

### Available Built-in Tools by Node
- **send_notification_to_user**: Send messages to user
- **AskUserForInput**: Request specific information from user
- **MoveToNextNode**: Navigate to specific nodes
- **EnterIdleState**: Pause and wait
- **kb_retrieval**: Search knowledge bases (KB/Subagent nodes)
- **webhook_request**: Make API calls (Webhook nodes)
- **SendWhatsappTemplateMessage**: Send WhatsApp templates

## Best Practices

1. **Use SubagentNode** instead of individual nodes when possible
2. **Global nodes**: Use sparingly (handoff, help menus)
3. **Edge conditions**: Natural language, no overlap
4. **Mock responses**: Enable during development
5. **Variables**: #{variable_name} in URLs, headers, bodies
6. **Node names**: lowercase_with_underscores
7. **Validation**: Always call agent.validate()
8. **Tool references**: Name specific tools in prompts when needed

## Quick Examples

### API Integration
```python
tool = WebhookTool(
    name="weather",
    url="https://api.weather.com/current?city=#{city}",
    http_method="GET",
    headers={"X-API-Key": "#{WEATHER_KEY}"},
    jmespath_query="current.temp_f",
    description="Get weather"
)
```

### Knowledge Base Search
```python
tool = KnowledgeBaseTool(
    name="faq",
    knowledge_base_text="Q: Hours? A: 9-5 M-F",
    description="FAQ answers"
)
```

### Global Help Menu
```python
help = DefaultNode(
    name="help",
    prompt="Show menu: 1) Status 2) Support 3) Info",
    global_=True,
    global_condition="user says help or menu"
)
```

## Debug Tips
- Run with `--verbose` flag
- Check `.deployed.yaml` for deployment state
- Use mock responses to test without APIs
- Validate before deploying
- Test incrementally with `kapso run`