Observed since 20 Oct, 23:27 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A modern, LLM-native agent simulation platform for social science research
AgentSociety 2 is a modern, LLM-native agent simulation platform designed for social science research and experimentation.
ServiceProxypip install agentsociety2
Before running the examples, set the LLM environment variables described in
Configuration. The package validates them when agentsociety2
is imported.
import asyncio
from datetime import datetime
from pathlib import Path
from agentsociety2.env import CodeGenRouter
from agentsociety2.contrib.env import SimpleSocialSpace
from agentsociety2.society import AgentSociety
async def main():
# Declare agent metadata (id / profile / config); agents are NOT instantiated here.
# AgentSociety batch-creates their workspaces during init().
agent_specs = [
{
"id": 1,
"profile": {
"name": "Alice",
"age": 28,
"personality": "friendly and curious",
"bio": "A software engineer who loves hiking and reading.",
},
"config": {},
}
]
names = [(s["id"], s["profile"]["name"]) for s in agent_specs]
# Create environment module with agent info
social_env = SimpleSocialSpace(agent_id_name_pairs=names)
# Create environment router (in-process CodeGenRouter; production uses an EnvRouterProxy Ray actor)
env_router = CodeGenRouter(env_modules=[social_env])
# Create the society
society = AgentSociety(
agent_specs=agent_specs,
agent_class_name="PersonAgent",
env_router=env_router,
start_t=datetime.now(),
run_dir=Path("run"),
)
# Initialize (batch-creates agent workspaces, binds the 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())
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 CodeGenRouter
env_router = CodeGenRouter(env_modules=[MyCustomEnvironment()])
import asyncio
from datetime import datetime
from pathlib import Path
from agentsociety2.env import CodeGenRouter
from agentsociety2.contrib.env import SimpleSocialSpace
from agentsociety2.society import AgentSociety
async def main():
# Declare agent metadata
agent_specs = [
{
"id": i,
"profile": {"name": f"Player{i}", "personality": "friendly"},
"config": {},
}
for i in range(1, 4)
]
names = [(s["id"], s["profile"]["name"]) for s in agent_specs]
# Create environment router (replay is enabled by default -> run/replay/)
env_router = CodeGenRouter(
env_modules=[SimpleSocialSpace(agent_id_name_pairs=names)]
)
# Create the society
society = AgentSociety(
agent_specs=agent_specs,
agent_class_name="PersonAgent",
env_router=env_router,
start_t=datetime.now(),
run_dir=Path("run"),
)
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())
Agents are autonomous entities that interact with environments through LLM-powered reasoning:
ask(question, readonly=True): Query without side effectsintervene(instruction): Make changes to the environmentPersonAgent follows a metadata-first, selected-only model. Skills are self-contained
directories; the only built-in skill is daily-guidance (daily behavior / needs-decay
guidance). The old observation / cognition / plan / memory skills have been removed —
those capabilities are now expressed via custom skills + workspace state files + ask_env.
agent/skills/
└── daily-guidance/ # SKILL.md + scripts/daily_guidance.py (pre_step hook)
Each skill has:
SKILL.md — YAML frontmatter (name, description, optional script / hooks) + behavior docsscripts/*.py — optional scripts. By default these run in-process via an entrypoint(argv, ctx)
contract (millisecond, concurrency-safe), with dynamic-wrapper and subprocess fallbacks.Skills follow metadata-first selection:
activate_skill / read_skill_file / execute_skill_script)pre_step / post_step lifecycle hooks are rendered into a dedicated <skill_hooks> blockCustom skills can be placed in <workspace>/custom/skills/ and hot-loaded at runtime.
Environment modules encapsulate specific functionality through tools:
observe: Single-parameter observation functionsstatistics: No-parameter aggregation functionsRouters mediate agent-environment interactions using different reasoning patterns:
AgentSociety 2 currently has two persistence paths:
from agentsociety2.storage import ReplayReader, ReplayWriter
from pathlib import Path
writer = ReplayWriter(Path("run/replay"))
await writer.init()
# Replay schema sidecar: run/replay/_schema.json
# 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)
reader = ReplayReader(Path("run/replay"))
print(reader.load_dataset_catalog())
reader.close()
_schema.json
metadata, then read them through DuckDB-backed views.run/agents/agent_xxxx/, such as
config.json, AGENT.json, AGENT_MEMORY.md, state/*.json, and .runtime/logs/*.jsonl.agentsociety2.trace module writes distributed tracing spans (sharded writer +
background-thread actor) for profiling steps and LLM calls.Legacy SQLite tables like agent_profile, agent_status, and agent_dialog are kept only for compatibility when reading old experiment databases; new runs write run/replay/ instead.
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
# 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:
# 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:
# From the repository root:
cp .env.example .env
# Edit .env with your credentials before importing agentsociety2
Note AgentSociety 2 validates
AGENTSOCIETY_LLM_API_KEYat import time. Make sure it is set before importingagentsociety2, or load.envearly in your entrypoint.
The examples/ directory (under this package) contains ready-to-run examples:
basics/: Basic agent and environment usage (workspace agent_specs + run_dir);
02_custom_env_module.py uses contrib WeatherEnvironmentgames/: Classic game theory simulations
01_prisoners_dilemma.py)02_public_goods.py)reputation_game.py)advanced/: Multi-router comparison and contrib SpecialistAgent
(01_custom_agent.py); production-style runs use create_env_router_proxyLonger batch scripts (Trust Game, Volunteer's Dilemma, Commons Tragedy, etc.) live under
experiments/env_main_*_v2.py.
For development guidelines, see docs/development.rst.
We welcome contributions! Please see CONTRIBUTING.md for details.
If you use AgentSociety 2 in your research, please cite:
@misc{piao2026agentsociety2,
title = {{AgentSociety} 2: An Integrated Research Environment for Executable Social Science},
author = {Jinghua Piao and Jun Zhang and Haoyu Huang and Keming Zhang and Jing Yi Wang and Xinran Zhao and Songwei Li and Boyuan Sun and Jiayi Chang and Fengli Xu and Chunyan Wang and Fang Zhang and Ke Rong and Jun Su and Tianguang Meng and Yi Liu and Qingguo Meng and Yu Wang and Yong Li},
year = {2026},
eprint = {2607.11895},
archiveprefix= {arXiv},
primaryclass = {cs.CY},
doi = {10.48550/arXiv.2607.11895},
url = {https://arxiv.org/abs/2607.11895},
}
Paper: arXiv:2607.11895. Repository-wide citations: CITATION.cff · citations.bib.
Apache License 2.0 - see LICENSE for details.
AgentSociety 2 builds upon excellent open-source projects:
For the original AgentSociety (v1.x) focused on city simulation, see the agentsociety package.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 2.9.3 | 24 Sept 2026 | 58 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 23:27 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:776633e89b732b6e08a1884436f37cc408f3279382af50842d3c9ca40ee95e5e