Skip to main content

Creating ATP Notifications

After registering your service, the next step is to create and send notifications. ATP provides a flexible notification system that supports various levels of complexity, from simple yes/no prompts to rich, structured data collection.

Notification Anatomy

An ATP notification consists of several key components:
  1. Basic Information - Title, description, and priority
  2. Actions - Possible user responses with associated response types
  3. Metadata - Additional context for your application
  4. Expiration - Optional timeout for time-sensitive notifications
Here’s a visual representation of a notification’s structure:

Basic Notifications

Let’s start with a simple notification that requires a basic yes/no response:

Python

from atp import ATPClient

client = ATPClient(api_key="your_api_key", service_id="your_service_id")

response = client.send_notification({
    "title": "Approve File Deletion",
    "description": "AI assistant wants to delete 15 temporary files to free up 250MB of space",
    "priority": "normal",
    "actions": [
        {"id": "approve", "label": "Approve", "response_type": "simple"},
        {"id": "reject", "label": "Reject", "response_type": "simple"}
    ]
})

notification_id = response["notification_id"]
print(f"Notification sent with ID: {notification_id}")

JavaScript/Node.js

import { ATPClient } from '@atp/client';

const client = new ATPClient({
  apiKey: 'your_api_key',
  serviceId: 'your_service_id'
});

async function sendBasicNotification() {
  try {
    const response = await client.sendNotification({
      title: 'Approve File Deletion',
      description: 'AI assistant wants to delete 15 temporary files to free up 250MB of space',
      priority: 'normal',
      actions: [
        { id: 'approve', label: 'Approve', responseType: 'simple' },
        { id: 'reject', label: 'Reject', responseType: 'simple' }
      ]
    });
    
    const notificationId = response.notification_id;
    console.log(`Notification sent with ID: ${notificationId}`);
    return notificationId;
  } catch (error) {
    console.error('Failed to send notification:', error);
  }
}

Rich Notifications

ATP supports rich response types that allow collecting structured data from users:

Text Input

Collect free-form text from users:
# Python example
client.send_notification({
    "title": "Name the new project",
    "description": "Please provide a name for the new project you're creating",
    "actions": [
        {
            "id": "submit_name",
            "label": "Submit",
            "response_type": "text",
            "response_options": {
                "placeholder": "Enter project name",
                "max_length": 50,
                "min_length": 3
            }
        },
        {
            "id": "cancel",
            "label": "Cancel",
            "response_type": "simple"
        }
    ]
})

Multiple Choice

Offer users predefined options to choose from:
# Python example
client.send_notification({
    "title": "Select deployment environment",
    "description": "Which environment should we deploy the latest changes to?",
    "actions": [
        {
            "id": "deploy",
            "label": "Deploy",
            "response_type": "select",
            "response_options": {
                "options": [
                    {"value": "dev", "label": "Development"},
                    {"value": "staging", "label": "Staging"},
                    {"value": "production", "label": "Production"}
                ],
                "allow_multiple": False,
                "required": True
            }
        },
        {
            "id": "cancel",
            "label": "Cancel",
            "response_type": "simple"
        }
    ]
})

Form Data

Collect structured data with multiple fields:
# Python example
client.send_notification({
    "title": "Update User Profile",
    "description": "Please review and update your profile information",
    "actions": [
        {
            "id": "update_profile",
            "label": "Update",
            "response_type": "form",
            "response_options": {
                "fields": [
                    {
                        "id": "display_name",
                        "label": "Display Name",
                        "type": "text",
                        "required": True,
                        "default": "Current Name"
                    },
                    {
                        "id": "bio",
                        "label": "Bio",
                        "type": "textarea",
                        "max_length": 500
                    },
                    {
                        "id": "newsletter",
                        "label": "Subscribe to newsletter",
                        "type": "boolean",
                        "default": False
                    }
                ]
            }
        },
        {
            "id": "cancel",
            "label": "Cancel",
            "response_type": "simple"
        }
    ]
})

JSON Schema

For complex data collection with validation, use JSON Schema:
# Python example
client.send_notification({
    "title": "Configure API Settings",
    "description": "Please review and update the API configuration",
    "actions": [
        {
            "id": "update_config",
            "label": "Update",
            "response_type": "json",
            "response_schema": {
                "type": "object",
                "properties": {
                    "timeout_ms": {
                        "type": "integer",
                        "minimum": 1000,
                        "maximum": 60000
                    },
                    "retry": {
                        "type": "object",
                        "properties": {
                            "enabled": {"type": "boolean"},
                            "max_attempts": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 10
                            },
                            "backoff_factor": {
                                "type": "number",
                                "minimum": 1.0,
                                "maximum": 5.0
                            }
                        },
                        "required": ["enabled", "max_attempts"]
                    },
                    "environment": {
                        "type": "string",
                        "enum": ["development", "staging", "production"]
                    }
                },
                "required": ["timeout_ms", "environment"]
            }
        },
        {
            "id": "cancel",
            "label": "Cancel",
            "response_type": "simple"
        }
    ]
})

Action Types

ATP supports different action types that determine what happens when a user responds:

Simple Actions

Simple actions require only a single click with no additional data:
# Python example
{
    "id": "approve",
    "label": "Approve",
    "response_type": "simple"
}

Data Collection Actions

These actions require additional information from the user:
# Python example
{
    "id": "provide_feedback",
    "label": "Submit Feedback",
    "response_type": "text",
    "response_options": {
        "placeholder": "Enter your feedback...",
        "multiline": True,
        "max_length": 1000
    }
}

Multi-step Actions

For more complex interactions, you can chain notifications based on initial responses:
# Python example for the first step
first_notification = client.send_notification({
    "title": "Review Generated Content",
    "description": "Please review the AI-generated blog post",
    "actions": [
        {
            "id": "approve",
            "label": "Approve",
            "response_type": "simple"
        },
        {
            "id": "needs_revision",
            "label": "Needs Revision",
            "response_type": "simple"
        }
    ],
    "metadata": {
        "content_id": "blog_post_123"
    }
})

# In your webhook handler, when receiving a "needs_revision" response:
def handle_webhook(payload):
    if payload["action_id"] == "needs_revision":
        # Send a follow-up notification to collect revision details
        client.send_notification({
            "title": "Specify Revisions Needed",
            "description": "Please provide details about the revisions needed",
            "actions": [
                {
                    "id": "submit_revisions",
                    "label": "Submit",
                    "response_type": "form",
                    "response_options": {
                        "fields": [
                            {
                                "id": "revision_type",
                                "label": "Type of Revision",
                                "type": "select",
                                "options": [
                                    {"value": "content", "label": "Content Issues"},
                                    {"value": "style", "label": "Style/Tone Issues"},
                                    {"value": "factual", "label": "Factual Errors"},
                                    {"value": "other", "label": "Other Issues"}
                                ],
                                "allow_multiple": True
                            },
                            {
                                "id": "details",
                                "label": "Revision Details",
                                "type": "textarea",
                                "required": True
                            }
                        ]
                    }
                }
            ],
            "metadata": {
                "content_id": payload["metadata"]["content_id"],
                "original_notification_id": payload["notification_id"]
            }
        })

Response Types Reference

ATP supports several response types to collect different kinds of data:
TypeDescriptionResponse Data
simpleBasic acknowledgmentNo additional data
textFree-form text inputString value
selectChoose from optionsSelected value(s)
formStructured data with multiple fieldsObject with field values
jsonComplex structured data validated against JSON schemaJSON object
fileFile uploadFile metadata and content

Simple Response Type

{
    "id": "confirm",
    "label": "Confirm",
    "response_type": "simple"
}

Text Response Type

{
    "id": "provide_name",
    "label": "Submit",
    "response_type": "text",
    "response_options": {
        "placeholder": "Enter your name",
        "multiline": False,
        "max_length": 100,
        "min_length": 2,
        "required": True
    }
}

Select Response Type

{
    "id": "choose_option",
    "label": "Select",
    "response_type": "select",
    "response_options": {
        "options": [
            {"value": "option1", "label": "Option 1"},
            {"value": "option2", "label": "Option 2"},
            {"value": "option3", "label": "Option 3"}
        ],
        "allow_multiple": False,
        "required": True
    }
}

Form Response Type

{
    "id": "submit_form",
    "label": "Submit",
    "response_type": "form",
    "response_options": {
        "fields": [
            {
                "id": "name",
                "label": "Name",
                "type": "text",
                "required": True
            },
            {
                "id": "age",
                "label": "Age",
                "type": "number",
                "min": 18,
                "max": 120
            },
            {
                "id": "interests",
                "label": "Interests",
                "type": "select",
                "options": [
                    {"value": "tech", "label": "Technology"},
                    {"value": "sports", "label": "Sports"},
                    {"value": "arts", "label": "Arts"}
                ],
                "allow_multiple": True
            }
        ]
    }
}

JSON Response Type

{
    "id": "submit_config",
    "label": "Submit",
    "response_type": "json",
    "response_schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "settings": {
                "type": "object",
                "properties": {
                    "enabled": {"type": "boolean"},
                    "threshold": {"type": "number"}
                }
            },
            "tags": {
                "type": "array",
                "items": {"type": "string"}
            }
        },
        "required": ["name", "settings"]
    }
}

Notification Constraints

When creating notifications, be aware of these constraints:

Limits

  • Title: Maximum 100 characters
  • Description: Maximum 1000 characters
  • Actions: Between 1 and 5 actions per notification
  • Action Labels: Maximum 50 characters
  • Priority Levels: “low”, “normal”, “high”, or “urgent”

Best Practices

  1. Keep notifications concise - Use clear, direct language
  2. Provide sufficient context - Ensure users understand why they’re being asked to respond
  3. Limit the number of actions - Fewer choices lead to faster decisions
  4. Use appropriate priority levels - Reserve “high” and “urgent” for time-sensitive notifications
  5. Include helpful metadata - Store relevant context for later processing

Example: Well-designed Notification

# Python example of a well-designed notification
client.send_notification({
    "title": "Approve payment of $156.78 to Acme Corp",
    "description": "The AI assistant has prepared a payment of $156.78 to Acme Corp for April consulting services (Invoice #AC-2023-042)",
    "priority": "high",
    "actions": [
        {
            "id": "approve",
            "label": "Approve Payment",
            "response_type": "simple"
        },
        {
            "id": "reject",
            "label": "Reject",
            "response_type": "text",
            "response_options": {
                "placeholder": "Reason for rejection (optional)",
                "required": False
            }
        },
        {
            "id": "modify",
            "label": "Modify Amount",
            "response_type": "form",
            "response_options": {
                "fields": [
                    {
                        "id": "amount",
                        "label": "Payment Amount",
                        "type": "number",
                        "required": True,
                        "default": 156.78,
                        "min": 0.01
                    },
                    {
                        "id": "reason",
                        "label": "Reason for change",
                        "type": "text",
                        "required": True
                    }
                ]
            }
        }
    ],
    "expiration": {
        "expires_in": 86400  # 24 hours in seconds
    },
    "metadata": {
        "invoice_id": "AC-2023-042",
        "vendor_id": "ACME-001",
        "payment_method": "bank_transfer",
        "department": "operations"
    }
})

Notification Metadata

Metadata allows you to include additional context with your notifications. This data will be returned with the response, helping you correlate responses with the original context:
# Python example with useful metadata
client.send_notification({
    "title": "Review content for publishing",
    "description": "Please review this AI-generated blog post before publishing",
    "actions": [
        {"id": "approve", "label": "Approve", "response_type": "simple"},
        {"id": "reject", "label": "Reject", "response_type": "simple"}
    ],
    "metadata": {
        "content_id": "post_12345",
        "content_type": "blog_post",
        "author": "ai_content_generator",
        "generated_at": "2023-04-15T10:30:00Z",
        "word_count": 750,
        "topic": "machine_learning",
        "target_publication_date": "2023-04-17"
    }
})
The metadata will be included in the webhook response, allowing your system to process the response in context:
{
  "notification_id": "ntf_1Ab2Cd3Ef4",
  "service_id": "srv_9Xy8Wv7Ut6",
  "action_id": "approve",
  "response_data": null,
  "response_time": "2023-04-15T14:22:10Z",
  "metadata": {
    "content_id": "post_12345",
    "content_type": "blog_post",
    "author": "ai_content_generator",
    "generated_at": "2023-04-15T10:30:00Z",
    "word_count": 750,
    "topic": "machine_learning",
    "target_publication_date": "2023-04-17"
  }
}

Notification Expiration

For time-sensitive notifications, you can set an expiration time:
# Python example with expiration
client.send_notification({
    "title": "Approve urgent security patch deployment",
    "description": "Security patch for critical vulnerability CVE-2023-1234 needs approval",
    "priority": "urgent",
    "actions": [
        {"id": "approve", "label": "Deploy Now", "response_type": "simple"},
        {"id": "schedule", "label": "Schedule", "response_type": "select",
         "response_options": {
             "options": [
                 {"value": "1h", "label": "In 1 hour"},
                 {"value": "4h", "label": "In 4 hours"},
                 {"value": "8h", "label": "In 8 hours"}
             ]
         }}
    ],
    "expiration": {
        "expires_in": 3600  # 1 hour in seconds
    },
    "metadata": {
        "vulnerability_id": "CVE-2023-1234",
        "severity": "critical",
        "systems_affected": 12
    }
})
When a notification expires:
  1. It will no longer be displayed to users
  2. Any pending responses will be rejected
  3. You can optionally receive a webhook notification of the expiration

Testing Your Notifications

Before sending notifications to real users, it’s a good practice to test them thoroughly:

Using the Test Environment

# Python example for testing
from atp import ATPClient

# Use test credentials for development
test_client = ATPClient(
    api_key="sk_test_your_test_key",
    service_id="test_service_id"
)

# Send a test notification
test_response = test_client.send_notification({
    "title": "Test Notification",
    "description": "This is a test notification",
    "actions": [
        {"id": "test_action", "label": "Test Action", "response_type": "simple"}
    ],
    "metadata": {
        "is_test": True
    }
})

print(f"Test notification sent with ID: {test_response['notification_id']}")

Simulating Responses

The ATP SDK provides test utilities for simulating user responses:
from atp.testing import TestClient

# Create a test client
test_client = TestClient()

# Simulate a user response
test_client.respond_to(notification_id, "test_action")

# For actions with response data
test_client.respond_to(
    notification_id,
    "provide_feedback",
    response_data="This is test feedback"
)

Notification Design Best Practices

To create effective notifications that respect user attention:
  1. Be clear and specific - Provide enough context for informed decisions
  2. Use appropriate priority - Don’t overuse high priority
  3. Group related notifications - Avoid notification fatigue
  4. Respect privacy - Don’t include sensitive information in titles/descriptions
  5. Set reasonable expirations - Match expiration time to urgency
  6. Provide actionable options - Make action labels clear and specific
  7. Include fallback options - Add “Cancel” or “Later” options when appropriate

Poor vs. Good Examples

Poor Notification
client.send_notification({
    "title": "Approval needed",
    "description": "Please approve this action",
    "actions": [
        {"id": "y", "label": "Yes", "response_type": "simple"},
        {"id": "n", "label": "No", "response_type": "simple"}
    ]
})
Good Notification
client.send_notification({
    "title": "Approve $530 expense report for Q2 client meeting",
    "description": "Expense report #ER-2023-089 includes: Hotel ($350), Meals ($120), Transportation ($60). All receipts verified.",
    "priority": "normal",
    "actions": [
        {"id": "approve", "label": "Approve Expense", "response_type": "simple"},
        {"id": "reject", "label": "Reject", "response_type": "text", 
         "response_options": {"placeholder": "Reason for rejection", "required": true}},
        {"id": "info", "label": "Request More Information", "response_type": "text",
         "response_options": {"placeholder": "What additional information do you need?", "required": true}}
    ],
    "metadata": {
        "expense_id": "ER-2023-089",
        "employee_id": "EMP-456",
        "department": "sales",
        "report_date": "2023-04-10"
    }
})

Verification: Knowledge Check

Before proceeding, let’s verify your understanding of notification creation: If you understand these concepts, you’re ready to start creating effective notifications for your users.

Next Steps

Now that you know how to create notifications, the next step is learning how to process the responses you receive from users.

Processing Responses

Learn how to handle and process user responses to your notifications
I