You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -5,59 +5,62 @@ description: "Collect structured input from users"
5
5
6
6
One of the most powerful features of the Agent Stack is the ability to request structured data from users through interactive forms. Instead of relying on free-form text input, your agent can present users with specific fields, dropdowns, and other form elements to gather precise information.
7
7
8
-
The Agent Stack provides a Form extension that allows you to collect structured data from users in two ways:
8
+
The Agent Stack provides a Form extensions that allows you to collect structured data from users in two ways:
9
9
10
10
1.**Initial form rendering** - Present a form as the first interaction before users start a conversation with your agent
11
11
2.**Dynamic form requests** - Request forms at any point during a multi-turn conversation when your agent needs specific structured input
12
12
13
+
## Initial Form Rendering
14
+
15
+
For initial form rendering, you specify the form structure when injecting the extension and then parse the response using a Pydantic model. The form is presented to users before they start a conversation with your agent.
For dynamic form requests during conversation, you can request forms at any point when your agent needs structured input. This is useful when your agent needs to collect additional information based on the conversation flow:
91
+
For dynamic form requests during conversation, you can request forms at any point when your agent needs structured input. This is useful when your agent needs to collect additional information based on the conversation flow.
Here's what you need to know to add form capabilities to your agent:
155
178
156
-
**Import the form extension**: Import `FormExtensionServer`, `FormExtensionSpec`, `FormRender`, and field types from `agentstack_sdk.a2a.extensions.ui.form`.
157
-
158
-
**Inject the extension**: Add a form parameter to your agent function using the `Annotated` type hint with `FormExtensionServer` and `FormExtensionSpec`.
179
+
**Import the form components**:
180
+
- For form fields and `FormRender`, import from `agentstack_sdk.a2a.extensions.common.form`
181
+
- For initial forms, import `FormServiceExtensionServer` and `FormServiceExtensionSpec` from `agentstack_sdk.a2a.extensions.services.form`
182
+
- For dynamic forms, import `RequestFormExtensionServer` and `RequestFormExtensionSpec` from `agentstack_sdk.a2a.extensions.ui.request_form`
159
183
160
-
**For initial forms**: Specify the form structure in the `FormExtensionSpec` parameters and use `parse_form_response()` to extract data from the initial message.
184
+
**Inject the extension**: Add a form parameter to your agent function using the `Annotated` type hint.
161
185
162
-
**For dynamic forms**: Use an empty `FormExtensionSpec()`and call `await form.request_form()`with your form definition when needed.
186
+
**For initial forms**: Use `FormServiceExtensionSpec.demand(initial_form=FormRender(...))` to specify the form structure and call `form.parse_initial_form(model=YourModel)`to extract data.
163
187
164
-
**Access form data**: Use `form_data.values['field_id'].value` to access the submitted values from your form fields. Different field types return different value types:
165
-
166
-
-**TextField/DateField**: Returns `str | None`
167
-
-**FileField**: Returns `list[FileInfo] | None` where each `FileInfo` has `uri`, `name`, and `mime_type`
-**MultiSelectField**: Returns `list[str] | None` (list of selected option IDs)
170
-
-**CheckboxField**: Returns `bool | None`
188
+
**For dynamic forms**: Use `RequestFormExtensionSpec()` and call `await request_form.request_form(form=FormRender(...), model=YourModel)` when needed.
171
189
172
-
As a convenient shortcut, you may use a custom model (Pydantic model, `TypedDict`, `dataclass`, or any class supported by `pydantic.TypeAdapter`) to load form data. For example, we can define a following model:
190
+
**Access form data**: The recommended approach is to use a Pydantic model (or `TypedDict`, `dataclass`, or any class supported by `pydantic.TypeAdapter`) to load form data. Define a model with fields matching your form field IDs:
173
191
174
192
```python
175
193
from pydantic import BaseModel
@@ -180,12 +198,27 @@ class ContactInfo(BaseModel):
180
198
company: str|None
181
199
```
182
200
183
-
Then, in agent code, pass `model=ContactInfo` to `parse_form_response(...)` or `request_form(...)` to get the form data directly as an instance of `ContactInfo`:
201
+
Then, pass `model=ContactInfo` to `parse_initial_form(...)` or `request_form(...)` to get the form data directly as an instance of `ContactInfo`:
If you don't use a model, the methods return `FormResponse` which has a `values` dictionary. You can access values using `form_data.values['field_id'].value`. Different field types return different value types:
215
+
216
+
-**TextField/DateField**: Returns `str | None`
217
+
-**FileField**: Returns `list[FileInfo] | None` where each `FileInfo` has `uri`, `name`, and `mime_type`
0 commit comments