-
Notifications
You must be signed in to change notification settings - Fork 161
Description
Pre-requisities
- I am using the newest version of the platform (
agentstack versionshows that CLI and platform are the same version, and there is no newer version available)
Describe the bug
If building an agent that has both a settings element containing a agentstack_sdk.a2a.extensions.ui.settings.SingleSelectField and then requests a form mid conversation that also includes a agentstack_sdk.a2a.extensions.ui.form.SingleSelectField, you get an import clash (Assuming this is all in the same file) resulting in pydantic validation errors for the agentstack_sdk.a2a.extensions.ui.form.SingleSelectField.
agentstack_sdk.a2a.extensions.ui.settings.OptionItem and agentstack_sdk.a2a.extensions.ui.form.OptionItem are similarly affected.
The equivalent types are similar enough that when defining them, mypy complains about things like id or value missing from the OptionItem. You can try and resolve this by adding the missing field in, but upon execution, an exception will be thrown when attempting to render the mid chat form.
A quick workaround is just to alias one of the pair on import like so:
from agentstack_sdk.a2a.extensions.ui.settings import (
OptionItem as SettingsOptionItem,
SingleSelectField as SettingsSingleSelectField,
)However, I think longer term, it might be worth combining the Settings and Form classes into a single common form class as there is so much overlap between the two.
To Reproduce
Create a simple agent that uses a agentstack_sdk.a2a.extensions.ui.settings.SingleSelectField in it's settings, and then requests a form mid chat using agentstack_sdk.a2a.extensions.ui.form.SingleSelectField.
Expected behavior
Both the settings and the mid chat form should render correctly.
Logs / Screenshots / Code snippets
Example to re-produce:
from typing import Annotated
from a2a.types import Message
from a2a.utils.message import get_message_text
from agentstack_sdk.a2a.extensions.ui.form import (
FormExtensionServer,
FormExtensionSpec,
FormRender,
OptionItem,
SingleSelectField,
)
from agentstack_sdk.a2a.extensions.ui.settings import (
OptionItem,
SettingsExtensionServer,
SettingsExtensionSpec,
SettingsRender,
SingleSelectField,
)
from agentstack_sdk.server import Server
from pydantic import BaseModel
server = Server()
class ContactInfo(BaseModel):
contact_method: str | None
vector_store_doctype_select = SingleSelectField(
id="vector_store_doc_type",
options=[
OptionItem(value="sql_query", label="SQL Queries"),
OptionItem(value="question", label="Questions"),
OptionItem(value="both", label="Both"),
],
default_value="sql_queries",
label="Vector Store Doc Type"
)
@server.agent()
async def dynamic_form_agent(
message: Message,
form_request: Annotated[FormExtensionServer, FormExtensionSpec(params=None)],
settings: Annotated[SettingsExtensionServer, SettingsExtensionSpec(
params=SettingsRender(
fields=[vector_store_doctype_select]
)
)]
):
"""Agent that requests forms dynamically during conversation"""
user_input = get_message_text(message)
# Check if user wants to provide contact information
if "contact" in user_input.lower() or "reach" in user_input.lower():
# Request contact form dynamically
contact_info = await form_request.request_form(
form=FormRender(
title="Please provide your contact information",
columns=2,
fields=[
SingleSelectField(
id="contact_method",
label="Preferred Contact Method",
col_span=2,
required=False,
options=[
OptionItem(id="email", label="Email"),
OptionItem(id="phone", label="Phone"),
OptionItem(id="sms", label="SMS"),
OptionItem(id="none", label="Do not contact"),
],
default_value="email",
)
],
model=ContactInfo
)
)
if contact_info is None:
yield "No contact information received."
else:
yield f"Thank you! I'll contact you at {contact_info.email} or {contact_info.phone} regarding {contact_info.company}."
else:
yield "Hello! If you'd like me to contact you, just let me know and I'll ask for your details."
if __name__ == "__main__":
server.run()Metadata
Metadata
Assignees
Labels
Type
Projects
Status