Skip to main content

Persona-based agents for AG2 (AutoGen) - enabling distinct character embodiment

Project description

PersonaAgent for AG2: Enabling Distinct Character Embodiment

PyPi MIT license Documentation

Why This Matters

AG2 (AutoGen) agents currently mix role, purpose, and context into a single unstructured system_message, which is fantastic flexibility but does not propose a common pattern for agents to authentically embody distinct personas. PersonaAgent enables agents to adopt rich, well-defined characters through explicit role, goal, and backstory components.

The real power comes from the PersonaBuilder Markdown library pattern: Load expert personas from configuration files, enabling domain experts to define agent behavior while developers handle runtime integration. This separation provides:

  • 🔄 Reusability: Share persona definitions across projects and teams
  • 🛠️ Maintainability: Update agent behavior without touching code
  • 👥 Non-developer friendly: Subject matter experts can edit Markdown files directly
  • 📝 Version control: Track persona evolution and collaborate on definitions
  • ⚡ Separation of concerns: Stable persona definition vs variable runtime config

Perfect for teams where domain experts define the "who" while developers handle the "how".

The Problem

Current AG2 agent creation:

agent = ConversableAgent(
    name="reviewer",
    system_message="You are a senior software engineer with 10 years of experience. Your task is to review code for quality issues, security vulnerabilities, and suggest improvements. Focus on Python best practices and ensure the code follows PEP-8 standards. You should be constructive in your feedback."
)

Issues:

  • 🎭 Weak Persona Embodiment - Agents lack distinct character identity
  • 🔄 Limited Reuse - Changing or sharing personas requires rewriting entire prompts
  • 📚 Maintainability - Difficult to update character aspects
  • 🎯 Inconsistent Behavior - Unstructured prompts lead to character drift

The Solution

PersonaAgent enables authentic character embodiment (inspired by CrewAI's backstory/goal structure):

agent = PersonaAgent(
    name="reviewer",
    role="Senior Software Engineer",
    goal="Review code for quality issues and suggest improvements",
    backstory="You have 10 years of experience in Python development",
    constraints=["Focus on Python best practices", "Follow PEP-8 standards"],
    llm_config={"model": "gpt-4"}
)

Benefits:

  • 🎭 Authentic Personas - Agents embody distinct, consistent characters
  • 🔄 Dynamic Character Updates - Modify and share persona aspects without full rewrites
  • 📚 Better Persona Maintenance - Update character traits independently
  • 🎯 Consistent Behavior - Well-defined personas reduce character drift

Quick Start

Installation

pip install ag2-persona
# or with modern uv:
uv add ag2-persona

📖 Full Documentation - Complete guides, API reference, and examples

Basic Usage

from ag2_persona import PersonaAgent

# Create an agent with a distinct persona
expert = PersonaAgent(
    name="data_analyst",
    role="Data Analysis Expert",
    goal="Analyze the provided dataset and identify key insights",
    backstory="You specialize in statistical analysis and data visualization",
    llm_config={"model": "gpt-4", "temperature": 0.7}
)

# Use like any AG2 agent
response = expert.generate_reply(messages=[{"content": "Analyze this sales data"}])

Team Composition with PersonaBuilder

Build multi-agent teams by loading expert personas from Markdown files. This enables domain experts to define agent behavior while developers handle runtime integration:

from ag2_persona import PersonaBuilder
from autogen import GroupChat, GroupChatManager

# Load domain expert personas from Markdown library (sync version)
lead_scientist = (PersonaBuilder("lead_scientist")
                 .from_markdown("library/research_team_lead.md")
                 .llm_config({"model": "gpt-4", "temperature": 0.7})
                 .build())

data_analyst = (PersonaBuilder("data_analyst")
               .from_markdown("library/senior_data_engineer.md")
               .llm_config({"model": "gpt-4", "temperature": 0.5})
               .build())

# Manual construction when Markdown doesn't exist yet
lab_technician = (PersonaBuilder("lab_tech")
                 .role("Laboratory Technician")
                 .goal("Execute experiments and ensure quality control")
                 .constraints(["Follow safety protocols", "Document all procedures"])
                 .llm_config({"model": "gpt-4", "temperature": 0.3})
                 .build())

# Use in GroupChat - personas are consistent and reusable
groupchat = GroupChat(
    agents=[lead_scientist, data_analyst, lab_technician],
    messages=[],
    max_round=10
)
manager = GroupChatManager(groupchat)

Benefits:

  • Domain experts edit Markdown files, developers handle runtime
  • Personas are shared across projects and teams
  • Updates don't require code changes
  • Version control tracks persona evolution

Async Team Composition

For async applications, use AsyncPersonaBuilder to avoid blocking the event loop:

import asyncio
from ag2_persona import AsyncPersonaBuilder
from autogen import GroupChat, GroupChatManager

async def create_async_team():
    # Load personas asynchronously with true fluent chaining - no blocking I/O
    lead_agent = await (AsyncPersonaBuilder("lead_scientist")
                       .from_markdown("library/research_team_lead.md")
                       .llm_config({"model": "gpt-4", "temperature": 0.7})
                       .build())

    analyst_agent = await (AsyncPersonaBuilder("data_analyst")
                          .from_markdown("library/senior_data_engineer.md")
                          .llm_config({"model": "gpt-4", "temperature": 0.5})
                          .build())

    return GroupChat(agents=[lead_agent, analyst_agent], messages=[], max_round=10)

# Usage in async context
async def main():
    team = await create_async_team()
    # Use team in async AG2 workflows...

# Markdown and async support now included by default

API Reference

PersonaAgent

Extends ConversableAgent with persona-based prompt components.

Constructor

PersonaAgent(
    name: str,
    role: str,
    goal: str,
    backstory: str = "",
    constraints: Optional[List[str]] = None,
    **kwargs  # All standard ConversableAgent parameters
)

Parameters:

  • name (str): Agent identifier
  • role (str): The agent's role or title (e.g., "Code Reviewer", "Data Scientist")
  • goal (str): What the agent should accomplish
  • backstory (str, optional): Background, expertise, or context
  • constraints (List[str], optional): Limitations or rules to follow
  • **kwargs: Any additional ConversableAgent parameters

Methods

update_goal(new_goal: str) -> None

Dynamically update the agent's goal and regenerate the system message.

agent.update_goal("Review only the security aspects of the code")

Properties

  • role (str): The agent's role
  • goal (str): The agent's current goal
  • backstory (str): The agent's backstory
  • constraints (List[str]): The agent's constraints
  • system_message (str): The composed system message (inherited)

PersonaBuilder Methods

PersonaBuilder supports three construction patterns for different use cases:

from ag2_persona import PersonaBuilder

# Option 1 (Recommended): Load expert personas from Markdown library
expert = (PersonaBuilder("bioinformatics_specialist")
          .from_markdown("library/bioinformatics_specialist.md")
          .llm_config({"model": "gpt-4", "temperature": 0.5})
          .build())

# Option 2: Construct from dictionary
persona_config = {
    "role": "Bioinformatics Specialist",
    "goal": "Analyze genomic sequences and identify patterns",
    "backstory": "PhD in computational biology with expertise in sequence analysis",
    "constraints": ["Use validated algorithms", "Ensure reproducibility"]
}

agent = (PersonaBuilder("bioinformatics_specialist")
         .from_dict(persona_config)
         .llm_config({"model": "gpt-4", "temperature": 0.5})
         .build())

# Option 3: Manual construction
agent = (PersonaBuilder("bioinformatics_specialist")
         .role("Bioinformatics Specialist")
         .goal("Analyze genomic sequences and identify patterns")
         .backstory("PhD in computational biology with expertise in sequence analysis")
         .constraints(["Use validated algorithms", "Ensure reproducibility"])
         .llm_config({"model": "gpt-4", "temperature": 0.5})
         .build())

# Async Markdown loading (for async applications)
async def create_async_agent():
    return await (AsyncPersonaBuilder("bioinformatics_specialist")
                 .from_markdown("library/bioinformatics_specialist.md")
                 .llm_config({"model": "gpt-4", "temperature": 0.5})
                 .build())

Markdown and async support included by default.

Migration Guide

From Standard ConversableAgent

Before:

agent = ConversableAgent(
    name="researcher",
    system_message="""You are a marine biology researcher with 8 years
    of experience studying coral reef ecosystems. Analyze oceanographic
    data to identify patterns in coral health. Focus on temperature and
    pH correlations. Always cite relevant scientific literature and
    follow peer review standards.""",
    llm_config=config
)

After:

agent = (PersonaBuilder("researcher")
         .role("Marine Biology Researcher")
         .goal("Analyze oceanographic data to identify coral health patterns")
         .backstory("You have 8 years of experience studying coral reef ecosystems")
         .constraints([
             "Focus on temperature and pH correlations",
             "Always cite relevant scientific literature",
             "Follow peer review standards"
         ])
         .llm_config(config)
         .build())

Compared to CrewAI

CrewAI:

from crewai import Agent

agent = Agent(
    role="Climate Scientist",
    goal="Analyze climate data and predict weather patterns",
    backstory="You are a climate scientist with expertise in atmospheric modeling",
    llm={"model": "gpt-4"}
)

AG2 PersonaAgent:

agent = (PersonaBuilder("climate_scientist")
         .role("Climate Scientist")
         .goal("Analyze climate data and predict weather patterns")
         .backstory("You are a climate scientist with expertise in atmospheric modeling")
         .llm_config({"model": "gpt-4"})
         .build())

Examples

Persona Library

A comprehensive collection of pre-built persona agents across various domains is available in examples/library/. These Markdown files provide ready-to-use personas that you can load with PersonaBuilder:

  • Construction Team: Project managers, architects, engineers for collaborative construction analysis
  • Software Development: Architects, data engineers, product managers for technical decision-making
  • Life Sciences: Pharmaceutical researchers, analysts for scientific research
  • Business Operations: Customer service, logistics, strategic analysis

See examples/README.md for complete documentation.

Multi-Agent Construction Team Example

The examples/construction_team.py demonstrates a complete multi-agent system where:

  • UserProxyAgent acts as human client proxy presenting real construction challenges
  • Three AI specialists collaborate autonomously using GroupChat
  • PersonaBuilder loads agents from Markdown configurations with runtime LLM setup

This example showcases the hybrid conversation pattern: human problems → expert AI collaboration.

# Run the construction team example
cd examples/
python construction_team.py

Frequently Asked Questions

Does this replace ConversableAgent?

No, PersonaAgent extends ConversableAgent. All existing ConversableAgent features work exactly as before, including function calling, human input modes, and group chats.

Can I mix PersonaAgent with regular AG2 agents?

Yes! PersonaAgents are fully compatible with regular ConversableAgents in group chats and conversations. You can gradually adopt PersonaAgent without changing your existing setup.

What if I need custom system message formatting?

Pass additional system_message content via kwargs - it gets appended to the generated persona message:

agent = PersonaAgent(
    name="reviewer",
    role="Code Reviewer",
    goal="Review code quality",
    system_message="Additional custom instructions here",
    llm_config=config
)
What's the best way to load personas from configuration?

Use PersonaBuilder with Markdown files for maximum flexibility:

# Recommended: Markdown library pattern
agent = (PersonaBuilder("expert")
         .from_markdown("library/domain_expert.md")
         .llm_config({"model": "gpt-4", "temperature": 0.7})
         .build())

This separates persona definition (stable, edited by domain experts) from runtime configuration (variable, handled by developers).

How do I contribute improvements?

Submit pull requests that enhance functionality while maintaining backward compatibility. Focus on:

  • New persona library entries
  • Additional PersonaBuilder methods
  • Documentation improvements
  • Bug fixes and performance enhancements

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ag2_persona-0.1.3.tar.gz (55.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ag2_persona-0.1.3-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file ag2_persona-0.1.3.tar.gz.

File metadata

  • Download URL: ag2_persona-0.1.3.tar.gz
  • Upload date:
  • Size: 55.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ag2_persona-0.1.3.tar.gz
Algorithm Hash digest
SHA256 d5e5392c6ac82edf101419fc2c9877a34fce93d9abd5671cbc20a9f69a74a574
MD5 e6701202e07a3dc40f89306cbfabcc61
BLAKE2b-256 9b7db95541c89c62cd019167593c157aa2cac9fe9b42c0063aa8e68e43d673eb

See more details on using hashes here.

File details

Details for the file ag2_persona-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: ag2_persona-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 22.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ag2_persona-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 90ae82d8fc8083a12553924a6128ac53470e6b587ecf51c27060b596587eba61
MD5 d79fccf32cef228522e4dcc4d29312db
BLAKE2b-256 567ce7feb2d38f4ec49c56c7df8df0a58f67ace6f16ffd7caf42709a6f659e07

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page