Metadata-Version: 2.4
Name: agentsociety2
Version: 2.4.0
Summary: A modern, LLM-native agent simulation platform for social science research
Project-URL: Homepage, https://github.com/tsinghua-fib-lab/agentsociety
Project-URL: Documentation, https://agentsociety2.readthedocs.io/
Project-URL: Repository, https://github.com/tsinghua-fib-lab/agentsociety.git
Project-URL: Issues, https://github.com/tsinghua-fib-lab/agentsociety/issues
Project-URL: Changelog, https://github.com/tsinghua-fib-lab/agentsociety/blob/main/CHANGELOG.md
Author-email: Jun Zhang <zhangjun990222@gmail.com>, Boyuan Sun <sunboyuan0124@gmail.com>, Haoyu Huang <2253940186@qq.com>, Keming Zhang <kemingzhang@bupt.edu.cn>, Yuxin Liu <aph.xin@gmail.com>
Maintainer-email: Jun Zhang <zhangjun990222@gmail.com>, Boyuan Sun <sunboyuan0124@gmail.com>, Haoyu Huang <2253940186@qq.com>, Keming Zhang <kemingzhang@bupt.edu.cn>, Yuxin Liu <aph.xin@gmail.com>
License: Apache-2.0
License-File: LICENSE
Keywords: agents,artificial-intelligence,experiment,llm,multi-agent,reinforcement-learning,simulation,social-science
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: <3.14,>=3.11
Requires-Dist: aiohttp>=3.10.11
Requires-Dist: aiosqlite>=0.20.0
Requires-Dist: black>=25.12.0
Requires-Dist: chromadb>=1.5.5
Requires-Dist: elemental-xenon>=1.1.0
Requires-Dist: faiss-cpu>=1.7.0
Requires-Dist: fastapi>=0.128.0
Requires-Dist: geojson>=3.1.0
Requires-Dist: json-repair>=0.46.2
Requires-Dist: litellm>=1.83.7
Requires-Dist: mcp[cli]>=1.13.1
Requires-Dist: mem0ai>=1.0.5
Requires-Dist: networkx>=3.0
Requires-Dist: numpy>=1.20.0
Requires-Dist: pandas>=2.0.0
Requires-Dist: protobuf>=4.0.0
Requires-Dist: pycityproto>=2.4.5
Requires-Dist: pydantic>=2.10.4
Requires-Dist: pyproj>=3.6.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: requests>=2.32.5
Requires-Dist: ruamel-yaml>=0.18.15
Requires-Dist: scikit-learn>=1.8.0
Requires-Dist: scipy>=1.10.0
Requires-Dist: shapely>=2.0.6
Requires-Dist: sqlalchemy[asyncio]>=2.0.46
Requires-Dist: sqlmodel>=0.0.16
Requires-Dist: stringcase>=1.2.0
Requires-Dist: tiktoken>=0.8.0
Requires-Dist: uvicorn>=0.36.0
Requires-Dist: wsproto>=1.2.0
Provides-Extra: all
Requires-Dist: furo>=2024.8.6; extra == 'all'
Requires-Dist: linkify-it-py>=2.0.0; extra == 'all'
Requires-Dist: matplotlib>=3.10.0; extra == 'all'
Requires-Dist: missingno>=0.5.0; extra == 'all'
Requires-Dist: mypy>=1.14.0; extra == 'all'
Requires-Dist: myst-parser>=4.0.0; extra == 'all'
Requires-Dist: openai>=2.16.0; extra == 'all'
Requires-Dist: pillow>=10.4.0; extra == 'all'
Requires-Dist: pre-commit>=3.8.0; extra == 'all'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
Requires-Dist: pytest-cov>=5.0.0; extra == 'all'
Requires-Dist: pytest>=9.0.2; extra == 'all'
Requires-Dist: ruff>=0.11.13; extra == 'all'
Requires-Dist: seaborn>=0.13.2; extra == 'all'
Requires-Dist: sphinx-autobuild>=2024.9.19; extra == 'all'
Requires-Dist: sphinx-autodoc2>=0.5.0; extra == 'all'
Requires-Dist: sphinx-intl==2.1.0; extra == 'all'
Requires-Dist: sphinx>=7.0.0; extra == 'all'
Requires-Dist: statsmodels>=0.14.0; extra == 'all'
Requires-Dist: sweetviz>=2.3.0; extra == 'all'
Requires-Dist: torch>=2.9.1; extra == 'all'
Requires-Dist: tqdm>=4.67.3; extra == 'all'
Requires-Dist: ydata-profiling>=4.6.0; extra == 'all'
Provides-Extra: analysis
Requires-Dist: matplotlib>=3.10.0; extra == 'analysis'
Requires-Dist: missingno>=0.5.0; extra == 'analysis'
Requires-Dist: openai>=2.16.0; extra == 'analysis'
Requires-Dist: pillow>=10.4.0; extra == 'analysis'
Requires-Dist: seaborn>=0.13.2; extra == 'analysis'
Requires-Dist: sweetviz>=2.3.0; extra == 'analysis'
Requires-Dist: tqdm>=4.67.3; extra == 'analysis'
Requires-Dist: ydata-profiling>=4.6.0; extra == 'analysis'
Provides-Extra: dev
Requires-Dist: mypy>=1.14.0; extra == 'dev'
Requires-Dist: pre-commit>=3.8.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest>=9.0.2; extra == 'dev'
Requires-Dist: ruff>=0.11.13; extra == 'dev'
Provides-Extra: docs
Requires-Dist: furo>=2024.8.6; extra == 'docs'
Requires-Dist: linkify-it-py>=2.0.0; extra == 'docs'
Requires-Dist: myst-parser>=4.0.0; extra == 'docs'
Requires-Dist: sphinx-autobuild>=2024.9.19; extra == 'docs'
Requires-Dist: sphinx-autodoc2>=0.5.0; extra == 'docs'
Requires-Dist: sphinx-intl==2.1.0; extra == 'docs'
Requires-Dist: sphinx>=7.0.0; extra == 'docs'
Provides-Extra: eda
Requires-Dist: statsmodels>=0.14.0; extra == 'eda'
Provides-Extra: ml
Requires-Dist: torch>=2.9.1; extra == 'ml'
Description-Content-Type: text/markdown

# AgentSociety 2

<p align="center">
  <a href="https://github.com/tsinghua-fib-lab/AgentSociety/stargazers">
    <img src="https://img.shields.io/github/stars/tsinghua-fib-lab/AgentSociety?style=social" alt="GitHub Stars">
  </a>
  <a href="https://pypi.org/project/agentsociety2/">
    <img src="https://img.shields.io/pypi/v/agentsociety2.svg" alt="PyPI Version">
  </a>
  <a href="https://pypi.org/project/agentsociety2/">
    <img src="https://img.shields.io/pypi/pyversions/agentsociety2.svg" alt="Python Version">
  </a>
  <a href="https://github.com/tsinghua-fib-lab/AgentSociety/blob/main/LICENSE">
    <img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License">
  </a>
</p>

<p align="center">
  <a href="https://agentsociety2.readthedocs.io/">
    <img src="https://img.shields.io/badge/docs-English-brightgreen" alt="English Docs">
  </a>
  <a href="https://agentsociety2.readthedocs.io/zh_CN/latest/">
    <img src="https://img.shields.io/badge/docs-%E4%B8%AD%E6%96%87-red" alt="Chinese Docs">
  </a>
</p>

> **AgentSociety 2** is a modern, LLM-native agent simulation platform designed for social science research and experimentation.

## Features

- **LLM-Native Design**: Built from the ground up for LLM-driven agents
- **Flexible Environment System**: Modular environment components with hot-pluggable tools
- **Multiple Reasoning Patterns**: ReAct, Plan-Execute, Code Generation, and Two-Tier routers
- **Developer-Friendly**: Pythonic API with type hints and comprehensive documentation
- **Experiment Replay**: Full SQLite-based replay system for analysis and debugging
- **MCP Support**: Model Context Protocol integration for tool extensibility

## Installation

```bash
pip install agentsociety2
```

### Requirements

- Python >= 3.11
- An LLM API key (OpenAI, Anthropic, or any provider supported by LiteLLM)

## Quick Start

### Create Your First Agent

```python
import asyncio
from datetime import datetime
from agentsociety2 import PersonAgent
from agentsociety2.env import CodeGenRouter
from agentsociety2.contrib.env import SimpleSocialSpace
from agentsociety2.society import AgentSociety

async def main():
    # Create an agent with a profile
    agent = PersonAgent(
        id=1,
        profile={
            "name": "Alice",
            "age": 28,
            "personality": "friendly and curious",
            "bio": "A software engineer who loves hiking and reading."
        }
    )

    # Create environment module with agent info
    social_env = SimpleSocialSpace(
        agent_id_name_pairs=[(agent.id, agent.name)]
    )

    # Create environment router
    env_router = CodeGenRouter(env_modules=[social_env])

    # Create the society
    society = AgentSociety(
        agents=[agent],
        env_router=env_router,
        start_t=datetime.now(),
    )

    # Initialize (sets up agents with environment)
    await society.init()

    # Query (read-only)
    response = await society.ask("What's your favorite activity?")
    print(f"Agent: {response}")

    # Close the society
    await society.close()

if __name__ == "__main__":
    asyncio.run(main())
```

### Create a Custom Environment Module

```python
from agentsociety2.env import EnvBase, tool

class MyCustomEnvironment(EnvBase):
    """A custom environment module."""

    @tool(readonly=True, kind="observe")
    def get_weather(self, agent_id: int) -> str:
        """Get the current weather for an agent."""
        return "The weather is sunny and 25°C."

    @tool(readonly=False)
    def set_mood(self, agent_id: int, mood: str) -> str:
        """Change the mood of an agent."""
        return f"Agent {agent_id}'s mood is now {mood}."

# Use the custom module
from agentsociety2.env import ReActRouter

env = ReActRouter()
env.register_module(MyCustomEnvironment())
```

### Run a Complete Experiment

```python
import asyncio
from datetime import datetime
from pathlib import Path
from agentsociety2 import PersonAgent
from agentsociety2.env import CodeGenRouter
from agentsociety2.contrib.env import SimpleSocialSpace
from agentsociety2.storage import ReplayWriter
from agentsociety2.society import AgentSociety

async def main():
    # Setup replay writer for environment dataset tracking
    writer = ReplayWriter(Path("my_experiment.db"))
    await writer.init()

    # Create agents first (needed for SimpleSocialSpace)
    agents = [
        PersonAgent(id=i, profile={"name": f"Player{i}", "personality": "friendly"})
        for i in range(1, 4)
    ]

    # Create environment router
    env_router = CodeGenRouter(
        env_modules=[SimpleSocialSpace(
            agent_id_name_pairs=[(a.id, a.name) for a in agents]
        )],
        replay_writer=writer,
    )

    # Create the society
    society = AgentSociety(
        agents=agents,
        env_router=env_router,
        start_t=datetime.now(),
        replay_writer=writer,
    )
    await society.init()

    # Query (read-only)
    answer = await society.ask("What are the names of all agents?")
    print(f"Answer: {answer}")

    # Intervene (read-write)
    result = await society.intervene("Set all agents' happiness to 0.8")
    print(f"Result: {result}")

    await society.close()

if __name__ == "__main__":
    asyncio.run(main())
```

## Core Concepts

### Agents

Agents are autonomous entities that interact with environments through LLM-powered reasoning:

- **AgentBase**: Abstract base class for all agents
- **PersonAgent**: Skills-based agent — a lightweight orchestrator whose capabilities are provided by a pluggable skill pipeline
- Agents support two interaction modes:
  - `ask(question, readonly=True)`: Query without side effects
  - `intervene(instruction)`: Make changes to the environment

#### Agent Skills

PersonAgent follows a **metadata-first, selected-only** model. Skills are self-contained directories under `agent/skills/`:

```
agent/skills/
├── observation/        # SKILL.md + scripts/observation.py
├── memory/             # SKILL.md + scripts/memory.py
├── cognition/          # SKILL.md + scripts/cognition.py
└── plan/               # SKILL.md + scripts/plan.py
```

Each skill has:

- `SKILL.md` — YAML frontmatter (name, description) + behavior docs
- `scripts/<name>.py` — optional subprocess script

Skills follow metadata-first selection:

- catalog exposes only name/description until activation
- execution is tool-loop driven (activate/read/execute)

Custom skills can be placed in `workspace/custom/skills/` and hot-loaded at runtime via the API or VSCode extension.

### Environment Modules

Environment modules encapsulate specific functionality through tools:

- **EnvBase**: Base class for creating custom modules
- **@tool decorator**: Register methods as discoverable tools
- Tool kinds:
  - `observe`: Single-parameter observation functions
  - `statistics`: No-parameter aggregation functions
  - Regular tools: Full read/write operations

### Routers

Routers mediate agent-environment interactions using different reasoning patterns:

- **ReActRouter**: Reasoning + Acting loop
- **PlanExecuteRouter**: Plan-first, then execute
- **CodeGenRouter**: Code generation based tool use
- **TwoTierReActRouter**: Two-level reasoning hierarchy
- **TwoTierPlanExecuteRouter**: Two-level planning hierarchy

### Storage

AgentSociety 2 currently has two persistence paths:

```python
from agentsociety2.storage import ReplayWriter
from pathlib import Path

writer = ReplayWriter(Path("experiment.db"))
await writer.init()

# Replay catalog tables (auto-created):
# - replay_dataset_catalog
# - replay_column_catalog

# Environment modules can register and write their own replay tables.
from agentsociety2.storage import ColumnDef, TableSchema
schema = TableSchema(
    name="custom_metrics",
    columns=[
        ColumnDef("metric_id", "INTEGER", nullable=False),
        ColumnDef("value", "REAL"),
    ],
    primary_key=["metric_id"],
)
await writer.register_table(schema)
```

- **ReplayWriter / SQLite**: stores environment replay datasets plus dataset/column catalog metadata.
- **PersonAgent workspace**: stores per-agent local files under `run/agents/agent_xxxx/`, such as `agent_config.json`, `session_state.json`, `tool_calls.jsonl`, and `thread_messages.jsonl`.

Legacy SQLite tables like `agent_profile`, `agent_status`, and `agent_dialog` are kept only for compatibility when reading old experiment databases; new runs no longer write them.

## Configuration

Set your LLM API credentials via environment variables. The examples below use the OpenAI API endpoint and `gpt-5.5`; other LiteLLM-supported providers can be used by changing the base URL and model id.

**Required Configuration**

```bash
# Default LLM (required - used for most operations)
export AGENTSOCIETY_LLM_API_KEY="your-api-key"
export AGENTSOCIETY_LLM_API_BASE="https://api.openai.com/v1"
export AGENTSOCIETY_LLM_MODEL="gpt-5.5"
```

**Optional Configuration**

For specialized tasks, you can configure separate LLM instances:

```bash
# Code Generation LLM (for code-related tasks)
# Falls back to default LLM if not set
export AGENTSOCIETY_CODER_LLM_API_KEY="your-coder-api-key"
export AGENTSOCIETY_CODER_LLM_API_BASE="https://api.openai.com/v1"
export AGENTSOCIETY_CODER_LLM_MODEL="gpt-5.5"

# Nano LLM (for high-frequency, low-latency operations)
# Falls back to default LLM if not set
export AGENTSOCIETY_NANO_LLM_API_KEY="your-nano-api-key"
export AGENTSOCIETY_NANO_LLM_API_BASE="https://api.openai.com/v1"
export AGENTSOCIETY_NANO_LLM_MODEL="gpt-5.5"

# Embedding Model (for text embeddings and semantic search)
# Falls back to default LLM if not set
export AGENTSOCIETY_EMBEDDING_API_KEY="your-embedding-api-key"
export AGENTSOCIETY_EMBEDDING_API_BASE="https://api.openai.com/v1"
export AGENTSOCIETY_EMBEDDING_MODEL="text-embedding-3-large"
export AGENTSOCIETY_EMBEDDING_DIMS="1024"

# Data directory (optional, default: ./agentsociety_data)
export AGENTSOCIETY_HOME_DIR="/path/to/your/data"
```

Or use a `.env` file:

```bash
cp .env.example .env
# Edit .env with your credentials
```

.. note::

   The upstream code validates ``AGENTSOCIETY_LLM_API_KEY`` at import time. Make sure it is set
   before importing `agentsociety2` (or load `.env` early in your entrypoint).

## Examples

The `examples/` directory contains ready-to-run examples:

- `basics/`: Basic agent and environment usage
- `games/`: Classic game theory simulations
  - Prisoner's Dilemma
  - Public Goods Game
  - Trust Game
  - Volunteer's Dilemma
  - Commons Tragedy
- `advanced/`: Advanced usage patterns
  - Custom environment modules
  - Multi-router setups
  - Experiment replay and analysis

## Documentation

- [English Documentation](https://agentsociety2.readthedocs.io/)
- [中文文档](https://agentsociety2.readthedocs.io/zh_CN/latest/)
- [API Reference](https://agentsociety2.readthedocs.io/en/latest/api.html)

## Development

For development and contribution guidelines, see [DEVELOPMENT.md](DEVELOPMENT.md).

### Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

## Citation

If you use AgentSociety 2 in your research, please cite:

```bibtex
@software{agentsociety2,
  title = {AgentSociety 2: A Modern LLM-Native Agent Simulation Platform},
  author = {Zhang, Jun and others},
  year = {2025},
  url = {https://github.com/tsinghua-fib-lab/agentsociety}
}
```

## License

Apache License 2.0 - see [LICENSE](LICENSE) for details.

## Acknowledgments

AgentSociety 2 builds upon excellent open-source projects:

- [litellm](https://github.com/BerriAI/litellm) - Unified LLM API
- [FastAPI](https://fastapi.tiangolo.com/) - Backend API framework
- [Pydantic](https://docs.pydantic.dev/) - Data validation

## Contact

- **Issues**: [GitHub Issues](https://github.com/tsinghua-fib-lab/agentsociety/issues)
- **Discussions**: [GitHub Discussions](https://github.com/tsinghua-fib-lab/agentsociety/discussions)

---

For the original AgentSociety (v1.x) focused on city simulation, see the [agentsociety package](https://pypi.org/project/agentsociety/).
