{"record":{"id":"bd25975e7050d06e","repo":"Significant-Gravitas/AutoGPT","slug":"some-webhooks-linked-to-these-credentials-are-stil","errorCode":null,"errorMessage":"Some webhooks linked to these credentials are still in use by an agent","messagePattern":"Some webhooks linked to these credentials are still in use by an agent","errorType":"exception","errorClass":"NeedConfirmation","httpStatus":null,"severity":"warning","filePath":"autogpt_platform/backend/backend/api/features/integrations/router.py","lineNumber":1179,"sourceCode":"async def remove_all_webhooks_for_credentials(\n    user_id: str, credentials: Credentials, force: bool = False\n) -> None:\n    \"\"\"\n    Remove and deregister all webhooks that were registered using the given credentials.\n\n    Params:\n        user_id: The ID of the user who owns the credentials and webhooks.\n        credentials: The credentials for which to remove the associated webhooks.\n        force: Whether to proceed if any of the webhooks are still in use.\n\n    Raises:\n        NeedConfirmation: If any of the webhooks are still in use and `force` is `False`\n    \"\"\"\n    webhooks = await get_all_webhooks_by_creds(\n        user_id, credentials.id, include_relations=True\n    )\n    if any(w.triggered_nodes or w.triggered_presets for w in webhooks) and not force:\n        raise NeedConfirmation(\n            \"Some webhooks linked to these credentials are still in use by an agent\"\n        )\n    for webhook in webhooks:\n        # Unlink all nodes & presets\n        for node in webhook.triggered_nodes:\n            await set_node_webhook(node.id, None)\n        for preset in webhook.triggered_presets:\n            await set_preset_webhook(user_id, preset.id, None)\n\n        # Prune the webhook\n        webhook_manager = get_webhook_manager(ProviderName(credentials.provider))\n        success = await webhook_manager.prune_webhook_if_dangling(\n            user_id, webhook.id, credentials\n        )\n        if not success:\n            logger.warning(f\"Webhook #{webhook.id} failed to prune\")\n\n","sourceCodeStart":1161,"sourceCodeEnd":1197,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/integrations/router.py#L1161-L1197","documentation":"_remove_webhooks_by_credentials first finds all webhooks linked to the credentials being deleted. If any of them are still attached to graph nodes (triggered_nodes) or agent presets (triggered_presets) and force is False, it raises NeedConfirmation('Some webhooks linked to these credentials are still in use by an agent'). This is not an HTTP error: the router layer catches NeedConfirmation and turns it into a confirmation request (typically HTTP 409-style response asking the caller to re-send with force=true), preventing accidental removal of webhooks that live agents depend on.","triggerScenarios":"DELETE /integrations/{provider}/credentials/{id} (or the bulk variant) while an agent graph node or preset still references a webhook created with those credentials; the credentials UI deleting a connection whose webhook block is still wired into a saved agent.","commonSituations":"Cleaning up 'unused' credentials without checking agents; deleting a connection after a teammate built an agent on it; leftover agent presets in the library referencing old webhooks.","solutions":["Inspect the response identifying which agents/nodes use the webhooks, unlink them (edit the agent or delete it), then retry the delete.","If you accept that those agents lose their trigger, re-send the request with force=true — webhooks get unlinked from nodes/presets and pruned.","Audit agents via GET /integrations/webhooks (include_relations) to see triggered_nodes/triggered_presets before deleting credentials."],"exampleFix":"# before\nDELETE /integrations/github/credentials/$CRED_ID            # -> confirmation required\n\n# after (once you accept unlinking agents)\nDELETE /integrations/github/credentials/$CRED_ID?force=true","handlingStrategy":"fallback","validationCode":"# Check usage before deleting credentials\nwebhooks = (await client.get(\"/integrations/webhooks\")).json()\nin_use = [w for w in webhooks if w.get(\"credentials_id\") == cred_id\n          and (w.get(\"triggered_nodes\") or w.get(\"triggered_presets\"))]\nif in_use:\n    ask_user_or_unlink(in_use)  # decide before calling DELETE","typeGuard":null,"tryCatchPattern":"resp = await client.delete(f\"/integrations/{provider}/credentials/{cred_id}\")\nif resp.status_code == 409 or \"still in use\" in resp.text:  # NeedConfirmation surfaced\n    if user_confirmed():\n        await client.delete(f\"/integrations/{provider}/credentials/{cred_id}?force=true\")\n    else:\n        unlink_and_retry()","preventionTips":["Check triggered_nodes/triggered_presets on webhooks before deleting their credentials.","Handle the confirmation response programmatically instead of treating it as an error.","Clean up agents that reference webhooks before credential teardown."],"tags":["credentials","webhook","confirmation-required","force-delete"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}