Dynamic forms library for AI-agent <-> user communication: a declarative,
surface-agnostic FormSchema artifact, renderers for every surface the
agent might be on, and template-driven intake generation.
Extracted from attune-ai's
elicitation subsystem (the elicitation-form-surface and
workflow-intake-forms specs); attune-ai consumes this package.
- One artifact —
FormSchema/FormQuestionbuilt from plain data viaform_from_dict, with build-time validation. - Question types — text, single/multi select, boolean, number, date,
textarea, plus the communication-grammar constructs:
decision(recommended option + rationale + per-option tradeoffs),pushback(structured disagreement),progress(status report with a blocked-item picker). - Renderers —
form_to_widget_html(self-contained interactive widget with postback),form_to_askuserquestion(batched payloads),form_to_elicitation_schema(native MCP elicitation). - Surface routing —
select_form_surfacepicks widget vs fallback; keyboard-mode opt-out persisted per project. - Validation —
collect_form_responsevalidates answers (required + option membership) and never silently accepts malformed input. - Intake templates —
FormTemplate+FieldSlotgenerate a workflow's intake form at ask-time from named candidate providers (PROVIDERS); build-time boundary rules reject invalid templates. - Telemetry — local-only surface-decision log (
form_events), disabled viaDO_NOT_TRACKorATTUNE_FORM_TELEMETRY=0.
pip install attune-formsfrom attune_forms import form_from_dict, select_form_surface, form_to_widget_html
form = form_from_dict({
"title": "Security audit scope",
"fields": [
{"id": "path", "type": "text_input", "label": "Which path?"},
{"id": "depth", "type": "single_select", "label": "How deep?",
"options": ["quick", "standard", "thorough"]},
],
})
if select_form_surface(form) == "widget":
html = form_to_widget_html(form) # render on your widget surfaceWorkflow-bound intake templates need two host hooks:
import attune_forms.intake_template as it
it.WORKFLOW_SCHEMA_RESOLVER = my_schema_resolver # name -> input schema
it.TEMPLATE_LOADERS.append(my_registration_loader) # imports template modulesApache 2.0. Copyright 2026 Smart AI Memory.