Documentation Index
Fetch the complete documentation index at: https://docs.expectedparrot.com/llms.txt
Use this file to discover all available pages before exploring further.
This page covers code methods for launching surveys, gathering human responses, and analyzing results. For interactive survey building, see Survey Builder. For Prolific recruitment, see Prolific studies. For email notifications and scheduled reminders, see Survey notifications.
How it works
Humanize the survey to generate a web-hosted version on Expected Parrot with a respondent link and an admin dashboard.
Share the respondent link with human participants (or recruit via Prolific). Collect responses back as a standard EDSL Results object.
Analyze your human results alongside any LLM results.
Basic usage
from edsl import Survey, QuestionMultipleChoice, QuestionFreeText, QuestionLinearScale
q1 = QuestionMultipleChoice(
question_name="frequency",
question_text="How often do you work from home?",
question_options=["Never", "1-2 days a week", "3-4 days a week", "Every day"],
)
q2 = QuestionLinearScale(
question_name="satisfaction",
question_text="How satisfied are you with your current work arrangement?",
question_options=[1, 2, 3, 4, 5],
option_labels={1: "Very dissatisfied", 5: "Very satisfied"},
)
q3 = QuestionFreeText(
question_name="improvement",
question_text="What one change would most improve your day-to-day work experience?",
)
survey = Survey([q1, q2, q3])
info = survey.humanize(
human_survey_name="Workplace Experience Survey",
survey_description="A short survey about remote and in-office work preferences.",
survey_visibility="unlisted",
)
print(info["respondent_url"]) # share with respondents
print(info["admin_url"]) # monitor responses
print(info["uuid"]) # save this to retrieve results later
.humanize() parameters
| Parameter | Type | Default | Description |
|---|
human_survey_name | str | "New survey" | Display name on Coop |
survey_description | str | None | None | Optional description |
survey_alias | str | None | None | URL-friendly alias |
survey_visibility | str | "private" | "private", "public", or "unlisted" |
humanize_schema | dict | None | None | Controls question styling and optionality — see Humanize schema |
delivery_map | DeliveryMap | None | None | Maps delivery channels to agent trait columns; required for email notifications |
Return value
survey.humanize() returns a Scenario (dict-like) with these keys:
| Key | Description |
|---|
uuid | Human survey UUID — needed to fetch responses later |
respondent_url | Public link for respondents |
admin_url | Admin dashboard link |
name | Survey name |
n_responses | Response count (0 at creation) |
survey_uuid | UUID of the pushed survey object |
scenario_list_uuid | UUID of the pushed scenario list (if any) |
Save the uuid — you need it to retrieve responses.
Previewing before deployment
Use .preview() to get a preview URL without creating a live survey:
preview_url = survey.preview()
print(preview_url)
# With schema customization
preview_url = survey.preview(humanize_schema=schema)
With scenarios
When using scenarios, call .humanize() on a Jobs object (not directly on the survey). You must specify a scenario_list_method.
This example shows each respondent a different policy description and asks for their reaction:
from edsl import Survey, QuestionFreeText, QuestionLinearScale, Scenario, ScenarioList
scenarios = ScenarioList([
Scenario({"policy": "Four-day workweek with no change in pay"}),
Scenario({"policy": "Flexible start times between 7am and 11am"}),
Scenario({"policy": "Monthly remote-work stipend of $100"}),
])
q1 = QuestionLinearScale(
question_name="support",
question_text="How much do you support this policy: '{{ scenario.policy }}'?",
question_options=[1, 2, 3, 4, 5],
option_labels={1: "Strongly oppose", 5: "Strongly support"},
)
q2 = QuestionFreeText(
question_name="reasoning",
question_text="What is the main reason for your rating?",
)
survey = Survey([q1, q2])
info = survey.by(scenarios).humanize(
human_survey_name="Workplace Policy Reactions",
scenario_list_method="randomize",
)
Scenario list methods
| Method | Behavior |
|---|
"randomize" | Each respondent gets a random scenario (with replacement) |
"ordered" | Scenarios are assigned sequentially to respondents |
"loop" | Survey is expanded — every question is repeated for every scenario |
"single_scenario" | Exactly one scenario is used for all respondents (list must have length 1) |
Rules:
- If you attach scenarios, you must specify
scenario_list_method.
- If you specify a method, you must attach scenarios.
- Agents and models are not supported with humanize — the survey goes to real humans.
With agent lists (for email notifications)
Attach an AgentList via .by() to associate respondents with email addresses. Pass a DeliveryMap to tell Coop which agent trait holds the email address.
from edsl import Survey, Agent, AgentList
from edsl.coop.coop_humanize_notifications import ChannelConfig, DeliveryMap
agents = AgentList([
Agent(traits={"name": "Jordan", "email": "[email protected]"}),
Agent(traits={"name": "Taylor", "email": "[email protected]"}),
Agent(traits={"name": "Morgan", "email": "[email protected]"}),
])
info = survey.by(agents).humanize(
human_survey_name="Panel Study — Wave 1",
agent_list_description="Recruited panel participants",
delivery_map=DeliveryMap(email=ChannelConfig(col_name="email")),
)
col_name must match the trait key that holds each respondent’s email address. Once deployed, use Survey notifications to send invitations, schedule reminders, and track delivery status.
Retrieving responses
from edsl import Coop
coop = Coop()
results = coop.get_human_survey_responses("your-human-survey-uuid")
results.select("answer.frequency", "answer.satisfaction", "answer.improvement").print()
Checking response count
status = coop.get_human_survey("your-human-survey-uuid")
print(f"Responses received: {status['n_responses']}")
QR code
Generate a QR code for the respondent link using get_human_survey_qr_code(). Requires the qrcode library (pip install "edsl[full]" or pip install "qrcode[pil]").
from edsl import Coop
coop = Coop()
qr = coop.get_human_survey_qr_code("your-human-survey-uuid")
qr.save("qr_code.png") # save to file
Prolific integration
For paid recruitment via Prolific, see the Prolific studies page. The short version:
from edsl import Coop
coop = Coop()
info = survey.humanize(human_survey_name="Workplace Experience Survey")
study = coop.create_prolific_study(
human_survey_uuid=info["uuid"],
name="Workplace Experience Study",
description="A short survey about remote and in-office work preferences. Takes about 3 minutes.",
num_participants=200,
estimated_completion_time_minutes=3,
participant_payment_cents=75,
)
# create_prolific_study leaves the study in DRAFT mode — publish to make it live
coop.publish_prolific_study(human_survey_uuid=info["uuid"])