# Phase B: AI-Powered Action Suggestions — Implementation Plan
## 1. Codebase Research Summary
### What Exists Today
#### Agent API (`app/routes/agent_api.py`)
- **All routes under `/api/v2/` prefix** — v2 sites, actions, submissions, analytics, campaigns, templates
- **No `/api/agent/build` endpoint exists** — it's documented in the spec but not implemented
- Auth: `X-API-Key` header via `_authenticate_api_key()` helper
- Site creation uses `add_site()` from models
- Action CRUD via `create_action()`, `update_action()`, `delete_action()`
#### LLM Integration
- **No dedicated LLM client module exists** — spec documents raw `requests.post()` to `{LLM_HOST}/v1/chat/completions`
- Model: Qwen3.5-4B via llama.cpp on port 8086 (configured via `BUILDER_LLM_HOST` env var)
- OpenAI-compatible API format with system/user message pattern
- No prompt templates, response parsing, or streaming logic implemented yet
#### Action Types (6 types)
| Type | Purpose | Config Schema |
|---|---|---|
| `webhook` | POST to URL | url, method, headers, body_template |
| `email` | Send email | recipients, subject, body_template |
| `log` | Audit logging | message_template |
| `redirect` | Redirect user | url, delay |
| `document` | Generate doc | template_id, output_format |
| `chain` | Multi-step workflow | name, steps[] |
#### Chain Step Types (12 types)
`webhook`, `email`, `document`, `wait`, `condition`, `webhook_batch`, `log`, `redirect`, `llm`, `variable_set`, `variable_merge`, `http_call`
#### Chain Templates (11 pre-built)
- `notification_chain` — email + webhook + log
- `crm_sync_chain` — webhook (create) + webhook (update)
- `support_workflow_chain` — email + webhook + wait + email
- `approval_workflow_chain` — email → condition → email/webhook
- `multi_vendor_chain` — webhook_batch + wait + webhook
- `document_workflow_chain` — document + email + webhook
- `lead_routing_chain` — webhook → wait → email
- `data_pipeline_chain` — http_call + webhook + condition + log
- `notification_escalation_chain` — email → wait → condition → webhook → log
- `onboarding_sequence_chain` — email → wait → email → wait → webhook → log
- `marketing_automation_chain` — webhook → email → wait → email
#### Chain Templates Categories
`notification`, `crm_sync`, `support`, `approval`, `multi_vendor`, `document_workflow`, `lead_routing`, `data_pipeline`, `escalation`, `onboarding`, `marketing`
#### Chain Engine (`app/services/chain_engine.py`)
- `validate_chain(config)` — validates chain before saving
- `execute_chain(action_id, submission_data)` — full chain execution with variable scope, conditions, LLM steps
- `evaluate_condition(step, scope)` — condition evaluation
- `execute_chain_step(step, scope)` — step dispatch
- `_execute_llm_step(step, scope)` — LLM step execution (uses `LLM_HOST` for variable enrichment)
- `execute_chain_sync(action_id, submission_data)` — sync execution
- Steps stored as JSON in `config["steps"]` array
#### Action Pipeline (`app/services/action_pipeline.py`)
- `execute_action(action, submission_data)` — dispatches action by type
- `_execute_webhook()` — POST with Jinja2 templating, retry logic
- `_execute_email()` — via Resend API
- `_execute_document()` — template rendering
- `_execute_chain(action_id, submission_data)` — delegates to chain_engine
#### DB Schema (SQLite)
```sql
CREATE TABLE actions (
id INTEGER PRIMARY KEY,
site_id INTEGER REFERENCES sites(id),
type TEXT, -- webhook/email/log/redirect/document/chain
config TEXT, -- JSON object
trigger_event TEXT DEFAULT 'submission',
enabled BOOLEAN DEFAULT 1,
execution_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE form_versions (
id INTEGER PRIMARY KEY,
site_id INTEGER REFERENCES sites(id),
field_config TEXT, -- JSON snapshot
version_number INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
#### What's Missing for Phase B
1. `/api/agent/build` endpoint (documented, not built)
2. LLM client module (no reusable client exists)
3. Chain suggestion engine (LLM-based action/chain recommendations)
4. Suggested chains storage (temporary or draft table)
5. One-click deploy for suggested chains
6. Edit-before-deploy workflow
## 2. Phase B Implementation Plan
### 2.1. New Files to Create
| File | Purpose |
|---|---|
| `app/services/llm_client.py` | Reusable LLM client with prompt templates, response parsing, retry logic |
| `app/services/chain_suggester.py` | LLM-based chain suggestion engine — takes user prompt + field context, returns suggested action chains |
| `app/routes/agent_build.py` | `/api/agent/build` endpoint + `/api/agent/suggest-chains` + `/api/agent/deploy-chain` endpoints |
| `app/models_suggested_chains.py` | DB operations for suggested chains (temporary storage) |
### 2.2. Files to Modify
| File | Changes |
|---|---|
| `app/__init__.py` | Register new `agent_build` blueprint |
| `app/migrations.py` | Add `migrate_suggested_chains()` for new table |
| `docs/agent-infrastructure-spec.md` | Update Phase B status, add new endpoints |
### 2.3. DB Changes
#### New Table: `suggested_chains`
```sql
CREATE TABLE suggested_chains (
id INTEGER PRIMARY KEY,
site_id INTEGER REFERENCES sites(id),
prompt TEXT, -- Original user prompt
suggested_actions TEXT, -- JSON array of suggested actions
status TEXT DEFAULT 'pending', -- pending | deployed | discarded
user_edits TEXT, -- JSON of user modifications
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP -- Auto-expire after 24h
);
CREATE INDEX idx_suggested_chains_site ON suggested_chains(site_id);
CREATE INDEX idx_suggested_chains_status ON suggested_chains(status);
```
This table acts as a temporary staging area for AI suggestions before deployment.
### 2.4. API Endpoint Design
#### `POST /api/agent/build`
The main entry point — accepts a natural language prompt and returns a complete form + suggested action chains.
**Request:**
```json
{
"prompt": "Create a client intake form for our consulting business: client name, company, email, phone, project description, budget range, timeline",
"form_type": "form",
"theme": { "primary": "#2563eb" },
"suggest_chains": true // Phase B addition
}
```
**Response:**
```json
{
"success": true,
"site_id": 42,
"token": "abc123xyz",
"fields": [...],
"actions_suggested": [
{
"id": "suggest_1",
"type": "chain",
"name": "Lead Management Workflow",
"description": "Notify your team, sync to CRM, then send a follow-up after 24h",
"confidence": 0.92,
"category": "lead_routing",
"steps": [
{
"id": "step_1",
"type": "email",
"name": "Notify Sales Team",
"config": {
"recipients": ["{{owner_email}}"],
"subject": "New lead: {{client_name}}",
"body_template": "..."
}
},
{
"id": "step_2",
"type": "webhook",
"name": "Sync to CRM",
"config": {
"url": "",
"method": "POST",
"body_template": "{{ submission_data }}"
},
"requires_config": ["url"]
},
{
"id": "step_3",
"type": "wait",
"name": "Wait 24 hours",
"config": { "duration": "24h" }
},
{
"id": "step_4",
"type": "email",
"name": "Follow-up Email",
"config": { ... }
}
],
"suggestion_id": "sc_abc123" // References suggested_chains DB record
}
],
"embed_url": "https://agentforms.io/embed/abc123xyz"
}
```
Key design decisions:
- `confidence` score (0.0–1.0) tells UI how strongly the LLM recommends this
- `requires_config` flags which step fields the user must fill before deploying
- `suggestion_id` ties back to the `suggested_chains` DB record for edit/deploy
#### `POST /api/agent/suggest-chains`
Standalone endpoint to get chain suggestions for an existing site (without rebuilding the form).
**Request:**
```json
{
"site_id": 42,
"prompt": "I want to set up automated follow-up emails after form submission"
}
```
**Response:**
```json
{
"success": true,
"suggestions": [ ... same format as actions_suggested above ... ]
}
```
#### `POST /api/agent/deploy-chain`
One-click deploy — takes a suggestion (with optional edits) and creates the real action.
**Request:**
```json
{
"site_id": 42,
"suggestion_id": "sc_abc123",
"steps": [
{
"id": "step_2",
"type": "webhook",
"name": "Sync to CRM",
"config": {
"url": "https://my-crm.com/api/leads", // User filled this in
"method": "POST",
"body_template": "{{ submission_data }}"
}
}
] // Only steps that were edited/added; omitted steps use original suggestion
}
```
**Response:**
```json
{
"success": true,
"action_id": 156,
"chain_steps": 4
}
```
#### `PUT /api/agent/suggestions/:suggestion_id`
Edit a suggested chain before deploying.
**Request:**
```json
{
"steps": [
// Modified steps — full replacement of the suggestion's steps
{ "id": "step_1", "type": "email", "name": "Notify Team", "config": {...} },
// ... all steps with user modifications
],
// Or partial edits:
"edits": {
"step_2.config.url": "https://my-crm.com/api/leads",
"step_3.config.duration": "12h"
}
}
```
#### `DELETE /api/agent/suggestions/:suggestion_id`
Discard a suggestion.
### 2.5. LLM Prompt Structure
#### System Prompt for Chain Suggestions
```
You are an automated workflow suggestion engine for AgentForms, a form automation platform.
Given a user's form description and form fields, suggest optimal post-submission action chains.
Available action step types:
- webhook: POST to any URL with submission data
- email: Send formatted email
- log: Store in audit log
- redirect: Redirect user to URL
- document: Generate PDF/DOCX from template
- wait: Pause for a duration (e.g., "24h", "1d", "2w")
- condition: Branch based on submission field values
- webhook_batch: Send to multiple endpoints simultaneously
- llm: Enrich data using AI (adds variables to submission)
- variable_set: Set a variable from field value
- variable_merge: Merge multiple fields into one variable
- http_call: Generic HTTP request (GET/PUT/DELETE)
Available pre-built chain templates by category:
- notification: email + webhook + log
- crm_sync: webhook (create) + webhook (update)
- support: email + webhook + wait + email
- approval: email → condition → email/webhook
- multi_vendor: webhook_batch + wait + webhook
- document_workflow: document + email + webhook
- lead_routing: webhook → wait → email
- data_pipeline: http_call + webhook + condition + log
- escalation: email → wait → condition → webhook → log
- onboarding: email → wait → email → wait → webhook → log
- marketing: webhook → email → wait → email
Rules:
1. Always suggest the MOST relevant chain based on the form purpose
2. Fill in realistic defaults for config fields when possible
3. Mark fields that require user configuration with "requires_config"
4. Use {{field_key}} template syntax for referencing form fields
5. Keep chains practical (2-6 steps, not excessive)
6. If multiple chains make sense, suggest the primary one and mention alternatives
7. Use pre-built templates as starting points when they fit
8. Confidence: high (0.8+) when form purpose clearly matches a template, low (<0.5) when uncertain
Response format — return ONLY valid JSON:
{
"suggested_chains": [
{
"name": "string",
"description": "string",
"confidence": 0.0-1.0,
"category": "string (one of the template categories)",
"steps": [
{
"type": "string",
"name": "string",
"config": {},
"requires_config": ["field_names_if_any"]
}
]
}
]
}
```
#### User Prompt Template
```
Form purpose: {prompt}
Form type: {form_type}
Form fields:
{field_list_json}
Suggest the best post-submission action chain(s) for this form.
Consider: What typically happens after someone submits this kind of form?
Who needs to be notified? Where does the data need to go? What follow-up actions make sense?
```
#### Field List Format for LLM
```json
[
{"key": "client_name", "type": "text", "label": "Client Name"},
{"key": "company", "type": "text", "label": "Company"},
{"key": "email", "type": "email", "label": "Email"},
{"key": "budget", "type": "select", "label": "Budget Range", "options": ["Under $5K", "$5K-$15K", "$15K-$50K", "$50K+"]},
{"key": "project_description", "type": "textarea", "label": "Project Description"}
]
```
### 2.6. Response Format — Detailed
The `/api/agent/build` response needs to support both the existing spec contract AND Phase B additions:
```json
{
"success": true,
"site_id": 42,
"token": "abc123",
"fields": [...], // Existing: generated field config
"actions_suggested": [...], // Phase B: suggested action chains
"embed_url": "https://agentforms.io/embed/abc123",
"meta": {
"llm_model": "qwen3.5-4b",
"llm_tokens_used": 1247,
"suggestions_generated": true,
"suggestion_ids": ["sc_abc123"]
}
}
```
Each `actions_suggested` item:
```json
{
"id": "suggest_1", // UI identifier
"type": "chain",
"name": "Lead Management Workflow",
"description": "Notify your team, sync to CRM, then send a follow-up after 24h",
"confidence": 0.92,
"category": "lead_routing",
"steps": [
{
"id": "step_1",
"type": "email",
"name": "Notify Sales Team",
"config": {
"recipients": ["{{owner_email}}"],
"subject": "New lead: {{client_name}}",
"body_template": "A new lead has submitted..."
},
"requires_config": []
},
{
"id": "step_2",
"type": "webhook",
"name": "Sync to CRM",
"config": {
"url": "",
"method": "POST",
"body_template": "{{ submission_data }}"
},
"requires_config": ["url"] // User must fill this
}
],
"suggestion_id": "sc_abc123", // DB reference
"can_deploy": false // false if requires_config fields are empty
}
```
### 2.7. Implementation Order (Recommended)
#### Step 1: LLM Client Module (`app/services/llm_client.py`)
- Create reusable client with `generate(prompt, system_prompt, temperature, max_tokens)`
- JSON response parsing with retry on parse failure
- Config from `BUILDER_LLM_HOST` env var
- This centralizes LLM access for both the existing (future) `/agent/build` form generation AND the new chain suggestions
#### Step 2: Suggested Chains Table + Models
- Migration for `suggested_chains` table
- `app/models_suggested_chains.py` with `create_suggestion()`, `get_suggestion()`, `update_suggestion()`, `deploy_suggestion()`, `delete_suggestion()`, `cleanup_expired()`
#### Step 3: Chain Suggester Service (`app/services/chain_suggester.py`)
- `suggest_chains(prompt, fields, form_type)` → list of suggested chain objects
- Uses llm_client with the system prompt defined above
- Validates LLM output against expected schema
- Falls back to template-based matching if LLM fails
#### Step 4: Agent Build Endpoint (`app/routes/agent_build.py`)
- `POST /api/agent/build` — main endpoint
- `POST /api/agent/suggest-chains` — standalone suggestions
- `POST /api/agent/deploy-chain` — one-click deploy
- `PUT /api/agent/suggestions/:id` — edit suggestion
- `DELETE /api/agent/suggestions/:id` — discard suggestion
#### Step 5: Wire Up + Register
- Register `agent_build_bp` in `app/__init__.py`
- Run migration
- Test end-to-end
### 2.8. Fallback Strategy
If the LLM is unavailable or returns invalid output:
1. Match form type/prompt keywords to pre-built chain templates from `chain_templates.py`
2. Return template-based suggestions with `confidence: 0.5` and `"llm_fallback": true` flag
3. This ensures the feature is always available even if the LLM is down
### 2.9. Edge Cases & Considerations
- **Rate limiting**: LLM calls are expensive — add per-user rate limiting on `/api/agent/build` and `/api/agent/suggest-chains`
- **Expiry**: `suggested_chains` records expire after 24h — add a background cleanup (can run in the existing rate limiter cleanup thread)
- **Security**: Validate all user edits against the action schema before deploying
- **Template variables**: In suggested chains, use `{{owner_email}}` for the site owner (resolved at deploy time) and `{{field_key}}` for form fields
- **Chain validation**: Run `validate_chain()` before deploying — reject invalid chains
- **One-click deploy creates a `type=chain` action**: The deployed action follows the exact same format as manually created chains
### 2.10. File Structure After Phase B
```
app/
├── __init__.py # Modified: register agent_build_bp
├── migrations.py # Modified: add suggested_chains table
├── models.py # (no changes needed)
├── models_suggested_chains.py # NEW
├── routes/
│ ├── agent_api.py # (no changes — v2 routes)
│ ├── agent_build.py # NEW: /api/agent/* endpoints
│ └── ...
├── services/
│ ├── llm_client.py # NEW: reusable LLM client
│ ├── chain_suggester.py # NEW: chain suggestion engine
│ ├── chain_engine.py # (no changes)
│ ├── chain_templates.py # (no changes)
│ ├── action_pipeline.py # (no changes)
│ └── ...
└── ...
```
## 3. Summary
| Area | Status | Action |
|---|---|---|
| `/api/agent/build` endpoint | Not implemented | Create `app/routes/agent_build.py` |
| LLM client | No module exists | Create `app/services/llm_client.py` |
| Chain suggestion engine | Does not exist | Create `app/services/chain_suggester.py` |
| Suggested chains storage | No table | Add `suggested_chains` table + models |
| One-click deploy | Does not exist | `POST /api/agent/deploy-chain` endpoint |
| Edit before deploy | Does not exist | `PUT /api/agent/suggestions/:id` endpoint |
| Delete suggestion | Does not exist | `DELETE /api/agent/suggestions/:id` endpoint |
| Chain validation | Exists | Reuse existing `validate_chain()` |
| Chain templates | 11 templates exist | Use as LLM context + fallback |
| Chain engine execution | Fully working | Deployed chains use existing engine |