Create records from different table data
You have data in one table and need to automatically create new records in a different table based on that data. AI fields won't do this automatically—you need automations.
The problem
AI fields can extract and transform data within a record, but they cannot automatically create new records in different tables. For example:
- You add an interview record
- You want topics and posts automatically created in separate tables
- Nothing happens automatically
This requires an automation workflow.
Solution: Automation with Generate Structured Data
The best approach is using Airtable's "Generate Structured Data" automation action, which can create multiple records at once.
Example: Interview → Topics → Posts
Let's say you have:
- Interviews table: Contains interview transcripts
- Topics table: Should contain extracted topics
- Posts table: Should contain suggested social media posts
Step 1: Set up the trigger
Create an automation that triggers when:
- A new interview record is created, OR
- A specific field (like "Transcript") is filled in
Trigger: "When record matches conditions"
- Field: Transcript
- Condition: Is not empty
Step 2: Generate structured data
Use the "Generate Structured Data" action:
- Action: "Generate structured data with AI"
- Input: Reference the transcript field from the triggering record
- Prompt: Tell AI what structure you want
Example prompt:
Extract all topics discussed in this interview transcript.
Return a JSON array where each topic has:
- name: the topic name
- description: a brief description
Return ONLY valid JSON, no other text.
Step 3: Create records from structured data
After generating structured data, use a "Run a script" action to create records:
// Get the structured data from previous step
const structuredData = input.config().structuredData
const topicsTable = base.getTable("Topics")
const interviewsTable = base.getTable("Interviews")
const triggerRecordId = input.config().triggerRecordId
// Parse the JSON array
const topics = JSON.parse(structuredData)
// Create a record for each topic
for (const topic of topics) {
await topicsTable.createRecordAsync({
"Name": topic.name,
"Description": topic.description,
"Interview": [{ id: triggerRecordId }] // Link back to interview
})
}
Step 4: Create posts from topics
Add another automation step to generate posts based on the created topics:
- Trigger: "When record is created" in Topics table
- Action: "Generate structured data with AI"
- Prompt: Generate social media post suggestions based on the topic
Alternative: Using repeating lists
If you prefer not to use structured data, you can use repeating lists with scripts:
Step 1: Generate text with AI
- Action: "Generate text with AI"
- Input: Transcript field
- Prompt: Extract topics as a comma-separated list
Step 2: Split into repeating list
Use a formula or script to split the comma-separated list into a repeating list field.
Step 3: Create records from list
Use a script to iterate through the repeating list and create records:
const topicsList = input.config().topicsList // Repeating list field
const topicsTable = base.getTable("Topics")
const triggerRecordId = input.config().triggerRecordId
for (const topic of topicsList) {
await topicsTable.createRecordAsync({
"Name": topic,
"Interview": [{ id: triggerRecordId }]
})
}
Complete automation example
Here's a full automation workflow for the interview analysis use case:
Automation: Extract Topics from Interview
Trigger:
- When: Record matches conditions
- Table: Interviews
- Condition: Transcript is not empty
Action 1: Generate Structured Data
- Input:
{Transcript}(from triggering record) - Prompt:
Analyze this interview transcript and extract all discussed topics.
Return a JSON array where each object has:
{
"name": "topic name",
"description": "brief description"
}
Return ONLY valid JSON array, no other text.
Action 2: Run Script
const structuredData = input.config().structuredData
const topicsTable = base.getTable("Topics")
const interviewsTable = base.getTable("Interviews")
const triggerRecordId = input.config().triggerRecordId
try {
const topics = JSON.parse(structuredData)
for (const topic of topics) {
await topicsTable.createRecordAsync({
"Name": topic.name,
"Description": topic.description,
"Interview": [{ id: triggerRecordId }]
})
}
} catch (error) {
console.error("Error parsing or creating topics:", error)
}
Automation: Generate Posts from Topics
Trigger:
- When: Record is created
- Table: Topics
Action 1: Generate Structured Data
- Input:
{Name}and{Description}from triggering topic - Prompt:
Based on this topic, suggest 3 social media post ideas.
Return a JSON array where each object has:
{
"content": "post text",
"summary": "brief summary",
"hashtags": "suggested hashtags"
}
Return ONLY valid JSON array.
Action 2: Run Script
const structuredData = input.config().structuredData
const postsTable = base.getTable("Posts")
const triggerRecordId = input.config().triggerRecordId
try {
const posts = JSON.parse(structuredData)
for (const post of posts) {
await postsTable.createRecordAsync({
"Content": post.content,
"Summary": post.summary,
"Suggested Hashtags": post.hashtags,
"Topic": [{ id: triggerRecordId }]
})
}
} catch (error) {
console.error("Error parsing or creating posts:", error)
}
Best practices
Structure your prompts clearly
Be specific about the JSON structure you want:
Return a JSON array where each object has:
{
"field1": "value",
"field2": "value"
}
Return ONLY valid JSON, no other text.
Handle errors gracefully
Always wrap JSON parsing in try-catch blocks:
try {
const data = JSON.parse(structuredData)
// Process data
} catch (error) {
console.error("Error:", error)
// Handle error or skip
}
Link records back
Always link created records back to the source:
await newTable.createRecordAsync({
"Field": value,
"Source Record": [{ id: triggerRecordId }] // Link back
})
Test with sample data
Before deploying, test your automation with:
- Sample records
- Edge cases (empty fields, malformed data)
- Multiple records
Use conditions to prevent duplicates
Add conditions to prevent creating duplicate records:
Condition: Check if records already exist
- Find records in Topics table
- Where Interview matches triggering record
- Only create if no records found
Common use cases
Extract items from text
Use case: Extract a list of items mentioned in a text field
Example: Extract hobbies from a notes field
// Prompt: Extract all hobbies mentioned. Return JSON array of strings.
const hobbies = JSON.parse(structuredData)
for (const hobby of hobbies) {
await hobbiesTable.createRecordAsync({
"Name": hobby,
"Source": [{ id: triggerRecordId }]
})
}
Break down complex data
Use case: Split a single record with multiple values into separate records
Example: One order with multiple line items → separate line item records
Generate related content
Use case: Create related records based on analysis
Example: Interview → Topics → Posts (as shown above)
Limitations and alternatives
Airtable automation limits
- AI actions: Limited by your plan's AI credits
- Script execution time: 30 seconds max
- Record creation rate: Consider rate limits for large batches
When to use external tools
Consider Make, Zapier, or custom scripts when:
- You need to process large volumes
- You need more complex logic
- You need to handle errors more robustly
- You need to create records across multiple bases
External tool example (Make)
- Trigger: Webhook or Airtable watch
- Action: AI module to extract data
- Action: Create records in Airtable via API
- Error handling: Retry logic and logging
Troubleshooting
Records not being created
Check:
- Automation is enabled
- Trigger conditions are met
- AI field has data (if using AI field as trigger)
- Script has proper error handling
- JSON parsing is working correctly
Duplicate records
Solution: Add a condition to check if records already exist before creating:
// Find existing records
const existing = await topicsTable.selectRecordsAsync({
filterByFormula: `{Interview} = "${triggerRecordId}"`
})
if (existing.records.length === 0) {
// Create records
}
Malformed JSON
Solution: Improve your prompt and add error handling:
try {
// Clean the response (remove markdown code blocks if present)
let cleaned = structuredData.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim()
const data = JSON.parse(cleaned)
} catch (error) {
console.error("JSON parse error:", error)
}
Quick reference
| Task | Method | Action |
|---|---|---|
| Extract list from text | Generate Structured Data | Returns JSON array |
| Create multiple records | Run Script | Loop through array |
| Link back to source | Create Record | Include link field |
| Prevent duplicates | Find Records | Check before creating |
| Handle errors | Try-Catch | Wrap JSON parsing |
Tips
- Start simple: Test with one record before scaling
- Use structured data: Prefer "Generate Structured Data" over text parsing
- Link everything: Always link created records back to source
- Test prompts: Refine AI prompts for better JSON output
- Monitor usage: Track AI credits and automation runs
- Document workflows: Keep notes on what each automation does
References
Community discussion on creating records from different table data: Create Records based on data in a different table