Yesterday's count_emails gave you a list of dicts — and each dict had an id field. You saw the count. You didn't look inside the messages. What do you think is actually in there?
I assume the id is just a handle, not the email itself. The real content — subject, sender, body — must live somewhere else?
Correct. The fetch list gives you lightweight stubs. To read a single email in full, you pass one of those IDs to a separate action — GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID. The response is a richer dict:
result = toolset.execute_action(
Action.GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID,
{"message_id": msg_id}
)
# result contains: subject, from, body, labelsSo the same toolset.execute_action call, but a different Action and a different param name? And I just return whatever comes back?
Exactly that. The Composio response is already structured — subject, sender, plain-text body, label list. You don't need to reshape it. Return the dict and your caller can read any field they need. That's the power of a thin wrapper: one call, full record.
That's it? I half-expected to decode a base64 payload or parse MIME headers. It just... comes back as fields?
The Composio layer handles MIME decoding for you. Your job is to pass the right ID and return the dict clean. No base64, no headers, no grief. Here's the full function:
def get_email(msg_id: str) -> dict:
result = toolset.execute_action(
Action.GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID,
{"message_id": msg_id}
)
print(f"Fetched email — subject: {result.get('subject', '(no subject)')}")
return resultFive lines and I can pull any email by ID. I could filter my inbox for flagged messages, grab their IDs from count_emails, and inspect each one without ever opening a browser.
That's exactly the shape of an inbox triage script. IDs in, full records out — the filter logic goes in the middle. Keep each function narrow: one ID in, one dict out. The workflow is just calling them in the right order.
GMAIL_FETCH_EMAILS returns lightweight stubs — each with an id. GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID takes one of those IDs and returns the full record.
| Key | Value |
|---|---|
subject | Email subject line |
from | Sender address |
body | Plain-text body |
labels | List of Gmail label strings |
Returning the raw response keeps the function composable — the caller decides which fields to read. A triage script reads subject; a labelling script reads labels. One function, many uses.
Yesterday's count_emails gave you a list of dicts — and each dict had an id field. You saw the count. You didn't look inside the messages. What do you think is actually in there?
I assume the id is just a handle, not the email itself. The real content — subject, sender, body — must live somewhere else?
Correct. The fetch list gives you lightweight stubs. To read a single email in full, you pass one of those IDs to a separate action — GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID. The response is a richer dict:
result = toolset.execute_action(
Action.GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID,
{"message_id": msg_id}
)
# result contains: subject, from, body, labelsSo the same toolset.execute_action call, but a different Action and a different param name? And I just return whatever comes back?
Exactly that. The Composio response is already structured — subject, sender, plain-text body, label list. You don't need to reshape it. Return the dict and your caller can read any field they need. That's the power of a thin wrapper: one call, full record.
That's it? I half-expected to decode a base64 payload or parse MIME headers. It just... comes back as fields?
The Composio layer handles MIME decoding for you. Your job is to pass the right ID and return the dict clean. No base64, no headers, no grief. Here's the full function:
def get_email(msg_id: str) -> dict:
result = toolset.execute_action(
Action.GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID,
{"message_id": msg_id}
)
print(f"Fetched email — subject: {result.get('subject', '(no subject)')}")
return resultFive lines and I can pull any email by ID. I could filter my inbox for flagged messages, grab their IDs from count_emails, and inspect each one without ever opening a browser.
That's exactly the shape of an inbox triage script. IDs in, full records out — the filter logic goes in the middle. Keep each function narrow: one ID in, one dict out. The workflow is just calling them in the right order.
GMAIL_FETCH_EMAILS returns lightweight stubs — each with an id. GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID takes one of those IDs and returns the full record.
| Key | Value |
|---|---|
subject | Email subject line |
from | Sender address |
body | Plain-text body |
labels | List of Gmail label strings |
Returning the raw response keeps the function composable — the caller decides which fields to read. A triage script reads subject; a labelling script reads labels. One function, many uses.
Create a free account to get started. Paid plans unlock all tracks.