{"id":50566404,"url":"https://github.com/neuron-core/ai-form","last_synced_at":"2026-06-04T15:01:50.152Z","repository":{"id":348336700,"uuid":"1197588059","full_name":"neuron-core/ai-form","owner":"neuron-core","description":"Conversational Data Collection. Built with Neuron AI Framework.","archived":false,"fork":false,"pushed_at":"2026-04-01T11:08:10.000Z","size":164,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-04T03:13:50.797Z","etag":null,"topics":["agent","agentic-ai","agentic-workflow","llm","neuron-ai","php"],"latest_commit_sha":null,"homepage":"https://docs.neuron-ai.dev","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neuron-core.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-31T17:49:21.000Z","updated_at":"2026-04-24T06:33:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/neuron-core/ai-form","commit_stats":null,"previous_names":["neuron-core/ai-form"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/neuron-core/ai-form","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neuron-core%2Fai-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neuron-core%2Fai-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neuron-core%2Fai-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neuron-core%2Fai-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neuron-core","download_url":"https://codeload.github.com/neuron-core/ai-form/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neuron-core%2Fai-form/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33910137,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","agentic-ai","agentic-workflow","llm","neuron-ai","php"],"created_at":"2026-06-04T15:01:50.045Z","updated_at":"2026-06-04T15:01:50.140Z","avatar_url":"https://github.com/neuron-core.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AIForm - Conversational Data Collection\n\nAIForm is a component for collecting structured data through multi-turn natural language conversations. It uses an AI agent to progressively gather information defined by a structured output class, validating each piece of data along the way.\n\nThe form maintains conversation history, tracks collected fields, missing fields, and validation errors across multiple turns.\n\nRead the full article here: **https://inspector.dev/collecting-data-through-conversation-introducing-aiform-for-neuronai/**\n\n\u003e Before moving on, support the Neuron AI community giving a GitHub star ⭐️. Thank you!\n\n## Creating a Data Class\n\nYou can provide the form structure you want to collect defining a data class using PHP attributes in the same way as you would with any other\n[structured output](https://docs.neuron-ai.dev/agent/structured-output) class in Neuron AI.\n\nYou can also attach validation rules like `#[NotBlank]` or `#[Email]` to fields, to enforce data requirements.\n\n```php\nuse NeuronAI\\StructuredOutput\\SchemaProperty;\nuse NeuronAI\\StructuredOutput\\Validation\\Rules\\Email;\nuse NeuronAI\\StructuredOutput\\Validation\\Rules\\NotBlank;\n\nclass RegistrationData\n{\n    #[SchemaProperty(description: 'User full name', required: true)]\n    #[NotBlank]\n    public string $name;\n\n    #[SchemaProperty(description: 'Email address', required: true)]\n    #[Email]\n    public string $email;\n\n    #[SchemaProperty(description: 'Phone number')]\n    public ?string $phone = null;\n\n    #[SchemaProperty(description: 'Company name')]\n    public ?string $company = null;\n}\n```\n\n## Creating a Custom Form\n\nExtend the `AIForm` class to create your custom form:\n\n```php\n\u003c?php\n\nnamespace App\\Neuron\\Forms;\n\nuse NeuronAI\\Form\\AIForm;\nuse NeuronAI\\Form\\Enums\\FormStatus;\nuse NeuronAI\\Form\\FormState;\nuse NeuronAI\\Providers\\Anthropic\\Anthropic;\n\nclass RegistrationForm extends AIForm\n{\n    protected string $formDataClass = RegistrationData::class;\n\n    protected function provider(): AIProviderInterface\n    {\n        return new Anthropic(\n            key: 'ANTHROPIC_API_KEY',\n            model: 'ANTHROPIC_MODEL',\n        );\n    }\n\n    /**\n     * Handle the submitted form data.\n     */\n    protected function callback(): mixed\n    {\n        // $data is an instance of RegistrationData\n        // Save to database, send email, call API, etc.\n        return function (RegistrationData $data) {\n            $this-\u003euserService-\u003eregister($data);\n        };\n    }\n}\n```\n\n## Using Form in Application Code\n\n### Basic Usage\n\n```php\nuse App\\Forms\\RegistrationForm;\nuse NeuronAI\\Chat\\Messages\\UserMessage;\nuse NeuronAI\\Providers\\OpenAI\\OpenAI;\n\n// Create form instance with AI provider\n$form = RegistrationForm::make();\n\n// Turn 1\n$state = $form-\u003eprocess(new UserMessage(\"Hi, I'd like to register\"));\n$state = $handler-\u003erun();\n\necho $state-\u003egetStatus()-\u003evalue;        // 'incomplete'\necho $handler-\u003egetLastResponse();        // AI asks for name\n\n// Turn 2\n$handler = $form-\u003eprocess(new UserMessage(\"My name is John Doe\"));\n$state = $handler-\u003erun();\n\n// Turn 3\n$handler = $form-\u003eprocess(new UserMessage(\"john@example.com\"));\n$state = $handler-\u003erun();\n\n// Check progress\necho $state-\u003egetCompletionPercentage();  // e.g., 75\nprint_r($state-\u003egetMissingFields());     // ['phone', 'company']\n```\n\n### Web Application Example (Controller)\n\nIn a web application, you need to use a persistent storage for the chat history to retain messages across multiple requests.\nYou can use one of the Neuron AI [chat history components](https://docs.neuron-ai.dev/agent/chat-history-and-memory)\nto store messages in a database or file system.\n\n```php\nuse App\\Forms\\RegistrationForm;\nuse NeuronAI\\Chat\\History\\FileChatHistory;\nuse NeuronAI\\Chat\\Messages\\UserMessage;\nuse NeuronAI\\Workflow\\Persistence\\FilePersistence;\n\nclass RegistrationController\n{\n    public function __invoke(Request $request): Response\n    {\n        $sessionId = $request-\u003esession()-\u003egetId();\n\n        // Create form with persistence for multi-request handling\n        $form = RegistrationForm::make()\n            -\u003esetChatHistory(new FileChatHistory(\"/tmp/chats/{$sessionId}\"));\n\n        // Send the next user message\n        $handler = $form-\u003eprocess(\n            new UserMessage($request-\u003einput('message'))\n        );\n\n        $state = $handler-\u003erun();\n\n        return response()-\u003ejson([\n            'status' =\u003e $state-\u003egetStatus()-\u003evalue,\n            'message' =\u003e $handler-\u003egetLastResponse(),\n            'completion' =\u003e $state-\u003egetCompletionPercentage(),\n            'missing_fields' =\u003e $state-\u003egetMissingFields(),\n            'is_complete' =\u003e $form-\u003eisComplete(),\n        ]);\n    }\n}\n```\n\n## Requiring Confirmation\n\nWhen you need users to review and confirm their data before submission, enable confirmation mode:\n\n```php\nclass RegistrationForm extends AIForm\n{\n    protected string $formDataClass = RegistrationData::class;\n\n    protected function provider(): AIProviderInterface\n    {\n        return new Anthropic('key', 'model');\n    }\n}\n\n// Enable confirmation in your application code\n$form = RegistrationForm::make()-\u003erequireConfirmation(true);\n```\n\n### Interruption\n\nWhen confirmation is enabled and all required fields are collected, the form throws a `FormInterruptRequest` instead of submitting immediately.\nThis interrupts the workflow and gives you control over the confirmation flow:\n\n```php\nuse NeuronAI\\Form\\Interrupt\\FormInterruptRequest;\n\n$handler = $form-\u003eprocess(new UserMessage(\"john@example.com\"));\n$state = $handler-\u003erun();\n\n// Check if the form is waiting for confirmation\nif ($handler-\u003egetInterrupt() instanceof FormInterruptRequest) {\n    $interrupt = $handler-\u003egetInterrupt();\n\n    // The interrupt contains the collected data for review\n    $data = $interrupt-\u003egetData();\n\n    // The AI-generated confirmation message\n    echo $handler-\u003egetLastResponse();\n    // \"I've collected the following information:\n    //  Name: John Doe\n    //  Email: john@example.com\n    //  Is this correct?\"\n\n    // Store the interrupt (e.g., in session) to resume later\n    $_SESSION['form_interrupt'] = serialize($interrupt);\n}\n```\n\n### Resuming After Confirmation\n\nTo resume the form after the user responds to the confirmation prompt, pass the interrupt back to `process()`:\n\n```php\n// Retrieve the stored interrupt\n$interrupt = unserialize($_SESSION['form_interrupt']);\n\n// User confirms the data\n$handler = $form-\u003eprocess(new UserMessage(\"Yes, that's correct\"), $interrupt);\n$state = $handler-\u003erun();\n\necho $state-\u003egetStatus()-\u003evalue;  // 'complete'\n\n// If the user wants to make changes\n$handler = $form-\u003eprocess(new UserMessage(\"No, I need to change my email\"), $interrupt);\n$state = $handler-\u003erun();\n\necho $state-\u003egetStatus()-\u003evalue;  // 'incomplete' - back to collecting data\n```\n\n### Confirmation Phrases\n\nThe form recognizes these confirmation responses:\n\n- **Confirm**: \"yes\", \"confirm\", \"correct\", \"right\", \"ok\", \"okay\", \"sure\", \"yep\", \"yeah\"\n- **Reject**: \"no\", \"cancel\", \"wrong\", \"incorrect\", \"change\", \"edit\", \"nope\"\n\n### Handling Cancellation\n\nUsers can cancel the form at any time using exit phrases:\n\n```php\n$handler = $form-\u003eprocess(new UserMessage(\"cancel\"));\n$state = $handler-\u003erun();\n\necho $state-\u003egetStatus()-\u003evalue;  // 'closed'\n```\n\n### Accessing Form Data\n\n```php\n// Get collected data (available during collection)\n$data = $form-\u003egetData();\n// or\n$data = $state-\u003egetCollectedData();\n\n// Get submitted data (available after submission)\n$submitted = $state-\u003egetSubmittedData();\n\n// Get form state details\n$missing = $state-\u003egetMissingFields();        // ['email', 'phone']\n$errors = $state-\u003egetValidationErrors();      // ['name' =\u003e ['must not be blank']]\n$completion = $state-\u003egetCompletionPercentage(); // 50\n```\n\n## Custom Exit Detection\n\nOverride `detectExit()` for custom cancellation logic:\n\n```php\nclass SmartForm extends AIForm\n{\n    protected function detectExit(string $content): bool\n    {\n        // Add custom exit detection\n        if (preg_match('/no\\s+thanks|not\\s+interested/i', $content)) {\n            return true;\n        }\n\n        return parent::detectExit($content);\n    }\n}\n```\n\n## Monitoring\n\nSince this component is build on top of Neuron AI Workflow, it natively supports monitoring and debugging using the\nbuilt-in [Inspector](https://inspector.dev) integration.\n\nAfter you sign up, make sure to set the `INSPECTOR_INGESTION_KEY` variable in the application environment file to start monitoring:\n\n```dotenv\nINSPECTOR_INGESTION_KEY=fwe45gtxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nAfter configuring the environment variable, you will see the agent execution timeline in your Inspector dashboard.\n\n[![](./assets/inspector.png)](https://inspector.dev)\n\nLearn more about Monitoring in the [documentation](https://docs.neuron-ai.dev/agent/observability).\n\n## Behind the scenes\n\nThis package is built on top of the Neuron AI Workflow component, just like the Agent class, but\ndesigned toward a specific use case: collecting structured data from the user conversation.\n\n- Neuron AI Workflow: https://docs.neuron-ai.dev/workflow/getting-started\n- Neuron AI Agent: https://docs.neuron-ai.dev/agent/agent\n- Neuron AI Structured Output: https://docs.neuron-ai.dev/agent/structured-output\n\n## Contribution\n\nYou are welcome to contribute to this project by submitting pull requests or issues.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneuron-core%2Fai-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneuron-core%2Fai-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneuron-core%2Fai-form/lists"}