Using AI to Auto‑Generate Forms: Production‑Ready Low‑Code Form Generation with Spring AI Alibaba ReactAgent

The article presents a production‑grade solution that lets users describe a form in natural language, then uses a Spring AI Alibaba ReactAgent powered by a ReAct reasoning loop to retrieve templates, validate fields, generate layout, enforce governance, and finally emit a versioned JSON schema ready for deployment.

Ray's Galactic Tech
Ray's Galactic Tech
Ray's Galactic Tech
Using AI to Auto‑Generate Forms: Production‑Ready Low‑Code Form Generation with Spring AI Alibaba ReactAgent

Problem Definition: Design, Not Drag‑And‑Drop, Is the Bottleneck

In enterprise low‑code platforms, creating a moderately complex form (20‑40 fields) typically consumes 0.5‑2 person‑days because requirements must be translated into structured fields, templates are hard to reuse, and naming, binding, and versioning inconsistencies arise.

Why an Agent Fits This Problem

Form creation is essentially a structured UI DSL generation task: the input is unstructured natural language, the output is a JSON schema, and the process can be broken into constrained tool steps. ReAct agents excel at such multi‑step reasoning and tool calling.

Goals: Not Just "Can Generate" but "Can Deploy"

Functional: natural‑language to standard form JSON, template reuse, field metadata constraints, automatic layout, human‑in‑the‑loop confirmation, versioning.

Engineering: support synchronous streaming and asynchronous long‑task modes, high concurrency, idempotency, audit, and security.

Governance: schema validation, version control, rollback, and permission checks.

Overall Architecture (Four‑Layer Decoupling)

┌──────────────── User Access Layer ────────────────┐
│  Low‑Code Designer  OpenAPI  Chat UI │
└───────────────────────────────────────────┘
               │
               ▼
┌──────────────── Intelligent Orchestration Layer ────────────────┐
│            Form ReactAgent            │
│ Prompt Router  ReAct Loop  HITL Gate │
│ Stream Output  Task State  Retry Guard│
└───────────────────────────────────────────────────────────────┘
               │
               ▼
┌──────────────── Capability Tool Layer ────────────────┐
│ Schema Search  Field Registry  Validator│
│ Layout Engine  Rule Builder  Saver│
│ Dictionary API  Binding Mapper  Diff Tool│
└───────────────────────────────────────────────────────┘
               │
               ▼
┌──────────────── Infrastructure Layer ────────────────┐
│ Redis  Elasticsearch  MySQL  RocketMQ│
│ Nacos  Micrometer  OTel  K8s│
└───────────────────────────────────────────────────────┘

Core Design Principles

Agent does not own business truth : field legality, dictionary values, and bindings are resolved by the tool layer.

Model output must be a controlled DSL : final result is a versioned, verifiable JSON contract, not free‑form text.

High‑cost steps are async : LLM calls, vector search, and rule generation run asynchronously when needed.

Human‑in‑the‑loop is mandatory : saving, overwriting, or publishing a schema requires explicit confirmation.

ReAct Reasoning for Form Generation

The user request is broken into a sequence of thoughts, actions, and observations:

Thought → Action → Observation → Thought → … → Final

Typical steps include:

Identify business domain.

Retrieve similar historical templates.

Extract candidate fields.

Fetch standard field metadata and dictionaries.

Generate layout and interaction rules.

Validate the JSON against the DSL contract.

Await human confirmation before persisting.

Domain Model Design

Four core metadata records are defined as Java record s:

public record FieldMeta(
    String fieldCode,
    String fieldName,
    String componentType,
    String javaType,
    boolean required,
    Integer maxLength,
    String dictCode,
    String tableName,
    String columnName,
    List<String> tags) {}

public record FormTemplate(
    String templateId,
    String businessDomain,
    String templateName,
    Integer version,
    String schemaJson,
    List<String> keywords,
    Double qualityScore) {}

public record FormSchema(
    String schemaId,
    String schemaName,
    Integer version,
    LayoutConfig layout,
    List<FormControl> controls,
    PublishConfig publishConfig) {}

public record FormGenerationTask(
    String taskId,
    String sessionId,
    String tenantId,
    String userId,
    String requestText,
    String status,
    Integer retryCount,
    String resultSchemaId) {}

A field‑metadata center prevents three common hallucination problems: inconsistent naming, wrong component types, and binding errors.

JSON Schema Contract Example

{
  "schemaId": "after_sale_workorder_v1",
  "schemaName": "售后维修工单",
  "version": 1,
  "layout": {"type": "grid", "columns": 2, "labelAlign": "right", "gutter": 16},
  "controls": [
    {"id": "customer_name", "type": "input", "label": "客户姓名", "required": true, "placeholder": "请输入客户姓名", "validation": [{"rule": "required", "message": "客户姓名必填"}, {"rule": "maxLength", "value": 50}], "dataBinding": {"table": "after_sale_order", "column": "customer_name"}},
    {"id": "priority", "type": "select", "label": "紧急程度", "required": true, "options": [{"label": "高", "value": "HIGH"}, {"label": "中", "value": "MEDIUM"}, {"label": "低", "value": "LOW"}], "dataBinding": {"table": "after_sale_order", "column": "priority"}},
    {"id": "fault_images", "type": "upload", "label": "故障图片", "maxCount": 5, "accept": [".jpg", ".png"], "dataBinding": {"table": "after_sale_order", "column": "fault_images"}}
  ],
  "rules": [{"when": "priority == 'HIGH'", "then": [{"action": "setRequired", "target": "visit_time", "value": true}]}]
}

Tool Design

Tools are implemented as Spring @Component s that conform to a BiFunction signature. Example of a historical‑template search tool:

@Component
public class SchemaSearcher implements BiFunction<String, ToolContext, String> {
    private final FormTemplateSearchService templateSearchService;
    public SchemaSearcher(FormTemplateSearchService templateSearchService) {
        this.templateSearchService = templateSearchService;
    }
    @Override
    @Tool(description = "检索相似历史表单模板")
    public String apply(String query, ToolContext context) {
        List<FormTemplateCandidate> candidates = templateSearchService.hybridSearch(query, 3);
        return JsonUtils.toJson(candidates);
    }
}

Other tools include fetch_field_metadata, validate_fields, compose_form_layout, build_form_rules, validate_schema, and save_form_schema. Retrieval and field‑metadata fetch are parallelizable.

State Machine for Long‑Running Generation

INIT → ANALYZING → TOOL_RUNNING → WAITING_CONFIRM → SAVING → COMPLETED → FAILED → CANCELED

The state machine enables front‑end polling, back‑end compensation, audit replay, and operational metrics.

Conversation Memory and Context Management

In multi‑instance deployments, session memory must be externalized. Redis is used as the primary store with a 30‑minute TTL and trimming to the most recent 10‑30 messages.

@Component
public class RedisConversationMemory {
    private static final String KEY_PREFIX = "agent:chat:";
    private final RedisTemplate<String, Object> redisTemplate;
    public RedisConversationMemory(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    public void append(String sessionId, ChatMessage chatMessage) {
        String key = KEY_PREFIX + sessionId;
        redisTemplate.opsForList().rightPush(key, chatMessage);
        redisTemplate.expire(key, Duration.ofMinutes(30));
        Long size = redisTemplate.opsForList().size(key);
        if (size != null && size > 30) {
            redisTemplate.opsForList().trim(key, size - 30, -1);
        }
    }
}

High Concurrency & Scalability Strategies

Dual‑channel: lightweight requests use SSE streaming; heavy requests are queued as async tasks returning a taskId.

Queue throttling with RocketMQ to limit concurrent LLM calls.

Parallel execution of independent tools (template search, field metadata, dictionary lookup).

Multi‑level caching for field metadata, dictionaries, hot template results, and semantic embeddings.

Model‑based routing: simple forms use a lightweight model, complex forms use a higher‑capacity model.

Idempotency Controls

Task‑level idempotency via unique taskId.

Schema version uniqueness enforced by a DB unique constraint on schemaName + version.

Request‑level deduplication using a requestHash cache.

Human‑In‑The‑Loop Integration

Critical actions (save, overwrite, publish, cross‑domain field generation) are intercepted with a compiled graph that pauses before save_form_schema. The front‑end presents field previews, layout previews, diff against historical templates, and risk warnings for user confirmation.

Security, Permission, and Auditing

All tool calls carry a ToolContextMeta containing tenant ID, user ID, trace ID, and permission set. Permissions are fine‑grained (e.g., form.template.read, form.schema.save). Audit logs record who initiated the request, the natural‑language input, invoked tools, tool summaries, generated schema, and confirmation details.

Observability

Metrics are collected via Micrometer for agent request volume, success rate, iteration count, latency percentiles, model token usage, tool call counts, and failure rates. Cost monitoring tracks token consumption per tenant and cache hit ratios.

@Component
public class FormMetrics {
    private final MeterRegistry meterRegistry;
    public FormMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    public void recordToolLatency(String toolName, long millis) {
        Timer.builder("form.agent.tool.latency")
            .tag("tool", toolName)
            .register(meterRegistry)
            .record(Duration.ofMillis(millis));
    }
}

API Design

Synchronous streaming : POST /api/forms/generate/stream returns SSE events (THINKING, TOOL_RUNNING, WAITING_CONFIRM, FINAL_SCHEMA).

Asynchronous : POST /api/forms/generate/async returns a taskId; status queried via GET /api/forms/tasks/{taskId}; confirmation via POST /api/forms/tasks/{taskId}/confirm.

Real‑World Case Study: After‑Sale Repair Work Order

The operator inputs a request for a repair work order with fields such as customer name, phone, product model, SN, fault description, images, visit time, priority, warranty flag, and processing result. The agent executes the steps described above, retrieves the most similar template (Repair Work Order V3), pulls standard fields, generates layout (two‑column grid), validates rules, and finally presents a preview. After user confirmation, the schema after_sale_workorder_v1 is saved.

Time to go from request to deployable schema drops from 2‑4 hours in a manual process to 5‑15 minutes with the AI‑assisted pipeline.

Common Production Issues & Mitigations

Hallucinated fields : enforce validate_fields and reject non‑standard fields.

Infinite loops : set maxIterations in the ReAct agent and include explicit failure‑stop prompts.

Cost explosion on similar requests : use semantic cache to return cached templates when embedding similarity exceeds a threshold.

Post‑publish compatibility breaks : embed schema version and run compatibility checks before saving.

Deployment Evolution Path

Prototype: Spring Boot + in‑memory memory + local templates (demo).

Initial production: Redis, MySQL, Elasticsearch, SSE (10‑50 QPS).

Stable production: RocketMQ, Redis Cluster, Kubernetes multi‑replica (50‑200 QPS).

Large‑scale: multi‑model routing, distributed tool services, semantic cache (>200 QPS).

Conclusion

Form generation in low‑code platforms is not a simple "let the model write JSON" task; it is a tightly coupled system of Agent + metadata center + rule engine + stable DSL**. By letting the LLM handle understanding and planning while the surrounding services enforce constraints, governance, observability, and scalability, teams can turn a manual, days‑long activity into a fast, reliable, and auditable production workflow.

References

Spring AI Alibaba official site: https://java2ai.com

Spring AI Alibaba GitHub: https://github.com/alibaba/spring-ai-alibaba

Spring AI Alibaba examples: https://github.com/springaialibaba/spring-ai-alibaba-examples

ReAct: Synergizing Reasoning and Acting in Language Models – https://arxiv.org/abs/2210.03629

OpenTelemetry documentation – https://opentelemetry.io/docs/

ReActobservabilitymetadatalow-codeSpring AIform generationReactAgent
Ray's Galactic Tech
Written by

Ray's Galactic Tech

Practice together, never alone. We cover programming languages, development tools, learning methods, and pitfall notes. We simplify complex topics, guiding you from beginner to advanced. Weekly practical content—let's grow together!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.