Skip to main content
Agents can be created individually or as a list, and updated after creation. They work with any question type for single questions or full surveys.
AI agents are not real people. Agent responses are generated by language models based on their training data. They reflect statistical patterns in that data, not the actual opinions of any demographic group. Use AI-simulated responses for prototyping, hypothesis generation, and pre-testing — and validate with real human data when your goal is to measure actual attitudes or behaviors.
Agent information is presented to a model in a system prompt; it is delivered together with a user prompt of information about a given question. In the examples below we show how to access these prompts to inspect them before running a survey and in the results that are generated for a survey. Note, however, that certain models do not take system prompts (e.g., OpenAI’s o1). When using a model that does not take a system prompt, agent information should be included in the user prompt.

Constructing an Agent

An Agent is created by passing a dictionary of traits relevant to the questions, using single values or textual narratives. For example:

Simplified constructor with keyword arguments

You can also create agents by passing traits directly as keyword arguments, which provides a more concise syntax:
This is equivalent to the traits dictionary approach but more convenient for simple agent creation.
Note:Note that traits= must be named explicitly in the construction, and the traits must use Python identifiers as keys (e.g., home_state but not home state or home-state).

Agent names

We can optionally give an agent a name when it is constructed:
If a name is not passed when the agent is created, an agent_name field is automatically added to the Results that are generated when a survey is run with the agent. This field is a unique identifier for the agent and can be used to filter or group results by agent. It is not used in the prompts for generating responses. If you want to use a name in the prompts for generating responses, you can pass it as a trait:
We can see how the agent information is presented to a model by inspecting the system prompt that is generated when we use an agent with a question:
Output:
Note that trying to create two agents with the same name or trying to use a key “name” in the traits will raise an error.

Agent lists

Agents can be created collectively and administered a survey together. This is useful for comparing responses for multiple agents. For example, here we create a list of agents as an AgentList with different combinations of traits:
This code will create a list of agents that can then be used in a survey. Example code for running a survey with the agents:
This will generate a Results object that contains a Result for each agent’s responses to the survey question. Learn more about working with results in the Results section.

Generating agents from data

An AgentList can be automatically generated from data stored in many source types, including a list, a dictionary, a CSV, TSV or Excel file, a Pandas dataframe, etc. A general method for this is from_source() which is called on the AgentList class, takes a data source_type (csv, excel, pandas, etc.) and a data source, and returns an AgentList object. Optional parameters allow you to specify special instructions, a codebook for the traits, and a name_field for the agents. For example, if you have agent data stored in a CSV file, you can create an AgentList from it using the from_source() method by specifying source_type=”csv” and the path to the CSV file:
If the data source is a CSV or Excel file, the header row is used as the keys for the traits, and can optionally have a column “name” for the agent names. If a different column name should be used for the agent names, it can be specified with the name_field parameter:
A codebook can also be passed to provide descriptions for the traits. It can be useful for providing context to a model about the traits of an agent. For example, if you have a trait “age” and you want to provide more context about what that means, you could use the codebook to specify that “age” refers to the age of the agent in years:
Special instructions can also be passed to modify the default instructions that are used with agent traits in the system prompt. For example, if you want all agents to answer in German, you could use the instructions parameter to specify that:

From natural language descriptions

You can generate agents from natural language descriptions using the from_vibes() method. This uses an LLM to interpret your descriptions and create appropriate agent traits:
This method is particularly useful when you want to quickly create diverse agents without manually specifying all traits.

From a list

We can create a simple AgentList from a list using the from_list() method, which takes a single trait_name and a list of values for it and returns an agent for each value (each agent has a single trait):
Output:

From a dictionary

We can create a more complex AgentList from a dictionary using the from_dict() method. It takes a dictionary with a key agent_list and a list of dictionaries, each of which must have a traits key with a dictionary of traits and an optional name key for the agent’s name:
Output:

From a CSV file

We can also create an AgentList from a CSV file using the from_csv() method. The CSV file must have a header row of Pythonic keys for the traits, and can optionally have a column “name” for the agent names:
Output:

Dynamic traits function

Agents can also be created with a dynamic_traits_function parameter. This function can be used to generate traits dynamically based on the question being asked or the scenario in which the question is asked.
Note:This method is only available with local inference. It does not work with remote inference.
Example:
When the agent is asked a question about age, the agent will return an age of 10. When asked about hair, the agent will return “brown”. This can be useful for creating agents that can answer questions about different topics without including potentially irrelevant traits in the agent’s traits dictionary. Note that the traits returned by the function are not added to the agent’s traits dictionary.

Agent direct-answering methods

Agents can also be created with a method that can answer a particular question type directly:
Output:
This can be useful for creating agents that can answer questions directly without needing to use a language model.

Giving an agent instructions

In addition to traits, agents can be given detailed instructions on how to answer questions. The instruction parameter can be used to omit or modify the default instructions that are used with agent traits in the system prompt. For example:
Output:
When the agent is assigned to a survey, the special instruction will be added to the prompts for generating responses. We can create a Job object to inspect the prompts (user and system) that will be used to generate responses:
Output: Learn more about how to use instructions in the Prompts section.

Controlling the presentation of the persona

The traits_presentation_template parameter can be used to create a narrative persona for an agent. This is a template string that can be rendered with the agent’s traits as variables. For example:
Output:
Note that the trait keys must be valid Python identifiers (e.g., home_state but not home state or home-state). This can be handled by using a dictionary with string keys and values, for example:
Output:
We can also use the traits_presentation_template together with an instruction and inspect the prompts:
Output:
Note:Note that it can be helpful to include traits mentioned in the persona as independent keys and values in order to analyze survey results by those dimensions individually. For example, we may want the narrative to include a sentence about the agent’s age, but also be able to readily analyze or filter results by age.
The following code will include the agent’s age as a column of a table with any other selected components (e.g., agent name and all the answers):
Note:Note that the prefix “agent” can also be dropped. The following code is equivalent:
We can filter the results by an agent’s traits:
We can also call the filter() method on an agent list to filter agents by their traits:

Using agent traits in prompts

The traits of an agent can be used in the prompts of questions. For example:
Output: Learn more about user and system prompts in the Prompts section.

Accessing agent traits

The traits of an agent can be accessed directly:
Output:
The traits of an agent can also be accessed as attributes of the agent:
Output:

Simulating agent responses

When a survey is run, agents can be assigned to it using the by method, which can be chained with other components like scenarios and models:
This will generate a Results object that contains a Result for each agent’s responses to the survey questions. We can select and inspect components of the results, such as the agent’s traits and their answers:
Output: If multiple agents will be used with a survey, they are passed as a list in the same by call:
Output: If scenarios and/or models are also specified for a survey, each component type is added in a separate by call that can be chained in any order with the run method appended last:
Learn more about Scenarios, Language Models and Results.

Updating agents

Agents can be updated after they are created.

Changing a trait

Here we create an agent and then change one of its traits:
Output:

Adding a trait

We can also add a new trait to an agent:
Output:

Removing a trait

We can remove a trait from an agent:
Output:

Using survey responses as new agent traits

After running a survey, we can use the responses to create new traits for an agent:
Output:
Note:Note that in the example above we simply replaced the original agent by selecting the first agent from the agent list that we created. This can be useful for creating agents that evolve over time based on their experiences or responses to surveys.
Here we use the same method to update multiple agents at once:
Output:

Creating AgentList from Results

The AgentList.from_results() method allows you to create an AgentList directly from a Results object. This is useful when you want to create agents based on survey responses, including their original traits and their answers to questions. By default, this method includes all answer columns as traits for the new agents:
This is particularly useful when you want to: - Create agents with only certain response patterns - Filter out irrelevant or sensitive question responses - Create more focused agent profiles based on specific survey questions - Reduce the number of traits when only certain responses are needed
Note:Note that the question_names parameter affects both answer.* columns (as traits) and prompt.* columns (as codebook). Agent traits (from agent.* columns) are always included.

Agent class

class edsl.agents.Agent(traits: dict | None = None, name: str | None = None, codebook: dict | None = None, instruction: str | None = None, trait_categories: dict[str, list[str]] | None = None, traits_presentation_template: str | None = None, dynamic_traits_function: Callable | None = None, dynamic_traits_function_source_code: str | None = None, dynamic_traits_function_name: str | None = None, answer_question_directly_source_code: str | None = None, answer_question_directly_function_name: str | None = None) [source]

Bases: Base A class representing an AI agent with customizable traits that can answer questions. An Agent in EDSL represents an entity with specific characteristics (traits) that can answer questions through various mechanisms. Agents can use language models to generate responses based on their traits, directly answer questions through custom functions, or dynamically adjust their traits based on the questions being asked. Key capabilities: - Store and manage agent characteristics (traits) - Provide instructions on how the agent should answer - Support for custom codebooks to provide human-readable trait descriptions - Integration with multiple question types and language models - Combine agents to create more complex personas - Customize agent behavior through direct answering methods Agents are used in conjunction with Questions, Scenarios, and Surveys to create structured interactions with language models.

init(traits: dict | None = None, name: str | None = None, codebook: dict | None = None, instruction: str | None = None, trait_categories: dict[str, list[str]] | None = None, traits_presentation_template: str | None = None, dynamic_traits_function: Callable | None = None, dynamic_traits_function_source_code: str | None = None, dynamic_traits_function_name: str | None = None, answer_question_directly_source_code: str | None = None, answer_question_directly_function_name: str | None = None) [source]

Initialize a new Agent instance with specified traits and capabilities.

Args:

traits: Dictionary of agent characteristics (e.g., {“age”: 30, “occupation”: “doctor”}) name: Optional name identifier for the agent codebook: Dictionary mapping trait keys to human-readable descriptions for prompts. This provides more descriptive labels for traits when rendering prompts. For example, {‘age’: ‘Age in years’} would display “Age in years: 30” instead of “age: 30”. instruction: Directive for how the agent should answer questions traits_presentation_template: Jinja2 template for formatting traits in prompts dynamic_traits_function: Function that can modify traits based on questions dynamic_traits_function_source_code: Source code string for the dynamic traits function dynamic_traits_function_name: Name of the dynamic traits function answer_question_directly_source_code: Source code for direct question answering method answer_question_directly_function_name: Name of the direct answering function The Agent class brings together several key concepts:

Traits

Traits are key-value pairs that define an agent’s characteristics. These are used to construct a prompt that guides the language model on how to respond. Example: >>> a = Agent(traits={“age”: 10, “hair”: “brown”, “height”: 5.5}) >>> a.traits {‘age’: 10, ‘hair’: ‘brown’, ‘height’: 5.5}

Traits Presentation

The traits_presentation_template controls how traits are formatted in prompts. It uses Jinja2 templating to insert trait values. Example: >>> a = Agent(traits={“age”: 10}, traits_presentation_template=”I am a {\} year old.”) \>\>\> repr(a.agent_persona) ‘Prompt(text=”””I am a \{{age}} year old.”””)’

Codebooks

Codebooks provide human-readable descriptions for traits in prompts. Example:

Instructions

Instructions guide how the agent should answer questions. If not provided, a default instruction is used.
For details on how these components are used to construct prompts, see edsl.agents.Invigilator.InvigilatorBase.

add(other_agent: A | None = None, *, conflict_strategy: str = ‘numeric’) → A [source]

Combine self with other_agent and return a new Agent.

Parameters

other_agent: The second agent to merge with self. If None, self is returned unchanged. conflict_strategy: How to handle overlapping trait names.
  • "numeric" (default) – rename conflicting traits coming from other_agent by appending an incrementing suffix (_1, _2 …). This is identical to the behaviour of the + operator before this refactor.
  • "error" – raise edsl.agents.exceptions.AgentCombinationError.
  • "repeated_observation" – if both agents have the same trait and the codebook entry for that trait is identical (or missing in both), merge the two values into a list [old, new]. If the codebook entries differ, an edsl.agents.exceptions.AgentCombinationError is raised.

Returns

Agent: A new agent containing the merged traits / codebooks.

add_canned_response(question_name, response) [source]

Add a canned response to the agent.

add_category(category_name: str, trait_keys: list[str] | None = None) → None [source]

Add a category to the agent

add_direct_question_answering_method(method: DirectAnswerMethod, validate_response: bool = False, translate_response: bool = False) → None [source]

Add a method to the agent that can answer a particular question type. See: /en/latest/agents#agent-direct-answering-methods

Args:

method: A method that can answer a question directly validate_response: Whether to validate the response translate_response: Whether to translate the response Raises: AgentDirectAnswerFunctionError: If the method signature is invalid

Example:

add_trait(trait_name_or_dict: str | dict[str, Any], value: Any | None = None) → Agent [source]

Add a trait to an agent and return a new agent.

Args:

trait_name_or_dict: Either a trait name string or a dictionary of traits value: The trait value if trait_name_or_dict is a string

Returns:

A new Agent instance with the added trait(s)

Raises:

AgentErrors: If both a dictionary and a value are provided

Example:

property agent_persona*: Prompt* [source]

Get the agent’s persona template as a Prompt object. This property provides access to the template that formats the agent’s traits for presentation in prompts. The template is wrapped in a Prompt object that supports rendering with variable substitution. Returns: Prompt: A prompt object containing the traits presentation template

answer_question(*, question: QuestionBase, cache: Cache, scenario: ‘Scenario’ | None = None, survey: ‘Survey’ | None = None, model: ‘LanguageModel’ | None = None, debug: bool = False, memory_plan: MemoryPlan | None = None, current_answers: dict | None = None, iteration: int = 0, key_lookup: ‘KeyLookup’ | None = None) → AgentResponseDict [source]

Answer a posed question asynchronously.
Args:
question: The question to answer cache: The cache to use for storing responses scenario: The scenario in which the question is asked survey: The survey context model: The language model to use debug: Whether to run in debug mode memory_plan: The memory plan to use current_answers: The current answers iteration: The iteration number key_lookup: The key lookup for API credentials
Returns:
An AgentResponseDict containing the answer
Example:
Note:
This is a function where an agent returns an answer to a particular question. However, there are several different ways an agent can answer a question, so the actual functionality is delegated to an InvigilatorBase object.

answer_question_directly_function_name = ” [source]

async async_answer_question(*, question: QuestionBase, cache: Cache, scenario: ‘Scenario’ | None = None, survey: ‘Survey’ | None = None, model: ‘LanguageModel’ | None = None, debug: bool = False, memory_plan: MemoryPlan | None = None, current_answers: dict | None = None, iteration: int = 0, key_lookup: ‘KeyLookup’ | None = None) → AgentResponseDict [source]

Answer a posed question asynchronously.
Args:
question: The question to answer cache: The cache to use for storing responses scenario: The scenario in which the question is asked survey: The survey context model: The language model to use debug: Whether to run in debug mode memory_plan: The memory plan to use current_answers: The current answers iteration: The iteration number key_lookup: The key lookup for API credentials
Returns:
An AgentResponseDict containing the answer
Example:
Note:
This is a function where an agent returns an answer to a particular question. However, there are several different ways an agent can answer a question, so the actual functionality is delegated to an InvigilatorBase object.

chat() [source]

code() → str [source]

Return the code for the agent.
Returns:
Python code string to recreate this agent
Example:

copy() → Agent [source]

Create a deep copy of this agent using serialization/deserialization. This method uses to_dict/from_dict to create a completely independent copy of the agent, including all its traits, codebook, instructions, and special functions like dynamic traits and direct answering methods.
Returns:
Agent: A new agent instance that is functionally identical to this one
Examples:
Copy preserves direct answering methods:

create_invigilator(*, question: QuestionBase, cache: Cache, survey: ‘Survey’ | None = None, scenario: ‘Scenario’ | None = None, model: ‘LanguageModel’ | None = None, memory_plan: ‘MemoryPlan’ | None = None, current_answers: dict | None = None, iteration: int = 1, raise_validation_errors: bool = True, key_lookup: ‘KeyLookup’ | None = None) → InvigilatorBase [source]

Create an Invigilator. An invigilator is an object that is responsible for administering a question to an agent. There are several different types of invigilators, depending on the type of question and the agent. For example, there are invigilators for functional questions, for direct questions, and for LLM questions.
Args:
question: The question to be asked cache: The cache for storing responses survey: The survey context scenario: The scenario context model: The language model to use memory_plan: The memory plan to use current_answers: The current answers iteration: The iteration number raise_validation_errors: Whether to raise validation errors key_lookup: The key lookup for API credentials
Returns:
An InvigilatorBase instance for handling the question
Example:
Note:
An invigilator is an object that is responsible for administering a question to an agent and recording the responses.

default_instruction = ‘You are answering questions as if you were a human. Do not break character.’ [source]

drop(**field_names: str | List[str]*) → Agent [source]

Drop field(s) from the agent.
Args:
*field_names: The name(s) of the field(s) to drop. Can be:
  • Single field name: drop(“age”)
  • Multiple field names: drop(“age”, “height”)
  • List of field names: drop([“age”, “height”])
Examples:
Drop a single trait from the agent:
Drop multiple traits using separate arguments:
Drop multiple traits using a list:
Drop an agent field like name:
Error when trying to drop a non-existent field:

drop_trait_if(bad_value: Any) → Agent [source]

Drop traits that have a specific bad value.
Args:
bad_value: The value to remove from traits
Returns:
A new Agent instance with the bad value traits removed
Example:

duplicate() → Agent [source]

Create a deep copy of this agent with all its traits and capabilities. This method creates a completely independent copy of the agent, including all its traits, codebook, instructions, and special functions like dynamic traits and direct answering methods.
Returns:
Agent: A new agent instance that is functionally identical to this one
Examples:
Create a duplicate agent and verify it’s equal but not the same object:
Duplicating preserves direct answering methods:
Duplicating preserves custom instructions:

property dynamic_traits_function*: Callable | None* [source]

The dynamic traits function if one exists. This property provides backward compatibility for the old attribute access pattern.
Returns:
The dynamic traits function or None
Examples:

property dynamic_traits_function_name*: str* [source]

The name of the dynamic traits function. This property provides backward compatibility for the old attribute access pattern.
Returns:
The function name or empty string if no function
Examples:

classmethod example(randomize: bool = False) → Agent [source]

Return an example Agent instance.
Args:
randomize: If True, adds a random string to the value of an example key
Returns:
An example Agent instance
Example:

classmethod from_dict(agent_dict: dict[str, dict | bool | str]) → Agent [source]

Deserialize from a dictionary.
Args:
agent_dict: Dictionary containing agent data
Returns:
An Agent instance created from the dictionary
Example:

classmethod from_result(result: Result, name: str | None = None) → Agent [source]

Create an Agent instance from a Result object. The agent’s traits will correspond to the questions asked during the interview (the keys of result.answer) with their respective answers as the values. A simple, readable traits_presentation_template is automatically generated so that rendering the agent will look like:
Args:
result: The Result instance from which to build the agent name: Optional explicit name for the new agent. If omitted, we attempt
to reuse result.agent.name if it exists
Returns:
A new Agent instance created from the result
Raises:
TypeError: If result is not a Result object
Example:

property has_dynamic_traits_function*: bool* [source]

Whether the agent has a dynamic traits function. This property provides backward compatibility for the old attribute access pattern.
Returns:
True if the agent has a dynamic traits function, False otherwise
Examples:

instruction [source]

ABC for something.

property invigilator [source]

Lazily initialize the invigilator to avoid importing language_models during Survey import

keep(**field_names: str | List[str]*) → Agent [source]

Keep only the specified fields from the agent.
Args:
*field_names: The name(s) of the field(s) to keep. Can be:
  • Single field name: keep(“age”)
  • Multiple field names: keep(“age”, “height”)
  • List of field names: keep([“age”, “height”])
Examples:
Keep a single trait:
Keep multiple traits using separate arguments:
Keep multiple traits using a list:
Keep agent fields and traits:
Error when trying to keep a non-existent field:

name [source]

Valid agent name descriptor.

old_keep(*traits: str) → Agent [source]

Legacy trait selection method (renamed from select). Note: This method has data integrity issues and is kept for backward compatibility. Use select() or keep() instead, which provide better data consistency.
Args:
*traits: The trait names to select
Returns:
A new Agent instance with only the selected traits
Example:

prompt() → Prompt [source]

Generate a formatted prompt containing the agent’s traits. This method renders the agent’s traits presentation template with the agent’s traits and codebook, creating a formatted prompt that can be used in language model requests. The method is dynamic and responsive to changes in the agent’s state:
  1. If a custom template was explicitly set during initialization, it will be used
  2. If using the default template and the codebook has been updated since initialization, this method will recreate the template to reflect the current codebook values
  3. The template is rendered with access to all trait values, the complete traits dictionary, and the codebook
The template rendering makes the following variables available: - All individual trait keys (e.g., {{ age }}, {{ occupation }}) - The full traits dictionary as {{ traits }} - The codebook as {{ codebook }}
Returns:
Prompt: A Prompt object containing the rendered template
Raises:
QuestionScenarioRenderError: If any template variables remain undefined
Examples:
Basic trait rendering without a codebook:
Trait rendering with a codebook (more readable format):
Adding a codebook after initialization updates the rendering:
Custom templates can reference any trait directly:

remove_direct_question_answering_method() → None [source]

Remove the direct question answering method.
Example:

remove_trait(trait: str) → Agent [source]

Remove a trait from the agent.
Args:
trait: The name of the trait to remove
Returns:
A new Agent instance without the specified trait
Example:

rename(old_name_or_dict: str | dict[str, str], new_name: str | None = None) → Agent [source]

Rename a trait.
Args:
old_name_or_dict: The old name of the trait or a dictionary of old names and new names new_name: The new name of the trait (required if old_name_or_dict is a string)
Returns:
A new Agent instance with renamed traits
Raises:
AgentErrors: If invalid arguments are provided
Example:

search_traits(search_string: str) → RankableItems [source]

Search the agent’s traits for a string. This method delegates to the traits manager to search through trait descriptions and return ranked matches based on similarity.
Args:
search_string: The string to search for in trait descriptions
Returns:
A ScenarioList containing ranked trait matches
Examples:

select(*traits: str) → Agent [source]

Select agents with only the referenced traits. This method now uses the robust keep() implementation for better data integrity and consistent handling of codebooks and trait_categories.
Args:
*traits: The trait names to select
Returns:
A new Agent instance with only the selected traits
Example:

table() → Dataset [source]

Create a tabular representation of the agent’s traits. This method delegates to the table manager to create a structured Dataset containing trait information.
Returns:
A Dataset containing trait information
Example:

to(target: ‘QuestionBase’ | ‘Jobs’ | ‘Survey’) → Jobs [source]

Send the agent to a question, job, or survey.
Args:
target: The question, job, or survey to send the agent to
Returns:
A Jobs object containing the agent and target
Example:

to_dict(add_edsl_version: bool = True, full_dict: bool = False) → dict[str, dict | bool | str] [source]

Serialize to a dictionary with EDSL info.
Args:
add_edsl_version: Whether to include EDSL version information full_dict: Whether to include all attributes even if they have default values
Returns:
A dictionary representation of the agent
Example:

property traits*: dict[str, Any]* [source]

Get the agent’s traits, potentially using dynamic generation. This property provides access to the agent’s traits, either from the stored traits dictionary or by calling a dynamic traits function if one is defined. If a dynamic traits function is used, it may take the current question as a parameter to generate context-aware traits.
Returns:
dict: Dictionary of agent traits (key-value pairs)
Examples:

property traits_presentation_template [source]

Get the traits presentation template.

translate_traits(values_codebook: dict[str, dict[Any, Any]]) → Agent [source]

Translate traits to a new codebook.
Args:
values_codebook: Dictionary mapping trait names to value translation dictionaries
Returns:
A new Agent instance with translated trait values
Example:

with_categories(*categories: str) → Agent [source]

Return a new agent with the specified categories

AgentList class

class edsl.agents.AgentList(data: list[Agent] | None = None, codebook: dict[str, str] | None = None) [source]

Bases: UserList, Base, AgentListOperationsMixin A list of Agents with additional functionality for manipulation and analysis. The AgentList class extends Python’s UserList to provide a container for Agent objects with methods for filtering, transforming, and analyzing collections of agents.

init(data: list[Agent] | None = None, codebook: dict[str, str] | None = None) [source]

Initialize a new AgentList.
Args:
data: A list of Agent objects. If None, creates an empty AgentList. codebook: Optional dictionary mapping trait names to descriptions. If provided, will be applied to all agents in the list.

add_instructions(instructions: str) → AgentList [source]

Apply instructions to all agents in the list. This method provides a more intuitive name for setting instructions on all agents, avoiding the need to iterate manually.
Args:
instructions: The instructions to apply to all agents.
Returns:
AgentList: Returns self for method chaining.
Examples:

add_trait(trait: str, values: List[Any]) → AgentList [source]

Adds a new trait to every agent, with values taken from values.
Parameters:
  • trait – The name of the trait.
  • values – The valeues(s) of the trait. If a single value is passed, it is used for all agents.

property all_traits*: list[str]* [source]

Return all traits in the AgentList. >>> from edsl import Agent >>> agent_1 = Agent(traits = {‘age’: 22}) >>> agent_2 = Agent(traits = {‘hair’: ‘brown’}) >>> al = AgentList([agent_1, agent_2]) >>> al.all_traits [‘age’, ‘hair’]

at(index: int) → Agent [source]

Get the agent at the specified index position.

chart() [source]

Create a chart from the results.

clipboard_data() → str [source]

Return TSV representation of this object for clipboard operations. This method is called by the clipboard() method in the base class to provide a custom format for copying objects to the system clipboard.
Returns:
str: Tab-separated values representation of the object

code(string=True) → str | list[str] [source]

Return code to construct an AgentList.

property codebook*: dict[str, str]* [source]

Return the codebook for the AgentList.

collapse(warn_about_none_name: bool = True) → AgentList [source]

All agents with the same name have their traits combined.

drop(**field_names: str | List[str]*) → AgentList [source]

Drop field(s) from all agents in the AgentList.
Args:
*field_names: The name(s) of the field(s) to drop. Can be:
  • Single field name: drop(“age”)
  • Multiple field names: drop(“age”, “height”)
  • List of field names: drop([“age”, “height”])
Returns:
AgentList: A new AgentList with the specified fields dropped from all agents.
Examples:
Drop a single trait from all agents:
Drop multiple traits using separate arguments:
Drop multiple traits using a list:

duplicate() → AgentList [source]

Create a deep copy of the AgentList.
Returns:
AgentList: A new AgentList containing copies of all agents.
Examples:

edit() [source]

classmethod example(randomize: bool = False, codebook: dict[str, str] | None = None) → AgentList [source]

Returns an example AgentList instance.
Parameters:
  • randomize – If True, uses Agent’s randomize method.
  • codebook – Optional dictionary mapping trait names to descriptions.

filter(expression: str) → AgentList [source]

Filter agents based on a boolean expression.
Args:
expression: A string containing a boolean expression to evaluate against each agent’s traits.
Returns:
AgentList: A new AgentList containing only agents that satisfy the expression.
Examples:

first() → Agent [source]

Get the first agent in the list.

flatten(field: str, keep_original: bool = False) → Dataset [source]

Expand a field containing dictionaries into separate fields. This method takes a field that contains a list of dictionaries and expands it into multiple fields, one for each key in the dictionaries. This is useful when working with nested data structures or results from extraction operations.
Parameters:
field: The field containing dictionaries to flatten keep_original: Whether to retain the original field in the result
Returns:
A new Dataset with the dictionary keys expanded into separate fields
Notes:
  • Each key in the dictionaries becomes a new field with name pattern “.
  • All dictionaries in the field must have compatible structures
  • If a dictionary is missing a key, the corresponding value will be None
  • Non-dictionary values in the field will cause a warning
Examples:

classmethod from_csv(file_path: str, name_field: str | None = None, codebook: dict[str, str] | None = None, instructions: str | None = None) [source]

Load AgentList from a CSV file. Deprecated since version Use: AgentList.from_source(‘csv’, …) instead.
Parameters:
  • file_path – The path to the CSV file.
  • name_field – The name of the field to use as the agent name.
  • codebook – Optional dictionary mapping trait names to descriptions.
  • instructions – Optional instructions to apply to all created agents.

classmethod from_dict(data: dict) → AgentList [source]

Deserialize the dictionary back to an AgentList object.
Parameters:
data: A dictionary representing an AgentList.

classmethod from_list(trait_name: str, values: List[Any], codebook: dict[str, str] | None = None) → AgentList [source]

Create an AgentList from a list of values.
Parameters:
  • trait_name – The name of the trait.
  • values – A list of values.
  • codebook – Optional dictionary mapping trait names to descriptions.

classmethod from_results(results: Results, question_names: List[str] | None = None) → AgentList [source]

Create an AgentList from a Results object.
Args:
results: The Results object to convert question_names: Optional list of question names to include. If None, all questions are included. Affects both answer.* columns (as traits) and prompt.* columns (as codebook). Agent traits are always included.
Returns:
AgentList: A new AgentList created from the Results

classmethod from_scenario_list(scenario_list: ScenarioList) → AgentList [source]

Create an AgentList from a ScenarioList. This method supports special fields that map to Agent parameters: - “name”: Will be used as the agent’s name - “agent_parameters”: A dictionary containing:
  • “instruction”: The agent’s instruction text
  • “name”: The agent’s name (overrides the “name” field if present)
Examples:

classmethod from_source(source_type: str, *args, instructions: str | None = None, codebook: dict[str, str] | None = None, name_field: str | None = None, **kwargs) → AgentList [source]

Create an AgentList from a specified source type. This method serves as the main entry point for creating AgentList objects, providing a unified interface for various data sources.
Args:
source_type: The type of source to create an AgentList from. Valid values include: ‘csv’, ‘tsv’, ‘excel’, ‘pandas’, etc. *args: Positional arguments to pass to the source-specific method. instructions: Optional instructions to apply to all created agents. codebook: Optional dictionary mapping trait names to descriptions, or a path to a CSV file. If a CSV file is provided, it should have 2 columns: original keys and descriptions. Keys will be automatically converted to pythonic names. name_field: The name of the field to use as the agent name (for CSV/Excel sources). **kwargs: Additional keyword arguments to pass to the source-specific method.
Returns:
An AgentList object created from the specified source.
Examples:

static get_codebook(file_path: str) → dict [source]

Returns a codebook dictionary mapping CSV column names to None. Reads the header row of a CSV file and creates a codebook with field names as keys and None as values. Args: file_path: Path to the CSV file to read. Returns: A dictionary with CSV column names as keys and None as values. Raises: FileNotFoundError: If the specified file path does not exist. csv.Error: If there is an error reading the CSV file.

get_tabular_data(remove_prefix: bool = False, pretty_labels: dict | None = None) → Tuple[List[str], List[List]] [source]

Internal method to get tabular data in a standard format. Args: remove_prefix: Whether to remove the prefix from column names pretty_labels: Dictionary mapping original column names to pretty labels Returns: Tuple containing (header_row, data_rows)

ggplot2(ggplot_code: str, shape: str = ‘wide’, sql: str | None = None, remove_prefix: bool = True, debug: bool = False, height: float = 4, width: float = 6, factor_orders: dict | None = None) [source]

Create visualizations using R’s ggplot2 library. This method provides a bridge to R’s powerful ggplot2 visualization library, allowing you to create sophisticated plots directly from EDSL data structures.
Parameters:
ggplot_code: R code string containing ggplot2 commands shape: Data shape to use (“wide” or “long”) sql: Optional SQL query to transform data before visualization remove_prefix: Whether to remove prefixes (like “answer.”) from column names debug: Whether to display debugging information height: Plot height in inches width: Plot width in inches factor_orders: Dictionary mapping factor variables to their desired order
Returns:
A plot object that renders in Jupyter notebooks
Notes:
  • Requires R and the ggplot2 package to be installed
  • Data is automatically converted to a format suitable for ggplot2
  • The ggplot2 code should reference column names as they appear after any transformations from the shape and remove_prefix parameters
Examples:

give_names(*trait_keys: str, remove_traits: bool = True, separator: str = ’,’, force_name: bool = False) → None [source]

Give names to agents based on the values of the specified traits.

join(other: AgentList, join_type: str = ‘inner’) → AgentList [source]

Join this AgentList with another AgentList.
Args:
other: The other AgentList to join with join_type: The type of join to perform (“inner”, “left”, or “right”)
Returns:
AgentList: A new AgentList containing the joined results
Examples:

classmethod join_multiple(**agent_lists: AgentList*, join_type: str = ‘inner’) → AgentList [source]

Join multiple AgentLists together.
Args:
*agent_lists: Variable number of AgentList objects to join join_type: The type of join to perform (“inner”, “left”, or “right”)
Returns:
AgentList: A new AgentList containing the joined results
Raises:
ValueError: If fewer than 2 AgentLists are provided
Examples:

keep(**field_names: str | List[str]*) → AgentList [source]

Keep only the specified fields from all agents in the AgentList.
Args:
*field_names: The name(s) of the field(s) to keep. Can be:
  • Single field name: keep(“age”)
  • Multiple field names: keep(“age”, “height”)
  • List of field names: keep([“age”, “height”])
Returns:
AgentList: A new AgentList with only the specified fields kept for all agents.
Examples:
Keep a single trait for all agents:
Keep multiple traits using separate arguments:
Keep multiple traits using a list:
Keep agent fields and traits:

last() → Agent [source]

Get the last agent in the list.

make_tabular(remove_prefix: bool, pretty_labels: dict | None = None) → tuple[list, List[list]] [source]

Turn the results into a tabular format.
Parameters:
remove_prefix – Whether to remove the prefix from the column names.

classmethod manage() [source]

property names*: List[str]* [source]

Returns the names of the agents in the AgentList.

num_observations() [source]

Return the number of observations in the dataset.
Print the results in a long format. >>> from edsl.results import Results >>> r = Results.example() >>> r.select(‘how_feeling’).print_long() answer.how_feeling: OK answer.how_feeling: Great answer.how_feeling: Terrible answer.how_feeling: OK

relevant_columns(data_type: str | None = None, remove_prefix: bool = False) → list [source]

Return the set of keys that are present in the dataset. Parameters:
  • data_type – The data type to filter by.
  • remove_prefix – Whether to remove the prefix from the column names.

remove_prefix() [source]

Returns a new Dataset with the prefix removed from all column names. The prefix is defined as everything before the first dot (.) in the column name. If removing prefixes would result in duplicate column names, an exception is raised.
Returns:
Dataset: A new Dataset with prefixes removed from column names
Raises:
ValueError: If removing prefixes would result in duplicate column names
Examples:
# Testing remove_prefix with duplicate column names raises DatasetValueError - tested in unit tests

remove_trait(trait: str) [source]

Remove traits from the AgentList.
Parameters:
traits – The traits to remove.

rename(old_name: str, new_name: str) → AgentList [source]

Rename a trait across all agents in the list.
Args:
old_name: The current name of the trait. new_name: The new name to assign to the trait.
Returns:
AgentList: A new AgentList with the renamed trait.
Examples:

report(*fields: str | None, top_n: int | None = None, header_fields: List[str] | None = None, divider: bool = True, return_string: bool = False, format: str = ‘markdown’, filename: str | None = None) → str | Document | None [source]

Generates a report of the results by iterating through rows.
Args:
*fields: The fields to include in the report. If none provided, all fields are used. top_n: Optional limit on the number of observations to include. header_fields: Optional list of fields to include in the main header instead of as sections. divider: If True, adds a horizontal rule between observations (markdown only). return_string: If True, returns the markdown string. If False (default in notebooks), only displays the markdown without returning. format: Output format - either “markdown” or “docx”. filename: If provided and format is “docx”, saves the document to this file.
Returns:
Depending on format and return_string: - For markdown: A string if return_string is True, otherwise None (displays in notebook) - For docx: A docx.Document object, or None if filename is provided (saves to file) Examples:

report_from_template(template: str, *fields: str | None, top_n: int | None = None, remove_prefix: bool = True, return_string: bool = False, format: str = ‘text’, filename: str | None = None, separator: str = ‘nn’, observation_title_template: str | None = None, explode: bool = False, filestore: bool = False) → str | Document | List | FileStore | None [source]

Generates a report using a Jinja2 template for each row in the dataset. This method renders a user-provided Jinja2 template for each observation in the dataset, with template variables populated from the row data. This allows for completely customized report formatting using pandoc for advanced output formats.
Args:
template: Jinja2 template string to render for each row *fields: The fields to include in template context. If none provided, all fields are used. top_n: Optional limit on the number of observations to include. remove_prefix: Whether to remove type prefixes (e.g., “answer.”) from field names in template context. return_string: If True, returns the rendered content. If False (default in notebooks), only displays the content without returning. format: Output format - one of “text”, “html”, “pdf”, or “docx”. Formats other than “text” require pandoc. filename: If provided, saves the rendered content to this file. For exploded output, this becomes a template (e.g., “report_”). separator: String to use between rendered templates for each row (ignored when explode=True). observation_title_template: Optional Jinja2 template for observation titles. Defaults to “Observation ” where index is 1-based. Template has access to all row data plus ‘index’ and ‘index0’ variables. explode: If True, creates separate files for each observation instead of one combined file. filestore: If True, wraps the generated file(s) in FileStore object(s). If no filename is provided, creates temporary files. For exploded output, returns a list of FileStore objects.
Returns:
Depending on explode, format, return_string, and filestore: - For text format: String content or None (if displayed in notebook) - For html format: HTML string content or None (if displayed in notebook) - For docx format: Document object or None (if saved to file) - For pdf format: PDF bytes or None (if saved to file) - If explode=True: List of created filenames (when filename provided) or list of documents/content - If filestore=True: FileStore object(s) containing the generated file(s)
Notes:
  • Pandoc is required for HTML, PDF, and DOCX output formats
  • Templates are treated as Markdown for all non-text formats
  • PDF output uses XeLaTeX engine through pandoc
  • HTML output includes standalone document structure
Examples:

sample(n: int, seed: str | None = None) → AgentList [source]

Return a random sample of agents. Args: n: The number of agents to sample. seed: Optional seed for the random number generator to ensure reproducibility. Returns: AgentList: A new AgentList containing the sampled agents.

select(*traits) → AgentList [source]

Create a new AgentList with only the specified traits. Args: *traits: Variable number of trait names to keep. Returns: AgentList: A new AgentList containing agents with only the selected traits. Examples:

set_codebook(codebook: dict[str, str]) → AgentList [source]

Set the codebook for the AgentList.
Parameters:
codebook – The codebook.

set_dynamic_traits(function: Callable) → None [source]

Set the dynamic traits for all agents in the list.
Args:
function: The function to set.

set_dynamic_traits_from_question_map(q_to_traits: dict[str, list[str]]) → AgentList [source]

Configure dynamic traits for each agent from a question→traits mapping (in-place). Each agent will get a dynamic traits function that, when asked a question whose question_name is present in q_to_traits, returns a dict mapping the corresponding trait name(s) to the agent’s original static value(s) for those trait(s). A warning is emitted if the set of mapped trait names does not exactly equal the set of trait keys present in this AgentList.
Args:
q_to_traits: Mapping from question name to list of trait keys, e.g. {"geo": ["hometown"], "cuisine": ["food"]}
Returns:
AgentList: self (modified in-place).
Examples:

set_instruction(instruction: str) → None [source]

Set the instruction for all agents in the list. Args: instruction: The instruction to set.

set_traits_presentation_template(traits_presentation_template: str) → None [source]

Set the traits presentation template for all agents in the list. Args: traits_presentation_template: The traits presentation template to set.

shuffle(seed: str | None = None) → AgentList [source]

Randomly shuffle the agents in place. Args: seed: Optional seed for the random number generator to ensure reproducibility. Returns: AgentList: The shuffled AgentList (self).

sql(query: str, transpose: bool = None, transpose_by: str = None, remove_prefix: bool = True, shape: str = ‘wide’) → Dataset [source]

Execute SQL queries on the dataset. This powerful method allows you to use SQL to query and transform your data, combining the expressiveness of SQL with EDSL’s data structures. It works by creating an in-memory SQLite database from your data and executing the query against it.
Parameters:
query: SQL query string to execute transpose: Whether to transpose the resulting table (rows become columns) transpose_by: Column to use as the new index when transposing remove_prefix: Whether to remove type prefixes (e.g., “answer.”) from column names shape: Data shape to use (“wide” or “long”)
  • “wide”: Default tabular format with columns for each field
  • “long”: Melted format with key-value pairs, useful for certain queries
Returns:
A Dataset object containing the query results
Notes:
  • The data is stored in a table named “self” in the SQLite database
  • In wide format, column names include their type prefix unless remove_prefix=True
  • In long format, the data is melted into columns: row_number, key, value, data_type
  • Complex objects like lists and dictionaries are converted to strings
Examples:

table(*fields, tablefmt: str | None = ‘rich’, pretty_labels: dict | None = None) → Any [source]

tally(*fields: str | None, top_n: int | None = None, output=‘Dataset’) → dict | Dataset [source]

Count frequency distributions of values in specified fields. This method tallies the occurrence of unique values within one or more fields, similar to a GROUP BY and COUNT in SQL. When multiple fields are provided, it performs cross-tabulation across those fields.
Parameters:
*fields: Field names to tally. If none provided, uses all available fields. top_n: Optional limit to return only the top N most frequent values. output: Format for results, either “Dataset” (recommended) or “dict”.
Returns:
By default, returns a Dataset with columns for the field(s) and a ‘count’ column. If output=”dict”, returns a dictionary mapping values to counts.
Notes:
  • For single fields, returns counts of each unique value
  • For multiple fields, returns counts of each unique combination of values
  • Results are sorted in descending order by count
  • Fields can be specified with or without their type prefix
Examples:

to(target: ‘Question’ | ‘Jobs’ | ‘Survey’) → Jobs [source]

to_agent_list(remove_prefix: bool = True) [source]

Convert the results to a list of dictionaries, one per agent.
Parameters:
remove_prefix – Whether to remove the prefix from the column names.

to_csv(filename: str | None = None, remove_prefix: bool = False, pretty_labels: dict | None = None) → FileStore [source]

Export the results to a FileStore instance containing CSV data.

to_dataset(traits_only: bool = True) [source]

Convert the AgentList to a Dataset.
Args:
traits_only: If True, only include agent traits. If False, also include agent parameters like instructions and names.
Returns:
Dataset: A dataset containing the agents’ traits and optionally their parameters.
Examples:

to_dict(sorted=False, add_edsl_version=True, full_dict=False) [source]

Serialize the AgentList to a dictionary.

to_dicts(remove_prefix: bool = True) → list[dict] [source]

Convert the results to a list of dictionaries. Parameters: remove_prefix – Whether to remove the prefix from the column names.

to_docx(filename: str | None = None, remove_prefix: bool = False, pretty_labels: dict | None = None) → FileStore [source]

Export the results to a FileStore instance containing DOCX data. Each row of the dataset will be rendered on its own page, with a 2-column table that lists the keys and associated values for that observation.

to_excel(filename: str | None = None, remove_prefix: bool = False, pretty_labels: dict | None = None, sheet_name: str | None = None) [source]

Export the results to a FileStore instance containing Excel data.

to_jsonl(filename: str | None = None) [source]

Export the results to a FileStore instance containing JSONL data.

to_list(flatten=False, remove_none=False, unzipped=False) → list[list] [source]

Convert the results to a list of lists.
Parameters:
  • flatten – Whether to flatten the list of lists.
  • remove_none – Whether to remove None values from the list.

to_pandas(remove_prefix: bool = False, lists_as_strings=False) [source]

Convert the results to a pandas DataFrame, ensuring that lists remain as lists. Args: remove_prefix: Whether to remove the prefix from the column names. lists_as_strings: Whether to convert lists to strings.
Returns:
A pandas DataFrame.

to_polars(remove_prefix: bool = False, lists_as_strings=False) [source]

Convert the results to a Polars DataFrame.
Args:
remove_prefix: Whether to remove the prefix from the column names. lists_as_strings: Whether to convert lists to strings.
Returns:
A Polars DataFrame.

to_scenario_list(remove_prefix: bool = True) → list[dict] [source]

Convert the results to a list of dictionaries, one per scenario. Parameters: remove_prefix – Whether to remove the prefix from the column names.

to_sqlite(filename: str | None = None, remove_prefix: bool = False, pretty_labels: dict | None = None, table_name: str = ‘results’, if_exists: str = ‘replace’) [source]

Export the results to a SQLite database file.

property trait_keys*: List[str]* [source]

Get the trait keys for the AgentList.

translate_traits(codebook: dict[str, str]) [source]

Translate traits to a new codebook. Parameters: codebook – The new codebook.

tree(node_order: List[str] | None = None) [source]

Convert the results to a Tree. Args: node_order: The order of the nodes. Returns: A Tree object.

unpack_list(field: str, new_names: List[str] | None = None, keep_original: bool = True) → Dataset [source]

Unpack list columns into separate columns with provided names or numeric suffixes. For example, if a dataset contains: [{‘data’: [[1, 2, 3], [4, 5, 6]], ‘other’: [‘x’, ‘y’]}] After d.unpack_list(‘data’), it should become: [{‘other’: [‘x’, ‘y’], ‘data_1’: [1, 4], ‘data_2’: [2, 5], ‘data_3’: [3, 6]}]
Args:
field: The field containing lists to unpack new_names: Optional list of names for the unpacked fields. If None, uses numeric suffixes. keep_original: If True, keeps the original field in the dataset
Returns:
A new Dataset with unpacked columns
Examples:

with_names(*trait_keys: str, remove_traits: bool = True, separator: str = ’,’, force_name: bool = False) → AgentList [source]

Return a new AgentList with names based on the values of the specified traits.
Args:
*trait_keys: The trait keys to use for naming remove_traits: Whether to remove the traits used for naming from the agents separator: The separator to use when joining multiple trait values force_name: Whether to force naming even if agents already have names
Returns:
AgentList: A new AgentList with named agents