# @agentforms/sdk

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

## Install

```bash
npm install @agentforms/sdk
```

## Quick Start

```typescript
import { AgentForms } from '@agentforms/sdk';

const af = new AgentForms('afk_live_...');

// Create a form
const form = await af.forms.create('Customer Feedback', [
  {
    name: 'rating',
    label: 'Rating',
    type: 'select',
    options: ['1', '2', '3', '4', '5'],
    required: true,
  },
  { name: 'feedback', label: 'Feedback', type: 'textarea' },
]);
console.log(form.share_url); // https://agentforms.io/{token}

// Or generate with AI (Starter tier+)
const generatedForm = await af.forms.generate(
  'Build a job application form for a restaurant'
);

// Read submissions
const subs = await af.submissions.list(form.token);
for (const sub of subs.submissions) {
  console.log(sub.dynamic_data);
}
```

## Human-in-the-Loop Pattern

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

```typescript
import { AgentForms } from '@agentforms/sdk';

const af = new AgentForms('afk_live_...');

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

// 2. Send the link to the human (via your messaging channel)
sendToUser(`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": []
  }
}
```

## 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.updateFields(token, fields)` | Replace all fields |
| `af.forms.delete(token)` | Delete form + submissions |
| `af.forms.list(limit, offset)` | List all forms |
| `af.forms.config(token)` | Get public form config |
| `af.submissions.list(token)` | List submissions for a form |
| `af.submissions.get(token, subId)` | Get single submission |
| `af.keys.create(name, permissions)` | Create API key |
| `af.keys.list()` | List API keys |
| `af.keys.revoke(keyId)` | Revoke API key |

## Error Handling

```typescript
import { AgentForms, AgentFormsError } from '@agentforms/sdk';

const af = new AgentForms('afk_live_...');

try {
  const form = await af.forms.create('Test', []);
} catch (err) {
  if (err instanceof AgentFormsError) {
    console.error(`API error ${err.statusCode}: ${err.message}`);
  }
}
```

## Configuration

```typescript
// Custom base URL and timeout
const af = new AgentForms('afk_live_...', {
  baseURL: 'https://my-instance.agentforms.io/api/v2',
  timeout: 60, // seconds
});
```

## Types

All public types are exported for use in your codebase:

```typescript
import type {
  FieldDefinition,
  Form,
  Submission,
  WebhookPayload,
  ApiKey,
  FormsResponse,
  SubmissionsResponse,
  Permission,
} from '@agentforms/sdk';
```
