Why the label beats a timestamp
The naive approach is to record a timestamp and only process threads newer than the last run. It sounds clean. In practice it breaks silently: if a thread arrives one second before your trigger fires and the script errors out partway through, that thread falls into a gap between timestamps and never gets forwarded.
A label is idempotent. The search query appends '-label:auto-forwarded', so any thread that received the label is permanently excluded from future runs regardless of when the trigger fires. The first time I hit this gap problem I had forwarded the same invoice three times before I understood why; switching to a label fixed it immediately.
Gmail's search grammar handles the exclusion natively. You are not writing filter logic in code — you are pushing the state into Gmail itself, where it belongs.