Skip to main content
This guide walks you through building a custom AI agent that listens for messages in Zenzap and responds using OpenAI. By the end, you’ll have a working bot that polls for new messages, processes them through an LLM, and sends replies back to your topics.

Prerequisites

Project Setup

Create a new directory for your agent and install the required dependencies:
Create a .env file with your credentials:

Step 1 — Build the Zenzap API Client

Create zenzap_client.py. This module handles all communication with the Zenzap API, including HMAC request signing (see Authentication for details). Start with the response wrapper and client constructor:
Next, add the private methods that handle request signing and HTTP calls. Every request must include an HMAC-SHA256 signature — GET requests sign the URI path, while POST/PATCH/DELETE requests sign the JSON body:
Finally, add the public API methods your agent will use:
The client uses additional methods like create_topic, list_topics, create_task, etc. See the full API Reference endpoints for everything you can do.

Step 2 — Handle Incoming Messages

Create bot.py. Start by defining a system prompt and a state object to track the bot’s runtime data:
  • bot_member_id — the bot’s own user ID, so it can skip its own messages.
  • next_offset — the cursor for long polling.
  • topic_name_cache — avoids repeated API calls to resolve topic names.
  • conversation_histories — per-topic message history sent to OpenAI for context.
Now add the core message handler. When a message arrives, it appends it to the topic’s conversation history, calls OpenAI, and sends the reply back:

Step 3 — Process Updates From the Poll Loop

Add a function that filters incoming updates and routes relevant ones to the chat handler. The bot should ignore its own messages and empty texts:
Key behaviors:
  • Only message.created events are processed — see Webhook Events for all event types.
  • The bot skips its own messages by comparing senderId to bot_member_id.
  • Each incoming message is marked as read and given an 👀 reaction as visual feedback.

Step 4 — Wire Up the Main Loop

Finally, add the main() function that initializes the clients and starts the long-polling loop:
The main loop uses long polling to efficiently wait for new events. If a 409 error occurs (offset expired), it resets and starts fresh.

Step 5 — Run the Agent

Start the bot:
You should see output confirming the connection:
The bot will also send a message to your control channel confirming it’s online. From here, any message sent in a topic the bot has access to will trigger an OpenAI-powered response.

Next Steps

  • Custom tools — Extend handle_chat to support function calling so your agent can create tasks, manage topics, or call external APIs.
  • Conversation management — Use a database instead of in-memory conversation_histories for persistence across restarts.

Contact Support

If you have any questions or need help, don’t hesitate to contact our Support Team.