Webhook Support (#2225)

This commit is contained in:
Dev Khant
2025-02-19 13:34:01 +05:30
committed by GitHub
parent 1436da18b1
commit 760cd54ddf
4 changed files with 387 additions and 2 deletions

View File

@@ -45,7 +45,8 @@
"features/custom-instructions",
"features/direct-import",
"features/async-client",
"features/memory-export"
"features/memory-export",
"features/webhook"
]
}
]

223
docs/features/webhook.mdx Normal file
View File

@@ -0,0 +1,223 @@
---
title: Webhooks
description: 'Configure and manage webhooks to receive real-time notifications about memory events'
icon: "webhook"
iconType: "solid"
---
## Overview
Webhooks allow you to receive real-time notifications when memory events occur in your Mem0 project. Webhooks are configured at the project level, meaning each webhook is associated with a specific project and will only receive events from that project. You can configure webhooks to send HTTP POST requests to your specified URLs whenever memories are created, updated, or deleted.
## Managing Webhooks
### Get Webhooks
Retrieve all webhooks configured for your project. By default, it uses the project_id from your client configuration, but you can optionally specify a different project:
<CodeGroup>
```python Python
from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
# Get webhooks for the default project
webhooks = client.get_webhooks()
# Or specify a different project
webhooks = client.get_webhooks(project_id="proj_123")
print(webhooks)
```
```javascript JavaScript
const { MemoryClient } = require('mem0ai');
const client = new MemoryClient('your-api-key');
// Get webhooks for the default project
const webhooks = await client.getWebhooks();
// Or specify a different project
const webhooks = await client.getWebhooks("proj_123");
console.log(webhooks);
```
```json Output
[
{
'id': 6,
'url': 'https://mem0.ai',
'name': 'mem0',
'owner': 'john',
'project': 'default-project',
'secret': '3254dde069fe2490216dba7ca4e0f3595619a28e5909ba80d45caed7577f1040',
'is_active': True,
'created_at': '2025-02-18T22:59:56.804993-08:00',
'updated_at': '2025-02-18T23:06:41.479361-08:00'
}
]
```
</CodeGroup>
### Create Webhook
Create a new webhook for your project. The webhook will only receive events from the specified project:
<CodeGroup>
```python Python
# Create a webhook in the default project
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger"
)
# Or create in a specific project
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger",
project_id="proj_123"
)
print(webhook)
```
```javascript JavaScript
// Create a webhook in the default project
const webhook = await client.createWebhook({
url: "https://your-app.com/webhook",
name: "Memory Logger"
});
// Or create in a specific project
const webhook = await client.createWebhook({
url: "https://your-app.com/webhook",
name: "Memory Logger",
projectId: "proj_123"
});
console.log(webhook);
```
```json Output
{
'id': 1,
'name': 'Memory Logger',
'url': 'https://your-app.com/webhook',
'project': 'default-project',
'secret': '3254dde069fe2490216dba7ca4e0f3595619a28e5909ba80d45caed7577f1040',
'is_active': True,
'created_at': '2025-02-18T22:59:56.804993-08:00',
'updated_at': '2025-02-18T23:06:41.479361-08:00'
}
```
</CodeGroup>
### Update Webhook
Modify an existing webhook's configuration. Remember that webhooks can only be updated within their associated project:
<CodeGroup>
```python Python
# Update webhook in default project
updated_webhook = client.update_webhook(
webhook_id=1,
name="Updated Logger",
url="https://your-app.com/new-webhook"
)
# Or update in a specific project
updated_webhook = client.update_webhook(
webhook_id=1,
name="Updated Logger",
url="https://your-app.com/new-webhook",
project_id="proj_123"
)
print(updated_webhook)
```
```javascript JavaScript
// Update webhook in default project
const updatedWebhook = await client.updateWebhook(1, {
name: "Updated Logger",
url: "https://your-app.com/new-webhook"
});
// Or update in a specific project
const updatedWebhook = await client.updateWebhook(1, {
name: "Updated Logger",
url: "https://your-app.com/new-webhook",
projectId: "proj_123"
});
console.log(updatedWebhook);
```
```json Output
{
"message": "Webhook updated successfully"
}
```
</CodeGroup>
### Delete Webhook
Remove a webhook configuration from a project:
<CodeGroup>
```python Python
# Delete webhook from default project
response = client.delete_webhook(webhook_id=1)
# Or delete from a specific project
response = client.delete_webhook(webhook_id=1, project_id="proj_123")
print(response)
```
```javascript JavaScript
// Delete webhook from default project
const response = await client.deleteWebhook(1);
// Or delete from a specific project
const response = await client.deleteWebhook(1, "proj_123");
console.log(response);
```
```json Output
{
"message": "Webhook deleted successfully"
}
```
</CodeGroup>
## Webhook Payload
When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following payload structure:
```json
{
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
"data": {
"memory": "Name is Alex"
},
"event": "ADD"
}
```
## Best Practices
1. **Implement Retry Logic**: Your webhook endpoint should be able to handle temporary failures and implement appropriate retry mechanisms.
2. **Verify Webhook Source**: Implement security measures to verify that webhook requests are coming from Mem0.
3. **Process Events Asynchronously**: Handle webhook events asynchronously to prevent timeouts and ensure reliable processing.
4. **Monitor Webhook Health**: Regularly check your webhook logs to ensure proper functionality and handle any delivery failures.
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />

View File

@@ -524,6 +524,112 @@ class MemoryClient:
"""
raise NotImplementedError("Chat is not implemented yet")
@api_error_handler
def get_webhooks(self, project_id: Optional[str] = None) -> Dict[str, Any]:
"""Get webhooks configuration for the project.
Args:
project_id: The ID of the project to get webhooks for.
Returns:
Dictionary containing webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
project_id = project_id or self.project_id
if not project_id:
raise ValueError("project_id must be set to access webhooks")
response = self.client.get(f"api/v1/webhooks/{project_id}/webhook/")
response.raise_for_status()
capture_client_event("client.get_webhook", self)
return response.json()
@api_error_handler
def create_webhook(self, url: str, name: str, project_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a webhook for the current project.
Args:
url: The URL to send the webhook to.
name: The name of the webhook.
Returns:
Dictionary containing the created webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
project_id = project_id or self.project_id
if not project_id:
raise ValueError("project_id must be set to create webhook")
payload = {"url": url, "name": name}
response = self.client.post(f"api/v1/webhooks/{project_id}/webhook/", json=payload)
response.raise_for_status()
capture_client_event("client.create_webhook", self)
return response.json()
@api_error_handler
def update_webhook(
self, webhook_id: int, name: Optional[str] = None, url: Optional[str] = None, project_id: Optional[str] = None
) -> Dict[str, Any]:
"""Update a webhook configuration.
Args:
webhook_id: ID of the webhook to update
name: Optional new name for the webhook
url: Optional new URL for the webhook
project_id: The ID of the project to update the webhook for.
Returns:
Dictionary containing the updated webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
project_id = project_id or self.project_id
if not project_id:
raise ValueError("project_id must be set to update webhook")
payload = {k: v for k, v in {"name": name, "url": url}.items() if v is not None}
response = self.client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status()
capture_client_event("client.update_webhook", self, {"webhook_id": webhook_id})
return response.json()
@api_error_handler
def delete_webhook(self, webhook_id: int, project_id: Optional[str] = None) -> Dict[str, str]:
"""Delete a webhook configuration.
Args:
webhook_id: ID of the webhook to delete
project_id: The ID of the project to delete the webhook for.
Returns:
Dictionary containing success message.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
project_id = project_id or self.project_id
if not project_id:
raise ValueError("project_id must be set to delete webhook")
response = self.client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status()
capture_client_event("client.delete_webhook", self, {"webhook_id": webhook_id})
return response.json()
def _prepare_payload(
self, messages: Union[str, List[Dict[str, str]], None], kwargs: Dict[str, Any]
) -> Dict[str, Any]:
@@ -867,3 +973,58 @@ class AsyncMemoryClient:
async def chat(self):
raise NotImplementedError("Chat is not implemented yet")
@api_error_handler
async def get_webhooks(self, project_id: Optional[str] = None) -> Dict[str, Any]:
project_id = project_id or self.sync_client.project_id
if not project_id:
raise ValueError("project_id must be set to access webhooks")
response = await self.async_client.get(
f"api/v1/webhooks/{project_id}/webhook/",
)
response.raise_for_status()
capture_client_event("async_client.get_webhook", self.sync_client)
return response.json()
@api_error_handler
async def create_webhook(self, url: str, name: str, project_id: Optional[str] = None) -> Dict[str, Any]:
project_id = project_id or self.sync_client.project_id
if not project_id:
raise ValueError("project_id must be set to create webhook")
response = await self.async_client.post(
f"api/v1/webhooks/{project_id}/webhook/", json={"url": url, "name": name}
)
response.raise_for_status()
capture_client_event("async_client.create_webhook", self.sync_client)
return response.json()
@api_error_handler
async def update_webhook(
self, webhook_id: int, name: Optional[str] = None, url: Optional[str] = None, project_id: Optional[str] = None
) -> Dict[str, Any]:
project_id = project_id or self.sync_client.project_id
if not project_id:
raise ValueError("project_id must be set to update webhook")
payload = {k: v for k, v in {"name": name, "url": url}.items() if v is not None}
response = await self.async_client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status()
capture_client_event("async_client.update_webhook", self.sync_client, {"webhook_id": webhook_id})
return response.json()
@api_error_handler
async def delete_webhook(self, webhook_id: int, project_id: Optional[str] = None) -> Dict[str, str]:
project_id = project_id or self.sync_client.project_id
if not project_id:
raise ValueError("project_id must be set to delete webhook")
response = await self.async_client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status()
capture_client_event("async_client.delete_webhook", self.sync_client, {"webhook_id": webhook_id})
return response.json()

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "mem0ai"
version = "0.1.51"
version = "0.1.52"
description = "Long-term memory for AI Agents"
authors = ["Mem0 <founders@mem0.ai>"]
exclude = [