# agentforms

Python SDK for AgentForms — programmatic form lifecycle for AI agents.

## Install

```bash
pip install agentforms
```

## Quick Start

```python
from agentforms import AgentForms

af = AgentForms(api_key="afk_live_...")

# Create a form
form = af.forms.create(
    name="Customer Feedback",
    fields=[
        {"name": "rating", "label": "Rating", "type": "select",
         "options": ["1", "2", "3", "4", "5"], "required": True},
        {"name": "feedback", "label": "Feedback", "type": "textarea"},
    ],
)
print(form.share_url)  # https://agentforms.io/{token}

# Or generate with AI (Starter tier+)
form = af.forms.generate(
    prompt="Build a job application form for a restaurant"
)

# Read submissions
subs = af.submissions.list(form.token)
for sub in subs["submissions"]:
    print(sub.dynamic_data)
```

## Human-in-the-Loop Pattern

The core agent pattern: agent needs human input → creates form → sends link → waits for webhook.

```python
from agentforms import AgentForms

af = AgentForms(api_key="afk_live_...")

# 1. Agent creates a decision gate
form = af.forms.create(
    name="Approval Request",
    metadata={"session_id": "conv_123", "agent_turn": 7},
    fields=[
        {"name": "approved", "label": "Do you approve?", "type": "select",
         "options": ["Yes", "No"], "required": True},
        {"name": "notes", "label": "Notes", "type": "textarea"},
    ],
)

# 2. Send the link to the human (via your messaging channel)
send_to_user(f"Please review: {form.share_url}")

# 3. Webhook fires when submitted → your agent continues
# Webhook payload:
#   {event: "submission", site_id: ..., fields: {approved: "Yes", notes: "..."}}
```

## Webhook Payload Schema

When a human submits a form, AgentForms POSTs to your configured webhook:

```json
{
  "event": "submission",
  "site_id": 42,
  "site_name": "Approval Request",
  "submission_id": 156,
  "submitted_at": "2026-06-12T14:30:00Z",
  "fields": {
    "approved": "Yes",
    "notes": "Looks good"
  },
  "field_metadata": {
    "visible_fields": {...},
    "computed_fields": {...},
    "applied_conditions": []
  }
}
```

See [OpenAPI spec](../openapi/openapi.yaml) for full reference.

## API Reference

| Method | Description |
|--------|-------------|
| `af.forms.create(name, fields)` | Create form with explicit fields |
| `af.forms.generate(prompt)` | AI generate form from prompt |
| `af.forms.get(token)` | Get form details |
| `af.forms.update_fields(token, fields)` | Replace all fields |
| `af.forms.delete(token)` | Delete form + submissions |
| `af.forms.list(limit, offset)` | List all forms |
| `af.submissions.list(token)` | List submissions for a form |
| `af.submissions.get(token, sub_id)` | Get single submission |
| `af.keys.create(name, permissions)` | Create API key |
| `af.keys.list()` | List API keys |
| `af.keys.revoke(key_id)` | Revoke API key |

## Error Handling

```python
from agentforms import AgentFormsError

try:
    form = af.forms.create(name="Test", fields=[])
except AgentFormsError as e:
    print(f"API error {e.status_code}: {e}")
```

## Agent Framework Examples

See [examples/](../examples/) for:
- [CrewAI human-in-the-loop](../examples/crewai_human_in_loop.py)
- [LangChain agent with form](../examples/langchain_form_agent.py)
