Turn one Tally intake into separate Airtable category records
One Tally submission creates separate Airtable records for each completed category brief, so requesters enter shared details once and each team gets its own work item.
Integrations used in this example
Collect once, route each category separately
A single Airtable form submission creates one record. That becomes awkward when a person needs to request work in several categories and each category needs its own tracked item.
This example uses a Tally form with a name field and one detail field per category. One response creates a separate Airtable record for each category the respondent filled in, all carrying the same submission ID. The agent can create or inspect the form and map its field keys before deployment.
An Airtable user wanted one form submission to create separate records for multiple categories instead of resubmitting the form for each category.Source: repeated form entry for several categories
What you'll tell the agent
- The Tally form's name field and one detail field for each category. The agent can create the form and map their field keys.
- An Airtable table with Name, Category, Details, and Submission ID fields.
- Account authorization for Tally and Airtable.
The agent will create the project and ask you for these details. When Automate.ax asks you to connect an account, authorize the integrations you want this workflow to use.
The automation
The field-key map turns completed category detail fields into separate records. The submission ID is checked before writing and stored on every created record.
import { automation, transform } from "automate.ax"
import { airtable } from "automate.ax/airtable"
import { tally } from "automate.ax/tally"
import { z } from "zod"
export default automation(
"Split one intake submission into category records",
{
parameters: [
{ label: "Tally form ID", name: "formId", type: "text" },
{ label: "Tally name field key", name: "nameFieldKey", type: "text" },
{
label: "Category detail field keys to labels JSON",
name: "categoryMapJson",
type: "text",
},
{ label: "Airtable base ID", name: "baseId", type: "text" },
{ label: "Airtable intake table", name: "table", type: "text" },
],
},
({ parameters }) => {
const categoryMap = z
.record(z.string(), z.string())
.parse(JSON.parse(parameters.categoryMapJson))
const submission = tally.onFormResponse({ formId: parameters.formId })
const intake = submission
.transform(({ data }) => {
const nameValue = data.fields.find(
(field) => field.key === parameters.nameFieldKey,
)?.value
const name = typeof nameValue === "string" ? nameValue.trim() : ""
const categories = data.fields.flatMap((field) => {
const category = categoryMap[field.key]
if (
!category ||
typeof field.value !== "string" ||
!field.value.trim()
)
return []
return [{ category, details: field.value.trim() }]
})
return { name, categories, submissionId: data.submissionId }
})
.filter(({ name, categories }) => Boolean(name) && categories.length > 0)
// Match on a stable submission ID before writing so a redelivery does not duplicate work.
const existing = airtable.listRecords({
baseId: parameters.baseId,
table: parameters.table,
filterByFormula: intake.submissionId.transform(
(id) =>
`{Submission ID} = '${z
.string()
.regex(/^[a-zA-Z0-9_-]+$/)
.parse(id)}'`,
),
})
const newIntake = transform([intake, existing], (value, prior) => ({
...value,
alreadyWritten: prior.records.length > 0,
})).filter(({ alreadyWritten }) => !alreadyWritten)
airtable.createRecords({
baseId: parameters.baseId,
table: parameters.table,
records: newIntake.transform(({ name, categories, submissionId }) =>
categories.map(({ category, details }) => ({
fields: {
Name: name,
Category: category,
Details: details,
"Submission ID": submissionId,
},
})),
),
})
},
)
What a run looks like
Example input
Taylor fills the Tally form once with a Design brief and a Content brief.
Expected result
Airtable receives one Design record with the design brief and one Content record with the content brief, both carrying Taylor's Tally submission ID.
Set it up
- Copy the setup prompt at the top into your coding agent.
- Ask the setup agent to create or inspect the Tally form, then map each category's detail field to its Airtable category label.
- Authorize Tally and Airtable. Have the agent set up the four Airtable fields and test a submission with details in two categories.
Check the result
Submit a disposable response with details in two categories. Check that it produces exactly two Airtable records with the right details and one submission ID, then redeliver the event and confirm it creates no extras.
Where this workflow stops
- The sample maps one text field per category. A multiselect or several detail fields per category needs a different field map.
- The existing-record check handles ordinary webhook redelivery, but simultaneous duplicate deliveries can still race. If each submission must be processed exactly once, ask the agent to prevent simultaneous runs from writing the same records.
- Airtable creates records in provider batches; a later batch can fail after earlier records have been written. Reconcile partial submissions before retrying.
Common questions
Does someone have to submit the form more than once?
No. One Tally response can create one Airtable record for each category with completed details.
Can the agent set up the form and table?
Yes. It can create or inspect the Tally form and Airtable table, then map their field names and keys into this example.