{"skill":{"slug":"airtable-participants","displayName":"Airtable Participants","summary":"Read and query retreat participant data from the Ceremonia Airtable base. Use this skill when asked about participants, subscriber counts, retreat attendance...","description":"---\nname: airtable-participants\ndescription: >\n  Read and query retreat participant data from the Ceremonia Airtable base.\n  Use this skill when asked about participants, subscriber counts, retreat\n  attendance, contact segments, phone numbers, emails, or donation status.\n  Also used by other skills (email-newsletter, sms-outreach) to retrieve\n  recipient lists. Read-only by default.\nversion: 1.0.0\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - AIRTABLE_API_KEY\n      bins:\n        - curl\n        - jq\n    primaryEnv: AIRTABLE_API_KEY\n    emoji: \"contacts\"\n    homepage: https://airtable.com/developers/web/api/introduction\n---\n\n# Airtable Participants Skill\n\n## Purpose\n\nQuery retreat participant data from the Ceremonia Airtable base. This is the\nauthoritative source of truth for who receives emails and SMS messages.\nAccess is read-only by default — record modifications require Austin's\nexplicit instruction per change.\n\n## Required Setup\n\nEnsure AIRTABLE_API_KEY is set in .env.\n\nYou will also need:\n- **Base ID:** [VERIFY — find in Airtable API docs at airtable.com/developers or ask Austin]\n- **Table name:** [VERIFY — confirm the participant table name with Austin]\n\nStore confirmed values in TOOLS.md and MEMORY.md once verified.\n\n## Expected Data Structure\n\nParticipant records are expected to have at minimum these fields:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| name | Text | Full name |\n| email | Email | Primary email address |\n| phone | Phone | E.164 format preferred (+1XXXXXXXXXX) |\n| retreat_status | Select | e.g., active, alumni, prospective, unsubscribed |\n| tags | Multi-select | e.g., february-2026, guide-circle, donor |\n| last_contact | Date | Most recent outreach date |\n| donation_status | Select | e.g., donor, non-donor |\n\n[VERIFY actual field names with Austin on first use — update this section when confirmed]\n\n## Common Query Patterns\n\n### Get all active participants (for newsletter sends)\n```bash\ncurl -s \"https://api.airtable.com/v0/{BASE_ID}/{TABLE_NAME}?filterByFormula={retreat_status}='active'&fields[]=name&fields[]=email\" \\\n  -H \"Authorization: Bearer $AIRTABLE_API_KEY\" | jq '.records[].fields'\n```\n\n### Get participants with phone numbers (for SMS campaigns)\n```bash\ncurl -s \"https://api.airtable.com/v0/{BASE_ID}/{TABLE_NAME}?filterByFormula=AND({retreat_status}='active',{phone}!='')&fields[]=name&fields[]=phone\" \\\n  -H \"Authorization: Bearer $AIRTABLE_API_KEY\" | jq '.records[].fields'\n```\n\n### Get participant count by status\n```bash\ncurl -s \"https://api.airtable.com/v0/{BASE_ID}/{TABLE_NAME}?fields[]=retreat_status\" \\\n  -H \"Authorization: Bearer $AIRTABLE_API_KEY\" | jq '[.records[].fields.retreat_status] | group_by(.) | map({status: .[0], count: length})'\n```\n\n### Get participants by tag\n```bash\ncurl -s \"https://api.airtable.com/v0/{BASE_ID}/{TABLE_NAME}?filterByFormula=FIND('february-2026',ARRAYJOIN({tags}))\" \\\n  -H \"Authorization: Bearer $AIRTABLE_API_KEY\" | jq '.records[].fields'\n```\n\nNote: Airtable paginates at 100 records. Use the offset parameter from the response to fetch subsequent pages:\n```bash\ncurl -s \"https://api.airtable.com/v0/{BASE_ID}/{TABLE_NAME}?offset={OFFSET_TOKEN}\" \\\n  -H \"Authorization: Bearer $AIRTABLE_API_KEY\" | jq .\n```\nAlways paginate fully before reporting totals or building recipient lists.\n\n## Behavior Rules\n\n- Read-only by default — never PATCH, POST, or DELETE Airtable records without Austin's explicit instruction per operation\n- When building a recipient list for email or SMS: always filter out records where retreat_status is 'unsubscribed'\n- Never include email addresses or phone numbers in Slack messages — summarize counts and segments only\n- If a query returns 0 results unexpectedly: report the issue to Austin rather than sending to an empty list\n- Paginate all list queries fully — do not report partial counts or build partial recipient lists\n- If Airtable API returns an error: surface it to Austin immediately with the error code and message\n\n## Record Modification (Requires Austin Approval)\n\nWhen Austin instructs a record change (e.g., marking someone unsubscribed, updating last_contact):\n1. Confirm the specific change with Austin before executing\n2. Execute the PATCH request\n3. Log the change in memory/logs/crm-writes/YYYY-MM-DD.md with: record name/email, field changed, old value, new value, Austin's instruction timestamp\n\n## Example Invocations\n\n- \"How many active participants do we have?\"\n- \"Get the email list for the February retreat attendees\"\n- \"Who attended the last three retreats?\"\n- \"How many people have phone numbers in the system?\"\n- \"Mark [name] as unsubscribed\" (requires Austin approval)\n- \"Pull the full active participant list for the newsletter\"\n- \"How many people joined since January?\"\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":985,"installsAllTime":37,"installsCurrent":2,"stars":0,"versions":1},"createdAt":1771942774377,"updatedAt":1778491628548},"latestVersion":{"version":"1.0.0","createdAt":1771942774377,"changelog":"Initial release providing read-only access to retreat participant data from Airtable.\n\n- Queries participant records for emails, phone numbers, attendance, donation status, and segments.\n- Supplies recipient lists for email-newsletter and sms-outreach, filtering out unsubscribed participants.\n- Enforces strict read-only access by default; record edits require explicit instruction and audit logging.\n- Includes detailed setup, common query examples, and behavioral guidelines for safe data handling.\n- Requires AIRTABLE_API_KEY and verification of base/table configuration before use.","license":null},"metadata":{"setup":[{"key":"AIRTABLE_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"austinmao","userId":"s17emjmz7c1adenm271bej3mys884j0k","displayName":"Austin Mao","image":"https://avatars.githubusercontent.com/u/6487975?v=4"},"moderation":null}