Flow Forms exposes 25 tools organized into seven categories. Each tool listing shows its name, what it does, parameters, and an example prompt you can use with your AI assistant.
A note about IDs: Flow Forms uses "sqids" (short unique IDs) for forms, submissions, and reports. These are the string IDs returned by tools like list-forms and create-form. Form elements carry two identifiers, and different tools want different ones: the numeric id is what create-submission and calculated fields reference, while the string gid is what update-form-element, delete-form-element, reorder-form-element, and set-element-condition take. get-form returns both for every field.
Account
whoami
Returns the ID, name, and email of the authenticated user - you, as far as Flow Forms is concerned. Useful for discovering your own user ID when another tool needs it, such as approver_user_ids.
No parameters.
Example: "Who am I logged in as?"
Form Management
list-forms
List forms in your account with optional search and pagination. Private forms are excluded.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
search |
string | No | - | Search forms by name |
limit |
integer | No | 50 | Max results (1-100) |
Returns: Array of forms with ID, name, slug, submission count, anonymous and disabled flags, and timestamps, plus a total count.
Example: "Show me all forms with 'expense' in the name"
get-form
Get a complete form definition including all fields with their IDs, types, and configurations.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) |
include_workflow |
boolean | No | false | Include workflow steps with group info and graduated form requirements |
Returns: Form metadata and a fields array with each field's numeric id and string gid, name, type, required status, help text, options, sort position, placeholder, rules, mask, group and section membership, visibility rule, props, and calculation details - plus top-level field_sets and conditions arrays. File fields also include multiple (true or false) so create-submission knows whether more than one file is allowed. The gid values here are the inputs to the element-editing tools, so start most element work with this call.
Example: "Get the full definition of form ABC123 including its workflow"
create-form
Create a new form in your account. Requires form creation permission.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | Yes | - | The form name |
is_anonymous |
boolean | No | false | If true, no login is required to fill out the form |
muted |
boolean | No | false | If true, suppress emails and SMS on step assignment and final approval |
is_private |
boolean | No | false | When true, submission data is excluded from notification emails (use for sensitive data like SSN, financial info, etc.) |
Returns: The created form with its ID, sqid, name, slug, and a link to the form editor.
Example: "Create a new anonymous form called 'Customer Feedback'"
update-form
Rename a form or change its flags. Only provided fields are changed. Changing name regenerates the public slug (/form/{slug}).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) to update |
name |
string | No | - | New form name. The URL slug is regenerated from this name |
is_anonymous |
boolean | No | - | If true, no login is required to fill out the form |
muted |
boolean | No | - | If true, suppress emails and SMS on step assignment and final approval |
is_private |
boolean | No | - | When true, submission notification emails omit form data |
disabled |
boolean | No | - | Set true to expire the form as of today. Set false to restore it |
Returns: The updated form with its ID, sqid, name, slug, flags, editor link, and public URL.
Example: "Rename this form to Gear and make it public"
Form Element Management
create-form-element
Add a field to a form. Supports 18 field types.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) |
type |
string | Yes | - | Field type (see supported types below) |
name |
string | Yes | - | The field label shown to users |
required |
boolean | No | false | Whether this field must be filled in. Forced to false for types that cannot be required: content, group, calculated, composite |
help |
string | No | - | Help text shown below the field |
options |
array | No | - | Options for select, radio, checkbox, or autocomplete fields |
sort |
integer | No | - | Position in form (appends to end if omitted) |
props |
object | No | - | Advanced configuration (see below) |
element_group_id |
string | No | - | Add this element as a child of a group element |
field_set_id |
integer | No | - | Place this element in a section (from create-field-set or get-form) |
rules |
string | No | - | Validation rules (e.g., `email |
placeholder |
string | No | - | Placeholder text, or static content for content type elements |
Supported field types:
| Type | Description | Requires Options |
|---|---|---|
text |
Single-line text input | No |
textarea |
Multi-line text input | No |
email |
Email address input | No |
telephone |
Phone number input | No |
number |
Numeric input | No |
checkbox |
Multiple choice checkboxes | Yes |
radio |
Single choice radio buttons | Yes |
select |
Dropdown selection | Yes |
autocomplete |
Searchable dropdown | Yes |
date |
Date picker | No |
time |
Time picker | No |
file |
File upload | No |
signature |
Signature capture | No |
html |
Rich text input (user enters formatted text) | No |
content |
Static display text (for instructions, headers) | No |
group |
Repeatable section container | No |
composite |
Template-based computed text | No |
calculated |
Math operations on other fields | No |
Repeatable groups: When you see numbered/indexed fields like "Member 1 - Name", "Member 2 - Name", use a group element instead. Create one group element, then add child fields using element_group_id. Users can dynamically add and remove rows. Cap the rows with props.max_rows.
Composite fields: First create the source fields, then create the composite with props.template using @-syntax (e.g., "@element(gid1) @element(gid2)"; also @submission(id|hash), @user(name|email|phone)). props.fields is derived from the template automatically - any value you supply for it is ignored. Legacy {id} tokens are rejected.
Calculated fields: Set props.operator to sum, multiply, subtract, divide, min, max, age (from a date field), time_difference (between two time fields), or date_offset (one date field plus props.days and props.direction of forward or back), and props.fields or props.operands referencing the source elements. props.format controls presentation: money, number, or the default plain number - and for time_difference, human (2 hours 3 minutes), minutes, or decimal. date_offset stores a calendar date (optional format: default Y-m-d, day, or american).
Returns: The created element with its ID, gid, type, name, sort position, and configuration.
Example: "Add a required email field called 'Work Email' to form ABC123"
batch-create-form-elements
Create multiple fields in a single operation. More efficient than calling create-form-element multiple times.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) |
elements |
array | Yes | - | Array of element definitions: type, name, required, help, options, props, rules, placeholder, element_group_id, field_set_id. Per-element sort is ignored - elements are placed in array order |
start_sort |
integer | No | - | Starting position (appends after existing fields if omitted) |
Cross-referencing with @ref:INDEX: Use @ref:0, @ref:1, etc. to reference other elements in the same batch. This works in two places:
- Adding child fields to a group: set
element_group_idto@ref:0where index 0 is the group element - Calculated fields: reference source fields in
props.fields
It does not work for composite fields - a composite's template needs real gids, so create the source fields in one batch, then create the composite once their gids exist.
Returns: The count of created elements and details for each.
Example: "Add a Name, Email, and Department dropdown with options Sales, Engineering, and Marketing to form ABC123"
update-form-element
Update an existing form element. Only the fields you provide are changed. Requires edit permission on the form.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
element_gid |
string | Yes | - | The element gid to update |
name |
string | No | - | New field label |
required |
boolean | No | - | Whether this field must be filled in |
help |
string | No | - | Help text shown below the field |
options |
array | No | - | New options (replaces all existing options) |
rules |
string | No | - | Validation rules (replaces the existing rules) |
placeholder |
string | No | - | Placeholder text, or static content for content elements |
field_set_id |
integer | No | - | Move the element to a different section |
props |
object | No | - | Advanced configuration; group elements accept max_rows here |
Returns: The updated element with its current configuration.
Example: "Rename the 'Full Name' field to 'Legal Name'"
delete-form-element
Remove a field from a form. Requires edit permission on the form.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
element_gid |
string | Yes | - | The element gid to delete |
Returns: Confirmation with the deleted element's name.
Example: "Remove the phone number field from my form"
reorder-form-element
Move a field to a new position in the form.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
element_gid |
string | Yes | - | The element gid to move |
position |
string | Yes | - | "first", "last", or "after:{target_gid}" |
Returns: Confirmation with the element's new sort position.
Example: "Move the email field to the top of the form"
create-field-set
Create a section on a form - the tabbed groupings respondents work through one at a time. Returns the section's ID to use as field_set_id when creating or updating elements.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) to add the section to |
name |
string | Yes | - | The section heading shown to users |
Sections hold top-level elements; fields inside a repeatable group cannot belong to one.
Returns: The created field set's ID and name.
Example: "Add a 'Contact Details' section to form ABC123 and move the name and email fields into it"
set-element-condition
Control when fields are shown. Creates a show/hide rule from trigger clauses and attaches it to the target fields: the targets are visible only while the rule evaluates true.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) the rule belongs to |
target_gids |
array | Yes | - | Element gids to show/hide. All targets share the rule |
rules |
array | Yes | - | Clauses: {trigger_gid, operator, value?, connective?}. An empty array detaches the targets from their rule, making them always visible |
name |
string | No | - | Rule name shown in the builder; defaults to a summary of the first clause |
condition_id |
integer | No | - | Existing condition ID (from get-form) to rewrite instead of creating a new rule |
Operators: is equal to, is not equal to, is greater than, is greater than or equal to, is less than, is less than or equal to, contains, does not contain, is empty, is not empty. A value is required except for the empty checks. For checkbox triggers use contains, since checkboxes store multiple values.
Connectives: each clause carries and (the default) or or. Clauses are not folded left to right: all the and clauses must be true together, and that result is OR'd with each or clause independently.
Returns: The rule's ID, name, clauses, and attached targets.
Example: "Only show the 'Other - please specify' field when Department is equal to Other"
Submission Management
create-submission
Submit data to a form. Use get-form first to discover the form's fields and their IDs. The submission is recorded as coming from you - the authenticated user - unless the form is anonymous. Note that this tool requires edit permission on the form, so it is for form editors and administrators, not general respondents.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) |
elements |
array | Yes | - | Array of values. Each needs form_element_id (numeric) or name (field name), plus value for non-file fields or files for file fields. |
approver_user_ids |
array | No | - | User IDs for the first approval step. Required for "one" and "multiple" flow types. |
parent_submission_id |
string | No | - | Parent submission ID (sqid) for graduated form submissions |
Element values: Each element in the elements array should include:
form_element_id(numeric) orname(field label) to identify the fieldvalue- the submitted value for non-file fieldsfiles(file fields only) - array of{ filename, content }.contentis raw base64 or adata:*;base64,...URL. Each file must be 300 MB or smaller. Send more than one file only whenget-formreportsmultiple: truefor that field. Do not sendfileson signature or other non-file fields.multi(optional, boolean) - set totruefor multiple selectionsquantity(optional) - for quantity-based fields
All required fields must have values. A required file field needs at least one file — an empty files array does not count. If a field name is duplicated, use form_element_id instead.
Conditionally hidden fields: Visibility rules apply to tool submissions the same way they apply in the browser. A required field that is hidden by the submitted values is not required, and a value submitted for a hidden field is discarded rather than stored.
Returns: The submission ID (sqid) and URL - plus a notes array explaining any values that were discarded because their fields were hidden.
Example: "Submit the leave request form with start date Jan 5 and end date Jan 10"
get-submission
Get a single submission with full details.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
submission_id |
string | Yes | - | The submission ID (sqid) |
include_elements |
boolean | No | true | Include field values |
include_notes |
boolean | No | true | Include notes/comments |
include_history |
boolean | No | true | Include approval history |
include_children |
boolean | No | true | Include child submissions (graduated forms) |
include_workflow |
boolean | No | false | Include current workflow step and graduated form requirements |
Returns: Submission details with user info, status, and optionally elements, notes, process history, children, and workflow context.
Example: "Show me submission XYZ789 with its approval history and workflow context"
get-submissions
Search and filter submissions across forms.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | No | - | Scope to a specific form |
search |
string | No | - | Full-text search across field values |
statuses |
array | No | - | Filter by status: pending, approved, denied, info_requested, sent_back |
forms |
array | No | - | Filter by multiple form IDs (sqids) |
submitters |
array | No | - | Filter by submitter user IDs |
start |
string | No | - | Start date (YYYY-MM-DD) |
end |
string | No | - | End date (YYYY-MM-DD) |
terms |
object | No | - | Filter by field values, keyed by numeric element ID: {"1234": ["value1", "value2"]} |
pending |
array | No | - | Filter by user IDs with pending approvals |
pending_on_user |
boolean | No | false | Show only submissions pending on you |
flows |
array | No | - | Filter by workflow step IDs the submissions are currently awaiting (step IDs come from get-form with include_workflow) |
sortBy |
string | No | updated_at | Sort by updated_at or created_at |
sortDirection |
string | No | desc | desc or asc |
fields |
array | No | - | Limit returned element values to these field names, to keep responses small |
limit |
integer | No | 50 | Max results (1-100) |
include_elements |
boolean | No | true | Include field values |
include_notes |
boolean | No | false | Include notes |
include_history |
boolean | No | false | Include approval history |
include_children |
boolean | No | false | Include child submissions |
Filtering logic: terms keys are numeric element IDs (from get-form), not field names - a field-name key is silently ignored. AND logic applies between different elements, OR logic within one element's values. For example, {"1234": ["Sales", "Marketing"], "5678": ["Active"]} finds submissions where element 1234 is Sales OR Marketing, AND element 5678 is Active.
Returns: Array of submissions with total count.
Example: "Find all pending expense submissions from the last month"
add-submission-note
Add a comment or note to a submission.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
submission_id |
string | Yes | - | The submission ID (sqid) |
message |
string | Yes | - | The note text |
Returns: The note with its ID, message, author name, and timestamp.
Example: "Add a note to submission XYZ789 saying 'Approved by finance team'"
Workflow and Approval
approve-submission
Approve a submission, advancing it through its approval workflow. You must have an active approval notification for the submission.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
submission_id |
string | Yes | - | The submission ID (sqid) |
next_approver_user_ids |
array | No | - | User IDs for the next approval step (required for "one" and "multiple" flow types) |
group_id |
integer | No | - | Group ID for group_select flow types |
Graduated forms: If the current approval step requires a graduated form to be completed first, you must create the child submission using create-submission with parent_submission_id before approving.
Returns: Updated submission status and confirmation message.
Example: "Approve submission XYZ789"
deny-submission
Deny a submission, ending its workflow. You must have an active approval notification for the submission.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
submission_id |
string | Yes | - | The submission ID (sqid) |
reason |
string | No | - | Reason for denial (automatically added as a note) |
Returns: Updated submission status and confirmation message.
Example: "Deny submission XYZ789 because the receipt is missing"
Reporting and Analytics
compute-aggregates
Compute counts, sums, averages, min/max, and per-column breakdowns over a form's submissions on the fly - the same semantics as a report, without saving one. Drafts and deleted submissions are excluded.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) whose submissions to aggregate |
filters |
array | No | - | Filter objects {column, operator, value}, same vocabulary as report filters |
aggregations |
array | No | - | Aggregation objects {function, column, label}. Functions: count, sum, avg, min, max; omit column for count |
breakdown |
object | No | - | Group-by: {column, interval, aggregate, aggregate_column}. interval (day/week/month/year) applies to date columns |
Returns: The computed values, plus a config_echo you can pass to create-report to save the same analysis as a report.
Example: "How many t-shirts of each size have been ordered on the merch form?"
list-reports
List reports visible to you, each belonging to a form and holding filters, aggregations, columns, and charts.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | No | - | Scope to one form's reports |
Returns: Array of reports with ID, name, and form.
Example: "What reports exist for the expense form?"
get-report
Get a report's full configuration plus the column vocabulary available on its form. Use before updating a report.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
report_id |
string | Yes | - | The report ID (sqid) |
Returns: The report's filters, aggregations, columns, and charts, plus available_columns for the form.
Example: "Show me how the quarterly expenses report is configured"
create-report
Create a report for a form, optionally with initial filters, aggregations, columns, and charts. Reports appear on the account's report pages.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) the report is for |
name |
string | Yes | - | The report name |
view_group_names |
array | No | - | Group names allowed to view the report; omit to leave it visible to everyone |
filters |
array | No | - | Filter objects {column, operator, value}. Operators depend on the column type - text: equals/not_equals/contains/starts_with/ends_with/is_empty/is_not_empty; numeric: equals/not_equals/greater_than/less_than/between; date: equals/before/after/between/relative; select: in/not_in. between takes [min, max]; relative takes values like this_week, last_30_days |
aggregations |
array | No | - | Aggregation objects {function, column, label}, shown as summary values above the report table |
columns |
array | No | - | Table columns {name, label}; omit to show all columns |
charts |
array | No | - | Chart objects {name, measure: {aggregate, column}, slice: {column, interval, limit}, split: {column}, display}. Displays: line, area, bar, stacked, grouped |
Column names come from get-report on an existing report of the same form, or from available_columns in this tool's response.
Returns: The created report with its ID and a link.
Example: "Create a report on the expense form showing total amount by month, filtered to approved submissions"
update-report
Update a report's name or configuration. Each config section you provide replaces that section entirely - read the current config with get-report first, and send an empty array to clear a section. Omitted sections are left unchanged.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
report_id |
string | Yes | - | The report ID (sqid) |
name |
string | No | - | New report name |
filters |
array | No | - | Replacement filters, same vocabulary as create-report |
aggregations |
array | No | - | Replacement aggregations |
columns |
array | No | - | Replacement table columns; empty array shows all columns |
charts |
array | No | - | Replacement charts |
Returns: The updated report configuration.
Example: "Add a chart of submissions per week to the intake report"
Access Control
set-form-access
Control which groups can access and fill out a form. This replaces all existing access settings.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
string | Yes | - | The form ID (sqid) |
group_names |
array | Yes | - | Exact group names that should have access |
Use list-groups first to see the available group names. All group names must match exactly.
Returns: The form ID and its updated list of groups with access.
Example: "Give the Sales and Marketing groups access to the feedback form"
list-groups
List all groups in your account.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
search |
string | No | - | Filter groups by name |
Returns: Array of groups with ID and name, plus total count.
Example: "What groups are available in this account?"