Monday morning. You open Gmail and scan subjects for anything urgent. How many steps before real work begins?
Open browser, go to Gmail, scan 40 subjects, flag three, close. Five minutes minimum, every week.
In Python, that scan is one call. You ask Composio to fetch up to N messages, you get back a dict with a messages key, and len(messages) is your count. No browser needed:
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 40})
count = len(result.get("messages", []))
print(f"Found {count} emails in your inbox")Wait — that's actually my inbox coming back? Real emails, right now?
Real emails. Your inbox. Right now. Welcome to the part where automation gets personal — your data, not toy data.
Why .get("messages", []) instead of just result["messages"]? I thought bracket access was the standard way.
On an empty inbox, Gmail may drop the messages key entirely. result["messages"] raises KeyError and your script crashes. .get("messages", []) falls back to an empty list, so len() returns 0 cleanly. Make .get(key, default) your reflex for every API response dict. Here's the full function:
def count_emails(max_results: int) -> int:
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": max_results})
messages = result.get("messages", [])
return len(messages)Five lines and I've replaced my entire Monday inbox scan. My ops brain is having a moment.
That moment never gets old. Every app in this track follows the same shape — one action, one dict response, one safe parse. The count is a starting point; the message IDs inside each dict unlock the rest.
Every Composio action in this track has the same shape: call toolset.execute_action with an Action enum and a params dict, parse what comes back.
Gmail returns {"messages": [{"id": "abc"}, {"id": "def"}]}. The messages key holds a list; each object has an id you can use to fetch full details. Today we just need the count.
.get() beats []| Access | Empty inbox |
|---|---|
result["messages"] | KeyError — crashes |
result.get("messages", []) | [] — len() returns 0 |
.get(key, default) is the reflex for every API response dict you'll parse. One habit, zero crashes.
Monday morning. You open Gmail and scan subjects for anything urgent. How many steps before real work begins?
Open browser, go to Gmail, scan 40 subjects, flag three, close. Five minutes minimum, every week.
In Python, that scan is one call. You ask Composio to fetch up to N messages, you get back a dict with a messages key, and len(messages) is your count. No browser needed:
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 40})
count = len(result.get("messages", []))
print(f"Found {count} emails in your inbox")Wait — that's actually my inbox coming back? Real emails, right now?
Real emails. Your inbox. Right now. Welcome to the part where automation gets personal — your data, not toy data.
Why .get("messages", []) instead of just result["messages"]? I thought bracket access was the standard way.
On an empty inbox, Gmail may drop the messages key entirely. result["messages"] raises KeyError and your script crashes. .get("messages", []) falls back to an empty list, so len() returns 0 cleanly. Make .get(key, default) your reflex for every API response dict. Here's the full function:
def count_emails(max_results: int) -> int:
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": max_results})
messages = result.get("messages", [])
return len(messages)Five lines and I've replaced my entire Monday inbox scan. My ops brain is having a moment.
That moment never gets old. Every app in this track follows the same shape — one action, one dict response, one safe parse. The count is a starting point; the message IDs inside each dict unlock the rest.
Every Composio action in this track has the same shape: call toolset.execute_action with an Action enum and a params dict, parse what comes back.
Gmail returns {"messages": [{"id": "abc"}, {"id": "def"}]}. The messages key holds a list; each object has an id you can use to fetch full details. Today we just need the count.
.get() beats []| Access | Empty inbox |
|---|---|
result["messages"] | KeyError — crashes |
result.get("messages", []) | [] — len() returns 0 |
.get(key, default) is the reflex for every API response dict you'll parse. One habit, zero crashes.
Create a free account to get started. Paid plans unlock all tracks.