Your doc_to_post chains Docs and LinkedIn. But what if an OAuth token expires mid-workflow — Gmail returns AUTH_REQUIRED instead of a send confirmation? What happens to your capstone?
After doc_to_post I've been assuming the connections stay live. But OAuth tokens expire. If Gmail returns AUTH_REQUIRED during the capstone run, does the whole workflow crash?
Without error handling, yes — it crashes. With safe_send, the AUTH_REQUIRED case becomes a graceful status return instead of an exception. The capstone keeps running even if one email fails:
try:
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {"to": to, "subject": subject, "body": body})
if "AUTH_REQUIRED" in str(result):
return {"status": "auth_required", "to": to}
return result
except Exception as e:
return {"status": "error", "message": str(e)}When does AUTH_REQUIRED appear? Is it an exception or a string in the response?
Composio surfaces AUTH_REQUIRED:<action_slug> as a string inside the response dict when OAuth fails — it's not a Python exception. So you check str(result) for the string instead of catching an exception. Here's the full function:
def safe_send(to: str, subject: str, body: str) -> dict:
try:
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {"to": to, "subject": subject, "body": body})
if "AUTH_REQUIRED" in str(result):
print(f"Auth required — reconnect Gmail")
return {"status": "auth_required", "to": to}
print(f"Sent to {to}")
return result
except Exception as e:
print(f"Send failed: {e}")
return {"status": "error", "message": str(e)}So the capstone can send 10 welcome emails and if one fails with AUTH_REQUIRED, the rest still go out. The workflow doesn't stop at the first error.
Fault-tolerant automation. That's the difference between a script that runs once and a tool you trust to run every Monday.
AUTH_REQUIRED is just an app asking you to log in again — expected, handled, not a crisis. That framing changes how I think about errors.
Log every failed send with the recipient address. When you reconnect the Gmail account and re-run, you need to know which sends to retry. {"status": "auth_required", "to": to} gives you exactly that.
Composio surfaces AUTH_REQUIRED:<slug> as a string in the response when OAuth expires. Handling this gracefully keeps your capstone workflow alive even when a single token lapses mid-run.
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {...})
if "AUTH_REQUIRED" in str(result):
return {"status": "auth_required"}AUTH_REQUIRED in str(result)try/except Exception for unexpected errorsAlways log the failed recipient in the status dict. You need to know which sends to retry after reconnecting.
Your doc_to_post chains Docs and LinkedIn. But what if an OAuth token expires mid-workflow — Gmail returns AUTH_REQUIRED instead of a send confirmation? What happens to your capstone?
After doc_to_post I've been assuming the connections stay live. But OAuth tokens expire. If Gmail returns AUTH_REQUIRED during the capstone run, does the whole workflow crash?
Without error handling, yes — it crashes. With safe_send, the AUTH_REQUIRED case becomes a graceful status return instead of an exception. The capstone keeps running even if one email fails:
try:
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {"to": to, "subject": subject, "body": body})
if "AUTH_REQUIRED" in str(result):
return {"status": "auth_required", "to": to}
return result
except Exception as e:
return {"status": "error", "message": str(e)}When does AUTH_REQUIRED appear? Is it an exception or a string in the response?
Composio surfaces AUTH_REQUIRED:<action_slug> as a string inside the response dict when OAuth fails — it's not a Python exception. So you check str(result) for the string instead of catching an exception. Here's the full function:
def safe_send(to: str, subject: str, body: str) -> dict:
try:
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {"to": to, "subject": subject, "body": body})
if "AUTH_REQUIRED" in str(result):
print(f"Auth required — reconnect Gmail")
return {"status": "auth_required", "to": to}
print(f"Sent to {to}")
return result
except Exception as e:
print(f"Send failed: {e}")
return {"status": "error", "message": str(e)}So the capstone can send 10 welcome emails and if one fails with AUTH_REQUIRED, the rest still go out. The workflow doesn't stop at the first error.
Fault-tolerant automation. That's the difference between a script that runs once and a tool you trust to run every Monday.
AUTH_REQUIRED is just an app asking you to log in again — expected, handled, not a crisis. That framing changes how I think about errors.
Log every failed send with the recipient address. When you reconnect the Gmail account and re-run, you need to know which sends to retry. {"status": "auth_required", "to": to} gives you exactly that.
Composio surfaces AUTH_REQUIRED:<slug> as a string in the response when OAuth expires. Handling this gracefully keeps your capstone workflow alive even when a single token lapses mid-run.
result = toolset.execute_action(Action.GMAIL_SEND_EMAIL, {...})
if "AUTH_REQUIRED" in str(result):
return {"status": "auth_required"}AUTH_REQUIRED in str(result)try/except Exception for unexpected errorsAlways log the failed recipient in the status dict. You need to know which sends to retry after reconnecting.
Create a free account to get started. Paid plans unlock all tracks.