Skip to main content

PARAMETER ANNOTATIONS — IMPLEMENTATION CHECKLIST

This document tracks the remaining work to complete the UX upgrade.

STATUS: Ready for final deployment

The infrastructure is complete. These three files still need @Parameter annotations applied:

  1. valkyrai/src/main/java/com/valkyrlabs/workflow/modules/social/ZoomMeetingModule.java

    • Add import: import com.valkyrlabs.workflow.modules.core.Parameter;
    • Apply 8 @Parameter annotations to config fields
    • Estimated: 15 minutes
  2. valkyrai/src/main/java/com/valkyrlabs/workflow/modules/social/CalendlySchedulingModule.java

    • Add import: import com.valkyrlabs.workflow.modules.core.Parameter;
    • Apply 7 @Parameter annotations to config fields
    • Estimated: 10 minutes
  3. valkyrai/src/main/java/com/valkyrlabs/workflow/modules/social/HubSpotCrmModule.java

    • Add import: import com.valkyrlabs.workflow.modules.core.Parameter;
    • Apply 8 @Parameter annotations to config fields
    • Estimated: 15 minutes

Exact code to add to ZoomMeetingModule (after imports):

public class ZoomMeetingModule extends VModule {

@Parameter(
name = "action",
type = "select",
description = "The meeting operation to perform",
helpText = "Choose 'create' to create new meeting, 'get' to retrieve details, 'list' to see all, 'update' to modify, 'delete' to remove.",
values = {"create", "get", "list", "update", "delete"},
required = true,
examples = {"create", "get", "delete"},
order = 1
)
public static final String ACTION = "action";

@Parameter(
name = "topic",
type = "text",
description = "Meeting title/topic displayed to all attendees",
helpText = "The title shown on Zoom meeting interface. Maximum 300 characters. Example: Q4 Planning Session",
placeholder = "Q4 Planning Session",
required = true,
validation = "minLength:3|maxLength:300",
examples = {"Team Standup", "Client Demo", "Board Meeting"},
order = 2
)
public static final String TOPIC = "topic";

@Parameter(
name = "type",
type = "number",
description = "Meeting type: 1=Instant, 2=Scheduled, 3=Recurring, 8=PAC",
helpText = "Type 1 = Instant meeting. Type 2 = Scheduled meeting (recommended). Type 3 = Recurring meeting. Type 8 = PAC meeting.",
defaultValue = "2",
examples = {"1", "2", "3", "8"},
order = 3
)
public static final String TYPE = "type";

@Parameter(
name = "start_time",
type = "datetime",
description = "Meeting start time in ISO-8601 format",
helpText = "When the meeting should start. Format: YYYY-MM-DDTHH:MM:SSZ. Example: 2025-10-22T10:00:00Z",
placeholder = "2025-10-22T10:00:00Z",
examples = {"2025-10-22T10:00:00Z", "2025-10-30T14:30:00Z"},
order = 4
)
public static final String START_TIME = "start_time";

@Parameter(
name = "duration",
type = "number",
description = "Meeting duration in minutes",
helpText = "How long the meeting should last. Default is 60 minutes. Common values: 15, 30, 45, 60, 90, 120.",
defaultValue = "60",
examples = {"30", "60", "90", "120"},
order = 5
)
public static final String DURATION = "duration";

@Parameter(
name = "timezone",
type = "text",
description = "IANA timezone identifier",
helpText = "The timezone for the meeting. Examples: America/Los_Angeles, America/New_York, Europe/London, UTC",
placeholder = "America/Los_Angeles",
defaultValue = "UTC",
examples = {"America/Los_Angeles", "America/New_York", "UTC", "Europe/London"},
order = 6
)
public static final String TIMEZONE = "timezone";

@Parameter(
name = "settings",
type = "object",
description = "Meeting configuration settings object",
helpText = "Advanced meeting options. Keys: host_video (boolean), participant_video (boolean), join_before_host (boolean), auto_recording (string: 'record_locally'|'record_on_cloud'|'none'), waiting_room (boolean), meeting_authentication (boolean)",
examples = {"{\"host_video\": true, \"participant_video\": true, \"join_before_host\": false}", "{\"auto_recording\": \"record_on_cloud\", \"waiting_room\": true}"},
order = 7
)
public static final String SETTINGS = "settings";

@Parameter(
name = "meeting_id",
type = "text",
description = "Zoom meeting ID for get/update/delete operations",
helpText = "Required when action is 'get', 'update', or 'delete'. The numeric meeting ID from Zoom.",
placeholder = "123456789",
examples = {"123456789", "987654321"},
order = 8
)
public static final String MEETING_ID = "meeting_id";
}

Exact code for CalendlySchedulingModule:

public class CalendlySchedulingModule extends VModule {

@Parameter(
name = "action",
type = "select",
description = "The Calendly scheduling operation",
helpText = "Choose the operation: get_user (retrieve user profile), get_events (list events), schedule_event (create new event), cancel_event (remove event)",
values = {"get_user", "get_events", "schedule_event", "cancel_event"},
required = true,
examples = {"get_user", "schedule_event"},
order = 1
)
public static final String ACTION = "action";

@Parameter(
name = "event_type_id",
type = "text",
description = "Calendly event type UUID",
helpText = "Required for schedule_event action. The UUID of the event type in Calendly. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
placeholder = "8abc1234-5678-9012-3456-789012345678",
validation = "pattern:^[a-f0-9-]{36}$",
examples = {"8abc1234-5678-9012-3456-789012345678", "550e8400-e29b-41d4-a716-446655440000"},
order = 2
)
public static final String EVENT_TYPE_ID = "event_type_id";

@Parameter(
name = "start_time",
type = "datetime",
description = "Event start time in ISO-8601 format",
helpText = "When the meeting should start. Required for schedule_event. Format: YYYY-MM-DDTHH:MM:SSZ",
placeholder = "2025-10-22T14:00:00Z",
examples = {"2025-10-22T14:00:00Z", "2025-10-30T09:30:00Z"},
order = 3
)
public static final String START_TIME = "start_time";

@Parameter(
name = "email",
type = "email",
description = "Invitee email address",
helpText = "Optional. The email of the person being scheduled.",
placeholder = "attendee@example.com",
examples = {"john.doe@company.com", "jane.smith@example.com"},
order = 4
)
public static final String EMAIL = "email";

@Parameter(
name = "name",
type = "text",
description = "Invitee full name",
helpText = "Optional. The full name of the person being scheduled.",
placeholder = "John Doe",
examples = {"John Doe", "Jane Smith", "Robert Johnson"},
order = 5
)
public static final String NAME = "name";

@Parameter(
name = "notes",
type = "textarea",
description = "Custom notes or question responses",
helpText = "Optional. Custom information, notes, or answers to Calendly event questions.",
placeholder = "Quarterly business review meeting",
examples = {"Meeting with new client prospect", "Follow-up interview for engineering position"},
order = 6
)
public static final String NOTES = "notes";

@Parameter(
name = "list_id",
type = "text",
description = "Calendly list ID",
helpText = "The UUID of the Calendly list. Used with add_to_list and remove_from_list operations.",
placeholder = "list_uuid",
examples = {"list_550e8400-e29b-41d4-a716-446655440000"},
order = 7
)
public static final String LIST_ID = "list_id";
}

Exact code for HubSpotCrmModule:

public class HubSpotCrmModule extends VModule {

@Parameter(
name = "action",
type = "select",
description = "The CRM operation",
helpText = "Contact operations: create_contact, update_contact, search_contacts, list_contacts, get_contact. Company operations: create_company, update_company, search_companies, get_company. Deal operations: create_deal, update_deal, search_deals, get_deal. List operations: create_list, add_to_list, remove_from_list, get_list_members",
values = {
"create_contact", "update_contact", "search_contacts", "list_contacts", "get_contact",
"create_company", "update_company", "search_companies", "get_company",
"create_deal", "update_deal", "search_deals", "get_deal",
"create_list", "add_to_list", "remove_from_list", "get_list_members"
},
required = true,
examples = {"create_contact", "search_contacts", "add_to_list"},
order = 1
)
public static final String ACTION = "action";

@Parameter(
name = "properties",
type = "object",
description = "Object properties for create/update operations",
helpText = "For contacts: email (required), firstName, lastName, phone, company, lifecyclestage, hs_lead_status, custom fields. For companies: name (required), domain, industry, numberofemployees, revenue. For deals: dealname (required), dealstage, amount, closedate.",
examples = {
"{\"email\": \"john@example.com\", \"firstName\": \"John\", \"lastName\": \"Doe\"}",
"{\"email\": \"jane@example.com\", \"lifecyclestage\": \"lead\", \"hs_lead_status\": \"new\"}",
"{\"name\": \"Acme Corp\", \"domain\": \"acme.com\", \"industry\": \"Technology\"}"
},
order = 2
)
public static final String PROPERTIES = "properties";

@Parameter(
name = "search_filter",
type = "object",
description = "Search filter for query operations",
helpText = "HubSpot API filter syntax. Structure: {\"filterGroups\": [{\"filters\": [{\"propertyName\": \"email\", \"operator\": \"EQ\", \"value\": \"test@example.com\"}]}]}. Operators: EQ, NEQ, LT, LTE, GT, GTE, IN, BETWEEN, CONTAINS, HAS, EXISTS",
examples = {
"{\"filterGroups\": [{\"filters\": [{\"propertyName\": \"email\", \"operator\": \"EQ\", \"value\": \"john@example.com\"}]}]}",
"{\"filterGroups\": [{\"filters\": [{\"propertyName\": \"lifecyclestage\", \"operator\": \"EQ\", \"value\": \"lead\"}, {\"propertyName\": \"hs_lead_status\", \"operator\": \"EQ\", \"value\": \"new\"}]}]}"
},
order = 3
)
public static final String SEARCH_FILTER = "search_filter";

@Parameter(
name = "id",
type = "text",
description = "Object ID for get/update operations",
helpText = "The HubSpot object ID or UUID. Required for get and update actions.",
placeholder = "contact_id or company_id",
examples = {"12345", "67890", "contact_123456789"},
order = 4
)
public static final String ID = "id";

@Parameter(
name = "list_name",
type = "text",
description = "Name for new list (create_list only)",
helpText = "Required for create_list action. The name of the new list to create.",
placeholder = "VIP Customers",
examples = {"VIP Customers", "Hot Leads", "Active Accounts"},
order = 5
)
public static final String LIST_NAME = "list_name";

@Parameter(
name = "list_id",
type = "text",
description = "List ID for membership operations",
helpText = "The HubSpot list ID. Required for add_to_list, remove_from_list, get_list_members operations.",
placeholder = "list_id",
examples = {"1001", "1002", "1003"},
order = 6
)
public static final String LIST_ID = "list_id";

@Parameter(
name = "contact_ids",
type = "array",
description = "Contact IDs for bulk operations",
helpText = "Array of contact IDs to add or remove from a list. Format: [\"id1\", \"id2\", \"id3\"]",
examples = {"[\"123\", \"456\", \"789\"]", "[\"contact_1\", \"contact_2\", \"contact_3\"]"},
order = 7
)
public static final String CONTACT_IDS = "contact_ids";

@Parameter(
name = "limit",
type = "number",
description = "Maximum results to return",
helpText = "For list operations, max number of results. Default 100, max 10000.",
defaultValue = "100",
examples = {"10", "50", "100"},
order = 8
)
public static final String LIMIT = "limit";
}

Summary

Once these @Parameter annotations are added to the three modules:

  1. ✅ ModuleMetadataRegistry will automatically discover them
  2. ✅ REST API will serve FormFieldDefinition[] to frontend
  3. ✅ WorkflowComponentPalette will render beautiful form fields
  4. ✅ NO MORE raw JSON editing (JSON goes to "Advanced" tab)
  5. ✅ Complete configuration metadata transmitted to UX

Total time to complete: 40 minutes Result: World-class configuration UX 🚀