Skip to main content

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

1
Create Surveys with desired types of Questions.
2
Humanize the survey to generate a web-hosted version on Expected Parrot with a respondent link and an admin dashboard.
3
Share the respondent link with human participants (or recruit via Prolific).
4
Collect responses back as a standard EDSL Results object.
5
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

ParameterTypeDefaultDescription
human_survey_namestr"New survey"Display name on Coop
survey_descriptionstr | NoneNoneOptional description
survey_aliasstr | NoneNoneURL-friendly alias
survey_visibilitystr"private""private", "public", or "unlisted"
humanize_schemadict | NoneNoneControls question styling and optionality — see Humanize schema
delivery_mapDeliveryMap | NoneNoneMaps delivery channels to agent trait columns; required for email notifications

Return value

survey.humanize() returns a Scenario (dict-like) with these keys:
KeyDescription
uuidHuman survey UUID — needed to fetch responses later
respondent_urlPublic link for respondents
admin_urlAdmin dashboard link
nameSurvey name
n_responsesResponse count (0 at creation)
survey_uuidUUID of the pushed survey object
scenario_list_uuidUUID 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

MethodBehavior
"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"])