Tutorial: Email Digest Agent
Build a complete agent that summarizes your Gmail emails and notifies you on Slack.
Goal
In this tutorial, you'll create an agent that:
- Connects to Gmail and Slack
- Fetches unread emails from the last 24 hours
- Summarizes each email with AI
- Sends a recap to a Slack channel
- Runs automatically every morning at 8am
Prerequisites
- A running Appstrate instance (Quickstart)
- A configured LLM model (Settings > Models)
- A Google account (for Gmail)
- A Slack workspace (for notifications)
1⃣ Step 1 — Create the Agent
Click New agent in the sidebar and configure:
- Name:
email-daily-digest - Description: Daily email summary
Prompt
You are an assistant that summarizes emails.
1. Use Gmail to fetch unread emails from the last 24 hours
2. For each email, write a 2-3 line summary with:
- Sender
- Subject
- Key points / required actions
3. Sort emails by priority (urgent first)
4. Send the recap on Slack in the #daily-digest channel
Slack message format:
*Daily Digest — {date}*
{count} unread emails
---
*URGENT*
• {subject} — from {sender}
{summary}
*NORMAL*
• {subject} — from {sender}
{summary}
If no emails are found, send "No unread emails in the last 24h "2⃣ Step 2 — Connect Gmail
- Go to the agent's page
- In the Providers section, click Connect next to Gmail
- Authenticate with your Google account
- Authorize read access to emails
The agent can now read your emails via the sidecar proxy, without ever having direct access to your OAuth tokens.
Via the API
curl -X POST "http://localhost:3000/api/connections/connect/@appstrate/gmail" \
-H "Authorization: Bearer ask_your_key" \
-H "Content-Type: application/json" \
-d '{"scopes": ["https://www.googleapis.com/auth/gmail.readonly"]}'The response contains { authUrl, state }; open authUrl in a browser and complete the OAuth flow. The API key is pinned to an application, so you do not need an X-App-Id header.
3⃣ Step 3 — Connect Slack
- In the Providers section, click Connect next to Slack
- Select your Slack workspace
- Authorize message sending
Via the API
curl -X POST "http://localhost:3000/api/connections/connect/@appstrate/slack" \
-H "Authorization: Bearer ask_your_key" \
-H "Content-Type: application/json" \
-d '{"scopes": ["chat:write"]}'Same pattern as Gmail: the response returns authUrl + state, complete the OAuth flow in a browser.
4⃣ Step 4 — Test the Agent
Click Run. The agent will:
- Start an isolated Docker container
- Read your emails via the sidecar (credentials auto-injected)
- Summarize each email with the LLM
- Post the recap to Slack
- Finish and destroy the container
Follow the execution in real time through the SSE logs.
Via the API
# Start the run
curl -X POST "http://localhost:3000/api/agents/@scope/agent-name/run" \
-H "Authorization: Bearer ask_your_key"
# Follow logs in real time
curl -N "http://localhost:3000/api/realtime/runs/run_xxx?token=ask_your_key"5⃣ Step 5 — Add an Output Schema
To structure the agent's result, add an output schema:
{
"schema": {
"type": "object",
"properties": {
"emailCount": {
"type": "number",
"description": "Number of processed emails"
},
"summaries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"from": { "type": "string" },
"subject": { "type": "string" },
"summary": { "type": "string" },
"priority": { "type": "string", "enum": ["urgent", "normal", "low"] }
}
}
},
"slackMessageSent": {
"type": "boolean"
}
}
}
}This schema is injected into the container for LLM constrained decoding — the agent will produce structured JSON in addition to the Slack message.
6⃣ Step 6 — Schedule Daily Execution
Create a schedule to run the agent every morning:
curl -X POST "http://localhost:3000/api/agents/@scope/email-daily-digest/schedules" \
-H "Authorization: Bearer ask_your_key" \
-H "Content-Type: application/json" \
-d '{
"connectionProfileId": "cp_xxx",
"cronExpression": "0 8 * * 1-5",
"name": "Email summary 8am"
}'The agent will now run every weekday at 8am.
7⃣ Step 7 — Add a Webhook (Optional)
To be notified on failures:
curl -X POST "http://localhost:3000/api/webhooks" \
-H "Authorization: Bearer ask_your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/appstrate",
"events": ["run.failed", "run.timeout"],
"payloadMode": "summary"
}'Going Further
- Persistent state — add
result.stateto remember the last processed email and avoid duplicates - Configuration — add a config schema to make the Slack channel and time window configurable
- Skills — attach a skill with classification instructions specific to your business
- End-users — use impersonation to run the agent on behalf of each user of your product