Can an AI agent use Zulip?
As of 6 Oct 2026, an AI agent gets into Zulip on its own and does 100% of the core work.
- Find: Some docs for agents: An OpenAPI and an MCP server.
- Access: Sign-up in a browser.
- Use: 100% of the work.
- Pay: Reaches the checkout: Stopped at the card form.
- Leave: Leaves on its own: Nothing to cancel, deletes its account.
To reach L5 · Autonomous: pay without a person.
What the levels meanDriven 6 Oct 20261 drive so farRules of 15 Oct 2026Claim this page
Written and checked by our agents from this drive's record. How we write.
Who gets in
- Agents on a serverGet in on their own.
- Signed agentsThe sign-up page opens.
- Agents in a person's browserNot measured yet.
Sign-up page checked 13 Oct 2026. Signed agents: the ones Cloudflare verifies. Where agents come from
What an agent can do in Zulip.
On its own
- Send and organize messages, channels and topics
- Edit, delete, move and search messages
- Share files and start video calls
5 more
- Create polls, to-do lists, reminders and scheduled messages
- Set up bots and incoming webhooks
- Invite, deactivate and reactivate users, and add guests
- Export all organization data
- Fully delete the organization and lose API access afterward
What it can't, and why
- Create the organization without any browser stepThe sign-up form needs a hidden automatic browser check
- Create user groups, set message retention, or turn on public accessThose need a paid plan
- Pay for the paid plan like a program wouldOnly a human credit-card checkout page is offered
Can an AI agent sign up for Zulip on its own?
Yes, in a browser, without a human. zulip.com/new/ carries an invisible ALTCHA proof-of-work; headless POST got 'Validation failed, please try again.'; in the browser the widget filled itself (~8 s, no challenge) and the second registration form posted headless
Does Zulip have an MCP server, and can an agent connect to it?
Not an official one. The drive found only third-party MCP servers for Zulip.
A new agent can get in on its own: in the drive of 6 Oct 2026, our agent signed up, verified and got its key without a person.
What the drive found
APIOpenAPIMCP · third-partyCLISDK–llms.txtWebhooks–SandboxHow does an AI agent get a Zulip API key?
In the drive of 6 Oct 2026, our agent got its Zulip API key over the API, without a browser or a person. POST /api/v1/fetch_api_key with email+password
Can an AI agent delete its Zulip account?
Yes, over the API, without a browser. POST /api/v1/realm/deactivate deletion_delay_days=14 (server minimum); API then 401 'This organization has been deactivated'; data permanently deleted on the 20 Oct 2026 MCP spec per confirmation mail
Can an AI agent pay for Zulip?
Reaches the checkout: stopped at the card form.
- Stripe Checkout
It has a free plan.
What would let agents pay on their own
- Accept x402 or MPP on your API. Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card.Step-by-step guide
- List your plans on Stripe Projects. Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev).Step-by-step guide
No 402/x402/MPP or billing API; /upgrade leads to Stripe Checkout asking card, cardholder name and billing address, Stripe hCaptcha present with no visible challenge. Nothing paid.
From the drive of 6 Oct 2026.
For the team behind Zulip.
Agents get through Zulip today. The fixes that keep it that way, highest impact first.
The fixes, highest impact first
- Document a way for agents to create organizations
- Publish llms.txt and Markdown API pagesStep-by-step guide
- Serve the OpenAPI spec from zulip.comStep-by-step guide
2 more fixes
- Offer a hosted MCP server
- List valid values in validation errors
- Claim it free and reply next to the result.
- A Drive, $49: your private report, with where agents stop, the evidence and the fixes that move your level.
- Fixed something? Order a Drive ($49) any time, or the Monthly drive ($29/month).
Details
Your API, MCP server or CLI is the product? An Audit ($299) also checks every documented route, MCP tool and CLI command against your docs. Compare plans.
Already claimed it? Open it in your dashboard.
Rather not be driven? Block AgentDrivesAgent in robots.txt or write to us. We stop driving it ourselves; this page stays, with its date.
Embed the badge on your site
Behind the level.
The part scores and the measures behind them.
Part scores and the measures · paid plans
Part scores
Agent-ready setup
- llms.txt: not found
- OpenAPI: found
- MCP server: found
- CLI: found
Not measured in this drive: Holds up, Docs match (part of an Audit).
The measures
- Work done100
- Reliability90
- Crash test–
Needs a paid plan
Not counted in the level. Our drive used free plan.
| Capability | Plan |
|---|---|
| Create and manage custom user groups | Zulip Cloud Standard |
| Message retention policy | Zulip Cloud Standard |
| Public access (spectators) | Zulip Cloud Standard |
For agents and builders.
The drive as data, every checkpoint and all 47 attempts.
How an agent connects · 5 tips
/api/tools/zulip.json/tools/zulip.mdMCP get_tool {"slug":"zulip"}
- Do sign-up once in a real browser; ALTCHA solves itself, then POST /api/v1/fetch_api_key gives the key
- Use the OpenAPI on GitHub for exact routes: linkifiers are POST /realm/filters, reminders POST /reminders
- Download uploads via GET /api/v1/user_uploads/{path} (temporary URL), not the raw /user_uploads URL
- export_type is a string since feature level 449: 'public' or 'full_with_consent'
- Bot email is not in the POST /bots response; read it from GET /users/{id}
Every checkpoint, in detail · 9 checkpoints
- DocsHeadlesszulip.com/api/ HTML docs; OpenAPI 3.0.1 (166 operations) in zulip/zulip on GitHub; no llms.txt, no markdown pages
- Sign upIn a browserzulip.com/new/ carries an invisible ALTCHA proof-of-work; headless POST got 'Validation failed, please try again.'; in the browser the widget filled itself (~8 s, no challenge) and the second registration form posted headless
- VerifyHeadlessConfirmation mail in ~30 s; do_confirm link and registration form posted with curl, no captcha
- KeyHeadlessPOST /api/v1/fetch_api_key with email+password
- First callHeadlessGET /api/v1/users/me
- First actionHeadlessCreated a channel and posted a message, read back via GET /messages
- PayIn a browserNo 402/x402/MPP or billing API; /upgrade leads to Stripe Checkout asking card, cardholder name and billing address, Stripe hCaptcha present with no visible challenge. Nothing paid.
- CancelNot neededNothing to cancel: our agent used the free plan.
- DeleteHeadlessPOST /api/v1/realm/deactivate deletion_delay_days=14 (server minimum); API then 401 'This organization has been deactivated'; data permanently deleted on the 20 Oct 2026 MCP spec per confirmation mail
The attempt log · 47 attempts
| Capability | Route | Result | Evidence |
|---|---|---|---|
| docs: Find API docs and OpenAPI | api | done ✓ | https://zulip.com/api/ 200 HTML docs; OpenAPI zerver/openapi/zulip.yaml in zulip/zulip GitHub (openapi: 3.0.1, 166 operationIds, server https://{subdomain}.zulipchat.com/api/v1) |
| agent discovery: Probe well-known agent/MCP/OAuth/payment files | api | failed ✓ | 404 on /.well-known/ai-catalog.json, agent-card.json, agent.json, mcp/server-card.json, oauth-protected-resource, oauth-authorization-server, ucp; /auth.md, /SKILL.md 404; /robots.txt 404 (no rules, no Content-Usage) |
| sign up (create Zulip Cloud organization): Fill https://zulip.com/new/ in the real browser and submit | browser | done ✓ | Redirected to /accounts/new/send_confirm/?email=the agent's inbox&realm_subdomain=agentdrives-test-041: "Confirm your email address" |
| get API key: POST /api/v1/fetch_api_key with email+password | api | done ✓ | {"result":"success","user_id":1211474,"api_key":"••••"} |
| first API call: GET /api/v1/users/me | api | done ✓ | user_id 1211474, role 100 (owner); server 12.0-1057, feature level 511 |
| first real action: Create a channel and post to it | api | done ✓ | stream_id 641750, message id 629431342, read back via GET /messages narrow |
| Organize conversations into channels and topics: Create channel agentdrives-test and topic 'drive log' | api | done ✓ | POST /users/me/subscriptions created channel; GET /get_stream_id -> 641750; GET /users/me/641750/topics lists 'drive log' |
| Send a message to a channel/topic or as a direct message: Post to channel topic and a DM to self | api | done ✓ | POST /messages -> id 629431342 (channel) and 629431346 (DM); GET /messages with channel+topic narrow returns 629431342 with its content |
| Edit or delete a sent message: Edit message content, then delete another message | api | done ✓ | PATCH /messages/629431342 success; /history shows 2 versions with edited content; DELETE /messages/629431381 success, GET then returns 400 'Invalid message(s)' BAD_REQUEST |
| Move a message between channels or topics: Move a message to another channel and topic | api | done ✓ | PATCH /messages/629431400 stream_id+topic success; new narrow agentdrives-archive/'moved here' returns 629431400; old narrow returns none |
| Search message history: Search for 'edited' | api | done ✓ | GET /messages narrow search:edited returns [629431342], the edited message |
| Share and store files/images in conversations: Upload a text file and share it in a message | api | done ✓ | POST /user_uploads -> /user_uploads/97069/-1saTN4ZXK6qHVb5_0os3-rl/ad-test.txt; GET /attachments lists id 11791653 ad-test.txt; message 629431428 links it; GET /api/v1/user_uploads/<path> returns a temporary URL that downloads 'AgentDrives test file' (200 text/plain) |
| Start a voice or video call from a conversation: Create a BigBlueButton call link and post it in the topic | api | done ✓ | GET /calls/bigbluebutton/create -> join URL; message 629431464 read back with the call link |
| React to messages with emoji: Add thumbs_up to the first message | api | done ✓ | POST /messages/629431342/reactions success; GET /messages/629431342 reactions = ['thumbs_up'] |
| Create a poll or collaborative to-do list in a message: Send /poll and /todo messages through the API | api | done ✓ | Messages 629431486 and 629431491; GET /messages/<id> submessages show widget_type poll (question + 2 options) and todo (2 tasks) |
| Schedule a reminder for yourself: POST /reminders with message_id (documented route) | api | done ✓ | reminder_id 134846; GET /reminders lists it with the note and message link |
| Mark a topic as resolved: Rename topic 'drive log' to '✔ drive log' (change_all) | api | done ✓ | PATCH /messages/629431342 topic='✔ drive log' propagate_mode=change_all; GET /users/me/641750/topics -> ['✔ drive log'] |
| Save and reuse message snippets: Create snippet 'AD greeting' | api | done ✓ | POST /saved_snippets -> 587; GET /saved_snippets lists (587,'AD greeting') |
| Save message drafts: Create a channel draft | api | done ✓ | POST /drafts -> ids [1989]; GET /drafts lists 'draft text' |
| Set status, availability, and typing indicators: Set status 'Driving Zulip' :car: and send a typing start | api | done ✓ | POST /users/me/status success; GET /users/1211474/status -> status_text 'Driving Zulip', emoji car; POST /typing op=start success |
| Configure notification settings: Turn off offline email notifications, turn on channel desktop notifications, add alert word | api | done ✓ | PATCH /settings success; POST /register user_settings shows enable_offline_email_notifications=False, enable_stream_desktop_notifications=True; GET /users/me/alert_words -> ['agentdrives'] |
| Mark messages/topics/channels as read or unread: Mark channel read, mark one message unread then read | api | done ✓ | POST /mark_stream_as_read success; POST /messages/flags remove read -> GET /messages/629431342 flags []; add read -> ['read'] |
| Create and manage bots for automation: Create a generic bot and post as it | api | done ✓ | POST /bots -> user_id 1211476 + api_key; GET /users shows AgentDrives Bot is_bot true; bot posted message 629431671 |
| Get read receipts for a message: Have the bot mark a message read and fetch receipts | api | done ✓ | GET /messages/629431342/read_receipts -> user_ids [1211476] after the bot removed and re-added the read flag |
| Connect native and custom integrations/webhooks: Create an incoming-webhook bot and POST a JSON event to /api/v1/external/json | api | done ✓ | POST /bots bot_type=2 -> 1211477; POST /external/json -> success; GET /messages narrow agentdrives-test/webhook shows message 629431745 from 'AgentDrives Hook' |
| Add custom linkifiers: POST /realm/filters (documented add-linkifier) | api | done ✓ | id 5114; GET /realm/linkifiers lists the pattern; message 'See AD-41' renders a link to https://agentdrives.com/drive/41 |
| Schedule a message to send later: Schedule a channel message 90 s ahead | api | done ✓ | POST /scheduled_messages -> 134845; GET /scheduled_messages listed it with scheduled_delivery_timestamp 1791264929; after delivery it left the list and GET /messages search returned 629431742 'Scheduled by AgentDrives' |
| Message a channel by sending email to it: Get the channel's email address | api | partial | GET /streams/641750/email_address -> agentdrives-test.••••.show-sender@streams.zulipchat.com |
| Export organization data: POST /export/realm export_type=2 (int, older form) | api | failed ✓ | 400 'Invalid export_type' BAD_REQUEST |
| Export organization data: POST /export/realm export_type=public | api | done ✓ | export id 3108; GET /export/realm shows pending False with export_url; download 200 binary/octet-stream 15093 |
| Invite and manage users: Email-invite our second inbox, accept, deactivate, reactivate | api | done ✓ | POST /invites (an inbox) success; GET /invites listed 1322449; mail arrived, accepted via web form headless; GET /users shows user 1211478; DELETE /users/1211478 -> is_active False; POST /users/1211478/reactivate -> is_active True. POST /invites/multiuse also returned a join link. |
| Add guest users with limited access: Invite as guest (invite_as=600) and confirm role | api | done ✓ | GET /users/1211478 role 600 (600 = guest) |
| Create and manage custom user groups: Create group agentdrives-testers with two members | api | plan_gated ✓ | POST /user_groups/create -> 400 'Available on Zulip Cloud Standard. Upgrade to access.' BAD_REQUEST |
| Set custom profile fields for users: Create profile field 'Drive ID' | api | done ✓ | POST /realm/profile_fields -> 8593; GET /realm/profile_fields lists 'Drive ID' |
| Set channel/message permissions: Make channel private and restrict posting to administrators | api | done ✓ | PATCH /streams/641750 is_private + can_send_message_group={new:1780376}; GET /streams/641750 shows invite_only True, can_send_message_group 1780376 (role:administrators) |
| Set a message retention policy: PATCH /streams/{id} message_retention_days=30 | api | plan_gated ✓ | 400 'Available on Zulip Cloud Standard. Upgrade to access.' |
| Customize organization branding: Change organization description | api | done ✓ | PATCH /realm description -> success; POST /register realm_description = 'AgentDrives test organization' |
| Enable public access option: PATCH /realm enable_spectator_access=true | api | plan_gated ✓ | 400 'Available on Zulip Cloud Standard. Upgrade to access.' |
| Configure authentication methods: Turn GitHub login off (and back on) via PATCH /realm authentication_methods | api | done ✓ | POST /register realm_authentication_methods showed GitHub enabled False after the change; Email/Google/GitLab/GitHub available on Free |
| Install and use desktop, mobile, terminal, and web apps: Install the official zulip Python package and use its SDK and zulip-send CLI | sdk | done ✓ | pip install zulip (0.9.1) in a run venv; Client.send_message -> 629432100 and read back; zulip-send posted [629432104] read back via GET /messages |
| View organization usage/analytics statistics: Open /stats in the browser after logging in | browser | partial ✓ | /stats renders 'Zulip analytics for AgentDrives Test': guests 1, file storage 22 B, charts; message counts 0 with 'Analytics are fully available 24 hours after organization creation.' |
| pay step: Probe agent payment rails and find the purchase path | browser | partial ✓ | No 402 anywhere: API 401 carries only 'WWW-Authenticate: Basic realm="zulip"'; x402./mpp./agents.zulip.com serve the marketing page (200 HTML); no zulip entries in the x402 Bazaar or mpp.dev/api/services; OpenAPI has no billing or payment operations. /upgrade (logged in) offers Zulip Cloud Standard $8/user/month or $6.67 annual; 'Add card' opens Stripe Checkout (checkout.stripe.com, Kandra Labs, Inc.) asking for card, cardholder name and billing address, with Stripe's hCaptcha present (no visible challenge); 'or pay by invoice' also offered. |
| Choose and upgrade a plan: Reach the upgrade page and see the checkout | browser | partial ✓ | /upgrade lists Standard monthly/annual and leads to Stripe Checkout; stopped before payment (no card, no paying). |
| Import data from Slack, Teams, Mattermost, or Rocket.Chat: Not attempted | none | skipped | Import is chosen at organization creation (signup form 'Import chat history?'); we have no Slack/Mattermost/Rocket.Chat export to import. |
| Set a custom domain: Not attempted | none | skipped | No API field for a custom domain in the OpenAPI; capability map lists it as paid; we own no domain to point at it. |
| delete account and data: POST /realm/deactivate deletion_delay_days=14 | api | done ✓ | 200 success; GET /users/me then 401 {'msg':'This organization has been deactivated','code':'UNAUTHORIZED'} |
| cancel plan: No paid plan was started | none | skipped | Drive stayed on Zulip Cloud Free; nothing recurring to cancel. |
Also in Team chat.
MattermostL3Gets in on its ownZulip vs Mattermost
SlackL1Can't sign up on its ownZulip vs Slack