Item Types
BriefGate items are typed. The agent declares what it needs; the client portal validates input in real time; get_intake_results returns data the agent can use directly without further parsing or type coercion.
Each item definition requires at minimum a key (unique within the intake), a label (shown to the client), and a type. Most types accept optional constraints that the portal enforces before the client can submit.
text
A single-line text input. Use for short, structured strings such as tracking IDs, account names, or codes.
Constraints (inside constraints object)
| Field | Type | Description |
|---|---|---|
min_chars |
integer | Minimum character count. |
max_chars |
integer | Maximum character count. |
Top-level item fields
| Field | Type | Description |
|---|---|---|
pattern |
string | ECMAScript regular expression the value must match. Placed directly on the item definition, not inside constraints. |
Example — Google Analytics tracking ID
{
"key": "ga4_id",
"label": "Google Analytics 4 Measurement ID",
"help": "Found in GA4 > Admin > Data Streams. Format: G-XXXXXXXXXX",
"type": "text",
"required": true,
"pattern": "^G-[A-Z0-9]+"
}Returned by get_intake_results
"ga4_id": "G-K4M9X3R2B1"longtext
A multi-paragraph textarea. Use for copy blocks, bios, mission statements, and any text where the client needs room to write.
Constraints
| Field | Type | Description |
|---|---|---|
min_chars |
integer | Minimum character count. |
max_chars |
integer | Maximum character count. |
Example — hero section copy
{
"key": "hero_copy",
"label": "Homepage hero text",
"help": "A short paragraph (up to 400 characters) that captures the spirit of the restaurant. Appears above the fold.",
"type": "longtext",
"required": true,
"constraints": {
"max_chars": 400
}
}Returned by get_intake_results
"hero_copy": "Since 1987, handcrafted Neapolitan pizza in the heart of the city. Come hungry, leave happy."file
A single file upload. Use for documents, PDFs, spreadsheets, fonts, or any non-image binary.
Constraints
| Field | Type | Description |
|---|---|---|
formats |
string[] | Allowed file extensions without the leading dot, e.g. ["pdf","docx"]. Case-insensitive. |
max_bytes |
integer | Maximum file size in bytes. Default is 52,428,800 (50 MB). |
Example — signed contract
{
"key": "signed_contract",
"label": "Signed project contract",
"help": "Upload the signed PDF you received by email.",
"type": "file",
"required": true,
"constraints": {
"formats": ["pdf"],
"max_bytes": 10485760
}
}Returned by get_intake_results
"signed_contract": {
"filename": "bella-napoli-contract-signed.pdf",
"url": "https://files.briefgate.dev/in_8f3kQmR2/signed_contract.pdf?token=sig_abc&expires=1710615600",
"mime": "application/pdf",
"size": 283492,
"checksum_sha256": "a3f2e1..."
}The url is a signed URL valid for 24 hours. Fetch the file promptly or call get_intake_results again to obtain a fresh URL.
file_list
Multiple file uploads collected as a group. Use for photo galleries, asset packs, or any situation where you need several files of the same category.
Constraints
| Field | Type | Description |
|---|---|---|
formats |
string[] | Allowed file extensions. |
max_bytes |
integer | Maximum size per individual file. |
min_count |
integer | Minimum number of files required. |
max_count |
integer | Maximum number of files accepted. |
Example — restaurant photos
{
"key": "photos",
"label": "Food and interior photos",
"help": "Upload between 5 and 15 photos of your food, interior, and ambience.",
"type": "file_list",
"required": true,
"constraints": {
"formats": ["jpg", "png", "heic"],
"min_count": 5,
"max_count": 15
}
}Returned by get_intake_results
"photos": [
{
"filename": "interior-01.jpg",
"url": "https://files.briefgate.dev/in_8f3kQmR2/photos/interior-01.jpg?token=...",
"mime": "image/jpeg",
"size": 3204812,
"checksum_sha256": "b4c1d2..."
},
{
"filename": "pizza-margherita.jpg",
"url": "https://files.briefgate.dev/in_8f3kQmR2/photos/pizza-margherita.jpg?token=...",
"mime": "image/jpeg",
"size": 2917034,
"checksum_sha256": "f9e3a1..."
}
]image
An image upload with optional dimension and format constraints. Use instead of file when you need to enforce resolution or require transparency.
Constraints
| Field | Type | Description |
|---|---|---|
formats |
string[] | Default: ["svg","png","jpg","jpeg","webp"]. |
min_width |
integer | Minimum image width in pixels. |
max_width |
integer | Maximum image width in pixels. |
min_height |
integer | Minimum image height in pixels. |
max_height |
integer | Maximum image height in pixels. |
max_bytes |
integer | Maximum file size in bytes. |
transparent_background |
boolean | If true, the portal warns the client if the image has no alpha channel. |
Example — logo
{
"key": "logo",
"label": "Company logo",
"help": "SVG or PNG with a transparent background. Minimum 512px on the shortest side.",
"type": "image",
"required": true,
"constraints": {
"formats": ["svg", "png"],
"min_width": 512,
"transparent_background": true
}
}Returned by get_intake_results
"logo": {
"filename": "logo-transparent.png",
"url": "https://files.briefgate.dev/in_8f3kQmR2/logo-transparent.png?token=...",
"mime": "image/png",
"width": 1024,
"height": 512,
"size": 48210
}color_list
A color picker that collects one or more hex color values. The portal provides a visual color picker with hex input. No constraints are needed — the portal always validates that values are valid hex codes.
Example — brand palette
{
"key": "brand_colors",
"label": "Brand colors",
"help": "Select your primary and secondary brand colors. Add as many as you use.",
"type": "color_list",
"required": true
}Returned by get_intake_results
"brand_colors": ["#1B2A4A", "#E8E2D9", "#C8382E"]select
A dropdown or radio group where the client picks exactly one option from a list you define. Useful when you need a constrained vocabulary.
Required fields
| Field | Type | Description |
|---|---|---|
options |
array | Array of {value, label} objects. value is what gets stored; label is what the client sees. |
Example — website platform
{
"key": "platform",
"label": "Preferred website platform",
"type": "select",
"required": true,
"options": [
{ "value": "wordpress", "label": "WordPress" },
{ "value": "webflow", "label": "Webflow" },
{ "value": "shopify", "label": "Shopify" },
{ "value": "custom", "label": "Custom / I'm not sure" }
]
}Returned by get_intake_results
"platform": "wordpress"The result is always the value string, never the label.
boolean
A yes/no toggle. The portal renders it as a pair of clearly labelled buttons or a checkbox, depending on the portal theme.
Example — existing website check
{
"key": "has_existing_site",
"label": "Do you have an existing website?",
"type": "boolean",
"required": true
}Returned by get_intake_results
"has_existing_site": trueurl
A URL input with built-in http/https validation. Optionally constrain to a specific domain or path pattern.
Top-level item fields
| Field | Type | Description |
|---|---|---|
pattern |
string | ECMAScript regular expression the URL must match. Placed directly on the item definition, not inside constraints. Use to restrict to a specific domain. |
Example — existing website URL
{
"key": "existing_site_url",
"label": "Existing website address",
"help": "The full URL including https://",
"type": "url",
"required": false
}Returned by get_intake_results
"existing_site_url": "https://old.bellanapoli.com"secret
An encrypted credential input. The portal shows a password-style field with a lock icon and explicit messaging that the value is stored securely. The plaintext is encrypted with a libsodium sealed box before leaving the browser and is never logged, indexed, or included in webhook payloads.
Secrets auto-expire after 30 days and can be revealed exactly once. After reveal the token is invalidated.
Example — CMS admin login
{
"key": "cms_credentials",
"label": "WordPress admin credentials",
"help": "Your current admin username and password. Stored encrypted and only accessible to your project team.",
"type": "secret",
"required": false
}Returned by get_intake_results
On the first call, the decrypted plaintext is returned directly:
"cms_credentials": {
"value": "username:password",
"one_time": true,
"first_reveal": true,
"expires_at": "2024-04-15T10:22:00Z"
}On all subsequent calls, value is omitted (first_reveal: false). Store the plaintext before proceeding — you cannot retrieve it again. Secrets auto-expire after 30 days.
Requires the secrets:read or admin scope on the API key.
structured
A JSON value matching a JSON Schema you define. The portal renders a dynamic form from the schema (simple flat schemas) or provides a JSON editor (complex or nested schemas). The submitted value is validated against the schema server-side before the item is accepted.
Required fields
| Field | Type | Description |
|---|---|---|
schema |
object | A valid JSON Schema (draft 7 or 2020-12) object. |
Example — opening hours
{
"key": "opening_hours",
"label": "Opening hours",
"help": "Your regular weekly schedule. Use a simple time range like '12:00-22:00' or the word 'Closed'.",
"type": "structured",
"required": true,
"schema": {
"type": "object",
"required": ["mon_fri", "sat", "sun"],
"properties": {
"mon_fri": { "type": "string", "title": "Monday to Friday", "example": "12:00-22:00" },
"sat": { "type": "string", "title": "Saturday", "example": "12:00-23:00" },
"sun": { "type": "string", "title": "Sunday", "example": "Closed" }
}
}
}Returned by get_intake_results
"opening_hours": {
"mon_fri": "12:00-22:00",
"sat": "12:00-23:00",
"sun": "13:00-21:00"
}The returned object is guaranteed to conform to the declared schema.
Combining types: restaurant website example
The following items array covers the major item types in a realistic project:
[
{
"key": "logo",
"label": "Restaurant logo",
"type": "image",
"required": true,
"constraints": { "formats": ["svg","png"], "min_width": 512, "transparent_background": true }
},
{
"key": "brand_colors",
"label": "Brand colors",
"type": "color_list",
"required": true
},
{
"key": "hero_copy",
"label": "Hero section tagline",
"type": "longtext",
"required": true,
"constraints": { "max_chars": 400 }
},
{
"key": "ga4_id",
"label": "Google Analytics 4 ID",
"type": "text",
"required": false,
"pattern": "^G-[A-Z0-9]+"
},
{
"key": "has_existing_site",
"label": "Do you have an existing website?",
"type": "boolean",
"required": true
},
{
"key": "existing_site_url",
"label": "Existing website URL",
"type": "url",
"required": false
},
{
"key": "platform",
"label": "Preferred platform",
"type": "select",
"required": true,
"options": [
{ "value": "wordpress", "label": "WordPress" },
{ "value": "webflow", "label": "Webflow" },
{ "value": "custom", "label": "Custom / I'm not sure" }
]
},
{
"key": "cms_credentials",
"label": "Existing CMS credentials",
"type": "secret",
"required": false
},
{
"key": "menu_pdf",
"label": "Menu (PDF)",
"type": "file",
"required": true,
"constraints": { "formats": ["pdf"], "max_bytes": 10485760 }
},
{
"key": "photos",
"label": "Food and interior photos",
"type": "file_list",
"required": true,
"constraints": { "formats": ["jpg","png","heic"], "min_count": 5, "max_count": 15 }
},
{
"key": "opening_hours",
"label": "Opening hours",
"type": "structured",
"required": true,
"schema": {
"type": "object",
"required": ["mon_fri","sat","sun"],
"properties": {
"mon_fri": { "type": "string" },
"sat": { "type": "string" },
"sun": { "type": "string" }
}
}
}
]Validation
Validation is server-side and happens at upload time, before the item is marked submitted. The client receives immediate inline feedback in the portal if a file fails a constraint (wrong format, too small, below minimum count, pattern mismatch). They cannot submit an invalid item.
The agent's item definition — type, constraints, and schema — is the single source of truth. BriefGate does not infer constraints from file content or other heuristics. If you need to tighten constraints after an intake is live, use add_items to add a replacement item with a new key, then use request_revision to direct the client to the new field.