Engineering · · 4 min read
AI agent troubleshooting: find the question behind the failure
Find answers to 40 practical questions about agent loops, Slack duplicates, Notion retrieval, Stripe retries, MCP permissions, GitHub access, context cost, and approvals.
The agent repeated itself. The bot replied twice. The document exists and the answer ignores it. Start with the observable behavior, then follow the request to where it went wrong.
These guides answer questions from public developer discussions, with follow-ups that fix the workflow. Each links the original reports and provider documentation. A historical bug report explains why a question matters; check your installed version for it.
Choose the symptom before changing the prompt#
| What you see | Start by inspecting |
|---|---|
| The same tool runs repeatedly | Result delivery, progress, stop conditions |
| Two identical Slack replies | Event delivery, worker ownership, send history |
| A Notion title with no usable content | Page-body retrieval, access, pagination, nested blocks |
| Repeated Stripe business actions | Event identity, operation identity, uncertain outcomes |
| A connected tool refuses an action | Actor, target, scope, execution-time permission |
| Each short follow-up costs more | Included history, tool results, reported usage |
| Approving work repeats an earlier step | Replay boundaries and side effects |
| GitHub returns 404 or 403 | Route, repository selection, token type, response headers |
Repeated tool calls#
- Why does the agent call the same tool after it has the answer?
- Should I increase the iteration limit?
- How do I stop repeated calls without breaking polling?
- Why does a parsing error turn into another tool call?
- What should the agent return when it cannot finish?
Slack replies#
- Why does one Slack message produce multiple bot replies?
- Does Slack retry events when my agent takes too long?
- Should I discard every event with a retry header?
- Why can duplicates continue after I deduplicate events?
- How do I reply in the original thread rather than starting another one?
Notion retrieval#
- Why does retrieving a Notion page return properties but no body?
- Why do I get object_not_found even though I can open the page?
- How do I retrieve more than the first batch of results?
- Why are nested paragraphs or list items missing?
- Can Notion search enumerate everything the agent needs?
Stripe retries#
- Can Stripe deliver the same webhook more than once?
- Why does checking the event ID still produce duplicates?
- Are webhook events guaranteed to arrive in order?
- Should a retry use the same idempotency key?
- What should happen after a timeout or a saved server error?
MCP permissions#
- Does authenticating to an MCP server authorize every tool call?
- How do I restrict individual tools or their arguments?
- Whose identity should a shared MCP server use?
- Can I pass the client's access token through to another API?
- How should an agent request additional permission or approval?
Context and cost#
- Does previous_response_id make earlier conversation tokens free?
- Does prompt caching remember the answer or skip the tool call?
- Why are cached tokens zero even when requests look similar?
- Should I summarize conversation history to reduce cost?
- How do I choose between recent messages, summaries, and retrieved memory?
Approval and resume#
- Why does code before interrupt execute again?
- How do I stop an approval resume from repeating a side effect?
- Why does the graph resume the wrong conversation or start over?
- How do I handle multiple approvals in parallel subgraphs?
- Does an empty next field prove the task is finished?
GitHub access#
- Why does the API return 404 when I can see the repository?
- What does resource not accessible by integration mean?
- Can GITHUB_TOKEN access another repository?
- Why does one repository operation work while another fails with the same token?
- How do I distinguish a permission failure from a rate limit?
Keep the evidence that makes the next attempt useful#
Save the logical task, exact operation, non-secret connection identity, target, first failure, and last known result. For a write, record whether it was never sent, confirmed, or uncertain.
To compare a fix, replay the original failure and a legitimate neighboring case: a loop detector still allows status polling, deduplication still accepts a new request with the same text, and an access fix still denies the wrong repository.
See the full troubleshooting series, the connected-system workflow guides, or the connector directory.