#4253·composio

[Bug]: Zoom webinar creation fails — managed OAuth app can't request webinar:write scope

Author: dolliverCreated Aug 26, 2026Updated Sep 9, 2026
Labelssupport

SDK Language

Python SDK (composio package)

SDK Version

composio==0.15.0, composio-client==1.39.0, composio-langgraph==0.15.0 (issue reproduces via hosted Tool Router meta-tools, not SDK-specific)

Runtime Environment

Python 3.11.9, Linux (server-side agent backend using langgraph + Tool Router meta-tools); bug is platform-side (managed Zoom OAuth app scopes + toolkit coverage)

Environment

Production Deployment

Describe the Bug

An end user asked our agent (via Tool Router meta-tools) to create a Zoom webinar. The flow is unfixable from the user side, for three compounding reasons:

  1. The managed Zoom OAuth app cannot request webinar creation. GET /api/v3/toolkits/zoomcomposio_managed_auth[0].scopes.available lists 26 scopes; every webinar scope is read-only except webinar:write:registrant. webinar:write:webinar (and update/delete) are not registered on the app, so no auth config and no re-consent can ever request them.

  2. The Zoom toolkit ships no webinar-creation tool (17 tools; webinar coverage is only ADD_A_WEBINAR_REGISTRANT / GET_A_WEBINAR / LIST_WEBINARS / LIST_WEBINAR_PARTICIPANTS). Yet COMPOSIO_SEARCH_TOOLS answers webinar-creation use cases with adjacent tools as primary_tool_slugs (ZOOM_ADD_A_WEBINAR_REGISTRANT, then ZOOM_CREATE_A_MEETING — a meeting, not a webinar) instead of flagging the capability gap.

  3. COMPOSIO_REMOTE_WORKBENCH's proxy_execute offers raw Zoom API access on that same managed auth, so the agent reasonably fell back to POST /users/me/webinars — and Zoom rejected it with a scope error the platform can never satisfy. Nothing distinguishes "scope not granted (re-consent may fix)" from "scope not requestable by this app (re-consent cannot fix)", so the agent looped on MANAGE_CONNECTIONS reinitiate and the end user completed a real OAuth consent, approved every scope offered, and got the identical error. Their (accurate) report: "I gave all permissions that were asked for but we still don't seem to have the right permission."

Expected: either webinar creation is supported end-to-end (scope registered + tool available), or the platform surfaces (search, workbench, connection manager) tell the agent the operation is unsupported instead of routing it into an OAuth loop that cannot succeed.

Note also the half-surface inconsistency: the app requests webinar:write:registrant and ships ADD_A_WEBINAR_REGISTRANT, but registrants can only be added to webinars the connected account cannot create through Composio.

Steps to Reproduce

All inside one Tool Router session (agentic flow; customer values masked):

  1. COMPOSIO_SEARCH_TOOLS with use case "Create and configure a Zoom webinar event with attendee registration for a product launch" → returns primary_tool_slugs: ["ZOOM_ADD_A_WEBINAR_REGISTRANT"], related ZOOM_GET_A_WEBINAR, ZOOM_LIST_WEBINARS. A follow-up query "Create a new Zoom webinar with registration enabled and configure its title, description, date, duration, timezone, and approval settings" → primary_tool_slugs: ["ZOOM_CREATE_A_MEETING"]. Neither response signals that webinar creation is unsupported.
  2. COMPOSIO_MANAGE_CONNECTIONS (toolkits: ["zoom"]) → managed auth config is auto-created, end user completes the hosted OAuth flow and approves the full consent screen → connection ACTIVE.
  3. Agent falls back to COMPOSIO_REMOTE_WORKBENCHproxy_execute("POST", "/users/me/webinars", "zoom", body={...}) (see minimal example) → Zoom returns the 400 scope error below.
  4. COMPOSIO_MANAGE_CONNECTIONS with reinitiate_all: true → "All connections are active" (was_reinitiated: false); retry of step 3 → byte-identical 400. The loop cannot converge: re-consent can only offer scopes the managed app registers.
  5. Root-cause check: GET /api/v3/toolkits/zoomcomposio_managed_auth[0].scopes.available contains no webinar:write:webinar / webinar:update:webinar / webinar:delete:webinar (only webinar read scopes + webinar:write:registrant), and the connected account's granted scope string exactly equals the auth config's requested list — the user withheld nothing.

Minimal Reproducible Example

bash
# Executed inside COMPOSIO_REMOTE_WORKBENCH (customer strings masked)
payload = {
    "topic": "<masked webinar title>",
    "type": 5,
    "start_time": "2026-09-10T11:00:00",
    "duration": 60,
    "timezone": "America/Los_Angeles",
    "agenda": "<masked>",
    "settings": {
        "host_video": True,
        "panelists_video": True,
        "practice_session": True,
        "approval_type": 0,
        "registration_type": 1,
        "audio": "both",
        "auto_recording": "cloud",
        "question_and_answer": {"enable": True, "allow_anonymous_questions": True},
    },
}
result, error = proxy_execute("POST", "/users/me/webinars", "zoom", body=payload)


Proof it can never succeed with the managed app:


curl -s -H "x-api-key: $COMPOSIO_API_KEY" https://backend.composio.dev/api/v3/toolkits/zoom \
  | jq '.composio_managed_auth[0].scopes.available | map(select(contains("webinar")))'
# ["webinar:read:webinar", "webinar:read:list_registrants", "webinar:read:list_webinars",
#  "webinar:read:list_past_participants", "webinar:read:participant", "webinar:write:registrant"]

Error Output / Stack Trace

bash
COMPOSIO_REMOTE_WORKBENCH result (stdout), verbatim:

Helper Function Error:Bad Request Error:proxy_execute:API returned status 400: Invalid access token, does not contain scopes:[webinar:write:webinar, webinar:write:webinar:admin].
{'error': 'API returned status 400: Invalid access token, does not contain scopes:[webinar:write:webinar, webinar:write:webinar:admin].'}

Secondary papercut: a first attempt used the documented Zoom path prefix and got a 404 from the proxy:

Helper Function Error:Not Found Error:proxy_execute:API returned status 404: This API endpoint is not recognized.
(call was proxy_execute("POST", "/v2/users/me/webinars", "zoom", ...) — the proxy wants paths without the /v2 prefix, which isn't documented in the workbench guidance)

Reproducibility

  • Always reproducible
  • Intermittent / Sometimes
  • Happened once, can’t reproduce

Additional Context or Screenshots

Identifiers for your logs (Composio-side only, happy to share more privately):

  • Auth config: ac_vQWJvXTaoo3_ (Composio-managed OAUTH2, auto-created by the Tool Router session)
  • Connected account: ca_9iWNGz05KNxL (status ACTIVE; granted scope string == requested list)
  • Tool Router session id: farm; occurred ~2026-08-20 17:56–18:01 UTC

Requested fixes, in order of value:

  1. Register webinar:write:webinar, webinar:update:webinar, webinar:delete:webinar on the managed Zoom app and add them to the toolkit's available scopes.
  2. Ship first-class webinar CRUD tools (e.g. ZOOM_CREATE_A_WEBINAR) — the toolkit currently has ADD_A_WEBINAR_REGISTRANT but no way to create the webinar it registers people into.
  3. Make COMPOSIO_SEARCH_TOOLS say when a use case is unsupported by a toolkit instead of returning adjacent tools as primary_tool_slugs (here: a registrant tool, then a meeting tool, for a webinar-creation query).
  4. Have proxy_execute / MANAGE_CONNECTIONS distinguish "scope not granted (re-consent may fix)" from "scope not requestable by this app (re-consent cannot fix)" — e.g. compare the scope named in the provider error against the managed app's available scopes and annotate the result. This is what turns a capability gap into an end-user OAuth loop today.

Zoom-side note for anyone hitting this: even with the scope, POST /users/me/webinars also requires the connected Zoom user to be Licensed with the Webinar add-on (Basic accounts get a plan error) — worth mentioning in the tool/toolkit docs once creation is supported.