Automated pipeline that syncs customer meeting recordings from Grain into a structured Notion Account Tracking database. Built to run as Oz cloud agents.
After each day of customer meetings, Grainiac:
- Pulls all external meeting recordings from Grain for a given date
- Identifies the customer company from participant email domains
- Fetches the full transcript for each meeting
- Analyzes the transcript against a structured enterprise customer template
- Creates or updates the company's page in the Notion Account Tracking database
The result is a living record per customer that tracks stakeholders, tech stack, requirements, use cases, deal status, follow-ups, and more — all extracted directly from meeting transcripts.
Copy and paste this prompt into Warp and follow along:
Set up Grainiac: clone https://github.com/warpdotdev/account-status-agent-oss.git if it isn't already cloned, then read the grainiac-setup skill in the repo and follow its instructions.
The setup skill walks through everything in the manual steps below interactively: cloning, Oz CLI auth, Notion configuration, secrets, environment creation, a test run, and an optional daily schedule.
The same steps, as a human-readable reference:
-
Set up Notion.
- Create a database in Notion (or use an existing one) for account tracking.
- Note the title property name. Every database has exactly one title property; new databases call it
Name, while Grainiac assumesCompany. Rename it toCompany, or setGRAINIAC_NOTION_TITLE_PROPERTYto match. - Create an internal integration at https://www.notion.so/my-integrations and copy its token into
GRAINIAC_NOTION_TOKEN. - Share the database with the integration (database
⋯menu → Connections → add your integration). Without this, the Notion API returns 404s. - Copy the database ID from the URL —
notion.so/<workspace>/<DATABASE_ID>?v=...— intoGRAINIAC_NOTION_DATABASE_ID.
No other database properties are required; everything else lives in the page body, which follows the Notion template.
-
Install and authenticate the Oz CLI. The CLI ships with the Warp app; otherwise see Installing the CLI. Then sign in:
oz login
For CI or headless environments, export an API key instead:
export WARP_API_KEY="wk-...". -
Add secrets. Warp injects team secrets into cloud runs as environment variables. Each command prompts for the value securely:
oz secret create --team GRAINIAC_GRAIN_TOKEN oz secret create --team GRAINIAC_NOTION_TOKEN oz secret create --team GRAINIAC_NOTION_DATABASE_ID oz secret create --team GRAINIAC_INTERNAL_DOMAIN
Add
GRAINIAC_SLACK_TOKENandGRAINIAC_SLACK_CHANNELas well if you use the Slack summary skill. -
Create an Oz environment named
grainiacwith this repo checked out. The orchestrator discovers the environment by this exact name, so it must match:oz environment create --team \ --name grainiac \ --repo <owner/repo> \ --docker-image warpdotdev/dev-base:latest
The scripts only need the Python standard library, so the base image is enough. Copy the environment ID from the output (or
oz environment list) for the next steps. -
Run manually (replace
<ENV_ID>with yourgrainiacenvironment ID):oz agent run-cloud \ --environment <ENV_ID> \ --prompt "Read the grainiac-orchestrator skill for instructions. Process today's meetings."
-
Schedule a daily run:
oz schedule create \ --name "Grainiac Daily" \ --cron "0 5 * * *" \ --environment <ENV_ID> \ --prompt "Read the grainiac-orchestrator skill for instructions. Process today's meetings."
This runs at 05:00 UTC (roughly 9–10pm Pacific depending on DST).
| Variable | Required | Description |
|---|---|---|
GRAINIAC_GRAIN_TOKEN |
Yes | Grain personal access token |
GRAINIAC_NOTION_TOKEN |
Yes | Notion integration token |
GRAINIAC_NOTION_DATABASE_ID |
Yes | Notion database ID for the Account Tracking database |
GRAINIAC_NOTION_TITLE_PROPERTY |
No | Name of the database's title property that holds the company name (default: Company) |
GRAINIAC_SLACK_TOKEN |
Slack skill only | Slack Bot OAuth token (xoxb-...) |
GRAINIAC_SLACK_CHANNEL |
Slack skill only | Slack channel to post summaries to (e.g. #meeting-summaries) |
GRAINIAC_INTERNAL_DOMAIN |
Recommended | Your company's email domain for filtering internal participants (e.g. yourcompany.com) |
GRAINIAC_TIMEZONE |
No | Timezone for resolving "today" (defaults to America/Los_Angeles) |
grainiac/
├── .agents/
│ └── skills/
│ ├── grainiac-setup/
│ │ └── SKILL.md # Oz skill: guided end-to-end deployment
│ ├── grainiac-orchestrator/
│ │ └── SKILL.md # Oz skill for the main orchestrator agent
│ ├── grainiac-meeting-processor/
│ │ ├── SKILL.md # Oz skill for per-meeting child agents
│ │ └── references/
│ │ └── notion-template.md # Notion page template (single source of truth)
│ └── grainiac-slack-summary/
│ └── SKILL.md # Oz skill: summarize a recording to Slack
├── scripts/
│ ├── grain_client.py # Grain API client (list, get, transcript, hydrate)
│ ├── notion_client.py # Notion API client (CRUD, block builders, section finders)
│ └── fetch_daily_meetings.py # CLI: fetch external meetings for a date
├── .env.example # Sample environment variables for local testing
├── LICENSE
├── README.md
└── SECURITY.md
Orchestrator agent (.agents/skills/grainiac-orchestrator/) — the main agent that runs once per batch:
- Runs
scripts/fetch_daily_meetings.pyto get the day's external meetings - For a single meeting, processes it inline
- For multiple meetings, spawns one child cloud agent per meeting via
oz agent run-cloud
Meeting processor agent (.agents/skills/grainiac-meeting-processor/) — one per meeting:
- Fetches the full transcript from Grain
- Reads and analyzes the entire transcript (not just the AI summary)
- Checks if the company already has a Notion page
- Creates a new page or surgically updates the existing one
Slack summary skill (.agents/skills/grainiac-slack-summary/) — optional, one recording at a time:
- Fetches a recording and its transcript from Grain
- Generates a concise meeting summary
- Posts a formatted summary to a Slack channel
The orchestrator supports three modes based on the prompt:
| Prompt | Behavior |
|---|---|
| (no parameters) | Process today's meetings (Pacific time default) |
| "Process meetings from 2026-03-10" | Process all external meetings on that date |
| "Process Acme Corp meetings from 2026-03-10" | Process only that company's meetings on that date |
All scripts use the Python 3.8+ standard library only — no pip dependencies required.
For local testing, copy .env.example to .env, fill in your values, and export them before running (e.g. set -a; source .env; set +a). The scripts read configuration directly from environment variables.
python scripts/fetch_daily_meetings.py <YYYY-MM-DD | today>Outputs a JSON array of external customer meetings to stdout. Stderr shows progress.
Importable Grain API client:
get_recording(id)— fetch recording metadata and participantsget_transcript_text(id)— fetch full plain-text transcriptlist_all_recordings()— paginate through all recordingshydrate_with_participants(recordings)— enrich list results with per-recording participant datafilter_external_meetings(recordings)— filter to external-only, identify company names
Importable Notion API client:
find_company_page(name)— check if a company page existscreate_page(name, blocks)— create a new page in the databaseget_all_blocks(page_id)— get all blocks from a pageappend_blocks(parent_id, blocks, after=)— insert blocks at a specific positionupdate_block(block_id, data)— update a block's contentfind_heading_block(),get_last_block_in_section()— locate insertion points- Block builders:
heading1(),heading2(),bullet(),todo(),paragraph(),divider(),rich()
The template that defines the structure of each customer's Notion page lives at .agents/skills/grainiac-meeting-processor/references/notion-template.md. This is the single source of truth for what information is tracked per customer. Key sections:
- Follow-Up Items (checkbox list)
- Key Activities & Decisions (reverse-chronological timeline)
- Meeting Log (hyperlinked Grain recordings)
- Company Overview, People & Org
- Tech Stack & Environment
- Current Tooling & Competitive Landscape
- Requirements (deployment, inference/LLM, security, governance, integrations, blockers)
- Use Cases (primary and secondary workflows)
- Commercial (pricing, procurement/legal)
- POC / Pilot Tracker
- Communication preferences
- Sentiment & Relationship Notes