Adding to this, and correcting two points above.
The 500 file and 512 MB figures do not apply here. Those are knowledge source limits, SharePoint and OneDrive connections and files added as knowledge. Conversational attachments are a different upload path with different limits, and the two get conflated constantly. There is a Microsoft Q&A thread where exactly this came up, a 15 to 16 MB conversational file processing limit against 512 MB for knowledge scenarios, and the answer notes explicitly that the larger figure refers to a different upload path. So do not expect other channels to give you 500 attachments per conversation.
I doubt this is a Teams or Bot Framework limit. The error wording is "this conversation has reached its 20-file upload limit", which reads as harness-level rather than a platform rejection. Teams platform errors do not phrase themselves that way. The GitHub Copilot harness runs each task in a sandbox with its own virtual filesystem, and it does enforce its own file limits, documented at 10 MB per created file. So the counter most likely lives in harness conversation state.
That actually explains your findings rather than contradicting them. If the counter is harness-side, no Teams-side action, deleting chat history, re-adding the app, will ever reset it. Which is what you observed three times.
On the 60 minute session point, be careful. Session and conversation are different things in Copilot Studio. A new session after inactivity does not create a new conversationId in Teams. So telling users to wait an hour will not clear the counter, and I would not build that expectation.
The test that would settle question 3. Run the same agent in a second channel, the test pane or M365 Copilot chat, and count attachments there. If each surface has its own independent 20, the counter is per conversation and your read is correct, which means the limit is effectively permanent per user in a Teams 1:1 since that conversationId is stable. If the count is shared, it is per agent or per user and something quite different is going on. Either answer tells you what to tell your users, which is what you actually need right now.
One interim workaround. The limit is per conversation, and a Teams group chat or channel conversation has a different conversationId from a 1:1. So moving a user into a fresh group chat with the agent gives a fresh counter. Ugly, and not something to build a process on, but it unblocks someone mid-task.
On question 5, yes. Move intake out of chat. This is also where the harness is pointed, the documented example for it is an accounts payable process where the agent reads invoices, matches them to purchase orders, and routes exceptions, which is your pattern and does not assume chat upload. Users drop files in a SharePoint library, the agent picks them up, and you are no longer bound by a conversation-scoped counter. You also get an audit trail and reprocessing, which chat attachments never give you.
Worth filing. An undocumented hard limit that blocks a core business process is a legitimate docs gap at minimum. Raise it through the Power Platform admin center and also use the feedback link on the tools overview page, since the limits section there lists the 10 MB created file cap and the MCP concurrency cap but not this one.