societyai
repoSocietyAI is a TypeScript library for building complex collaborative AI systems. DAG engine, zero dependencies, and completely model agnostic.
README.md
SocietyAI
SocietyAI is a powerful TypeScript/Node.js library for orchestrating collaborative multi-agent systems. It allows you to build sophisticated workflows where AI agents, equipped with specific roles and capabilities, collaborate through a graph-based execution engine (DAG & Cycles).
The library is fully model-agnostic, domain-independent, and designed to be modular.
๐ฏ Why SocietyAI?
- Model-Agnostic: Works with any LLM (OpenAI, Anthropic, Mistral, Local, etc.). You implement the interface, you control the call.
- Graph Orchestration: Native support for DAGs (Directed Acyclic Graphs) as well as feedback loops and recursive structures.
- Zero Runtime Dependencies: The core is pure TypeScript.
- Fluent API: An intuitive builder (
Society.create()) to quickly define agents and workflows. - Type-Safe: Fully typed for a robust development experience.
- Two API Levels: Choose between high-level (quick) or low-level (powerful) depending on your needs.
๐ New to SocietyAI? Check out the Documentation for architectural insights and best practices.
โจ Key Features
- ๐ค Multi-Agent System: Define roles, personalities, and contexts for each agent.
- ๐ Flexible Workflows: Sequential, Parallel, Collaborative (debate between agents), and Conditional.
- โก Worker Threads Support: Execute CPU-intensive agents in isolated worker threads to prevent blocking the main event loop.
- ๐ง Memory & Context: Native management of short/long-term memory and type-safe Context Injection.
- ๐พ Persistence & Recovery: Save execution state, handle crashes, and resume workflows seamlessly.
- ๐ OpenTelemetry Integration: Built-in distributed tracing support for production observability.
- ๐ MCP Protocol Support: Integrate external tools and services via Model Context Protocol.
- ๐ก Observability: Full event-driven system to track every thought, action, and state change.
- ๐ Human-in-the-Loop: Pause workflows for human validation or input and resume automatically.
- โก Execution Strategies: The engine transforms your configuration into an optimized execution graph.
- ๐ ๏ธ Extensible: Middleware system, Custom Tools (Function Calling), and Validation.
๐งช Testing
SocietyAI comes with a comprehensive test suite using Jest.
Running Tests
# Run all tests npm test # Run with coverage report npm run test -- --coverage
Coverage Areas
- Core Logic: Execution engine, graph traversal, and state management.
- Capabilities: Tool execution, memory system, and schema validation.
- Builders: Fluent API configuration and validation.
- Observability: Event system and logging.
๐ Quick Start
Installation
npm install societyai
1. Connect Your Model
SocietyAI does not depend on any specific SDK library. You simply need to adapt
your model to the AIModel interface. Here is a minimal example for OpenAI:
import { AIModel } from 'societyai'; import OpenAI from 'openai'; // Install openai separately export class OpenAIModel implements AIModel { private client: OpenAI; private modelName: string; constructor(apiKey: string, model: string = 'gpt-4') { this.client = new OpenAI({ apiKey }); this.modelName = model; } name(): string { return this.modelName; } supportsPromptType(type: string): boolean { return true; } async process(prompt: unknown): Promise<string> { const response = await this.client.chat.completions.create({ model: this.modelName, messages: [{ role: 'user', content: String(prompt) }], }); return response.choices[0].message.content || ''; } }
2. Create Your First Society
This example creates a small team to write and review an article.
import { Society } from 'societyai'; import { OpenAIModel } from './my-model-impl'; // Your implementation above const model = new OpenAIModel(process.env.OPENAI_API_KEY); // Create the Society const result = await Society.create() .withId('blog-team') // -- Define Agents -- .addAgent((agent) => agent .withId('writer') .withRole((role) => role .withName('Technical Writer') .withSystemPrompt('You are an expert in concise technical writing.') ) .withModel(model) ) .addAgent((agent) => agent .withId('editor') .withRole((role) => role .withName('Editor in Chief') .withSystemPrompt('You correct style and verify clarity.') ) .withModel(model) ) // -- Define Workflow -- // Task 1: The writer writes .addTask((task) => task .withId('draft') .withAgents(['writer']) .withInstructions('Write a paragraph about the benefits of TypeScript.') .sequential() ) // Task 2: The editor reviews (explicitly depends on 'draft') .addTask((task) => task .withId('review') .dependsOn('draft') .withAgents(['editor']) .withInstructions( 'Review the previous text, correct mistakes, and improve the tone.' ) .sequential() ) // Execute .execute('Start Project'); console.log('Final Result:', result.output); console.log('History:', result.taskResults);
3. Advanced: Worker Threads & Observability
For CPU-intensive agents, use worker threads to prevent blocking:
import { Society, createOpenTelemetryObserver } from 'societyai'; import { OpenAIModel } from './my-model-impl'; const model = new OpenAIModel(process.env.OPENAI_API_KEY); // Optional: Enable distributed tracing const observer = createOpenTelemetryObserver({ serviceName: 'my-app', exporterType: 'console', }); const result = await Society.create() .withId('advanced-team') .withObserver(observer) // โ Add OpenTelemetry tracing // Standard agent (I/O-bound tasks) .addAgent( (agent) => agent .withId('coordinator') .withRole((role) => role.withSystemPrompt( 'You coordinate tasks and handle I/O operations.' ) ) .withModel(model) // executionMode defaults to 'default' (main thread) ) // CPU-intensive agent (runs in worker thread) .addAgent( (agent) => agent .withId('data-processor') .withRole((role) => role.withSystemPrompt( 'You perform heavy data analysis and complex calculations.' ) ) .withModel(model) .withExecutionMode('isolated') // โ Runs in Worker Thread ) .addTask((task) => task.withId('coordinate').withAgents(['coordinator']).thenGoto(['process']) ) .addTask((task) => task.withId('process').withAgents(['data-processor'])) .execute('Start workflow'); console.log('Result:', result.output); // Cleanup observer await observer.shutdown();
Key Points:
- executionMode: 'isolated': Agent runs in a Worker Thread, preventing main thread blocking.
- OpenTelemetry Observer: Distributed tracing for production monitoring.
- MCP Tools: Add external tools via
withTools(await MCPServers.filesystem('/path')).
๐ Documentation
Explore detailed documentation in the /docs folder:
- 1. Basics: Getting Started and Core Concepts.
- 2. Building Societies: Agents, Roles, Context, and Configuration.
- 3. Capabilities: Tools, Memory, Validation, and Persistence.
- 4. Advanced: Loops, Middleware, and Observability.
- 5. Architecture: Execution Engine, DAGs, and Patterns.
- Reference: API Index and Decision Guides.
Recent Highlights:
- Context Management for dependency injection.
- Observability System for full event tracking.
- Memory & RAG for long-term state.
- Structured Validation for reliable JSON outputs.
- Execution Engine deep dive.
๐ค Contribution
Contributions are welcome! Feel free to open an issue or a Pull Request on the GitHub repository.
๐ License
MIT