✨ v0.0.3 is available

Multi-Agent
Orchestration
for TypeScript

SocietyAI is a TypeScript library with zero runtime dependencies for building collaborative AI workflows — model-agnostic, graph-native, and production-ready.

npm install societyai
Zero Runtime Dependencies
TypeScript Native
MIT License
Model Agnostic
Architecture

Built for reliability

No black magic — solid engineering foundations designed for complex production workflows.

Model Agnostic

Compatible with OpenAI, Anthropic, Mistral, or any local model. Implement one interface — that's it.

Graph Orchestration

Native DAG and cyclic graph support. Build sequential chains, parallel fans, and feedback loops.

Zero Runtime Dependencies

The core is pure TypeScript with no runtime dependencies. Optional peer deps (OpenTelemetry, MCP, Redis, Postgres) are strictly opt-in.

Fully Type-Safe

Autocomplete your entire workflow. Catch configuration errors at compile time, not runtime.

Fluent Builder API

Express agents, roles, and task graphs in a readable, chainable API — one line per concept.

Extensible by Design

13 built-in middlewares, custom tools, structured output validation, and a plugin-ready event system.

Capabilities

Everything you need to ship

From quick prototypes to production-grade multi-agent pipelines.

Multi-Agent System

Define roles, personalities, and system prompts for each agent. Agents can collaborate through structured message passing, iterate over multiple rounds, or debate to reach consensus.

Flexible Workflows

Sequential, parallel, collaborative, conditional, and human-in-the-loop tasks. Combine them in any order with explicit dependency declarations or implicit sequential wiring.

Memory & Context

Built-in short-term, long-term, and entity memory systems. Share data across tasks via typed context injection. Pluggable VectorProvider interface for RAG-compatible backends.

Worker Thread Isolation

Run CPU-intensive agents in isolated Worker Threads with executionMode: 'isolated'. Prevents event loop blocking for latency-sensitive applications.

Observability & Tracing

Full event-driven system with built-in structured logger. Optional OpenTelemetry integration (peer dep) for distributed tracing. Plug in your own observer for custom monitoring.

MCP Protocol

Optional Model Context Protocol integration (peer dep) for connecting external tools — filesystem, git, search engines, and more via the standardized MCP interface.

Tools & Function Calling

Define custom tools with JSON Schema parameter validation. The ReAct pattern is natively supported — agents reason, act, and observe in a structured loop.

Structured Validation

Validate agent outputs against JSON Schema definitions. The self-correcting validator automatically retries with feedback until the output matches the expected shape.

Persistence & Recovery

Save and restore execution state mid-workflow. Built-in file adapter included; optional Redis and PostgreSQL adapters available as peer dependencies.

How it works

From config to execution in 4 steps

The SocietyExecutor transforms your high-level configuration into an optimized DAG and runs it.

Define Roles & Agents

Each agent has a role (system prompt), an AI model adapter, and a unique ID. Roles are reusable across agents.

step-1-roles.ts
import { Society } from 'societyai';

// Define roles inline when creating agents
const society = Society.create()
  .addAgent(a => a
    .withId('writer')
    .withRole(r => r
      .withName('Technical Writer')
      .withSystemPrompt('You are an expert in concise technical writing.'))
    .withModel(model))
  .addAgent(a => a
    .withId('editor')
    .withRole(r => r
      .withName('Editor in Chief')
      .withSystemPrompt('You correct style and verify clarity.'))
    .withModel(model));

Declare Tasks & Dependencies

Use Society.create() to wire agents into tasks. Use .dependsOn() to declare explicit ordering — no magic positional assumptions.

step-2-society.ts
const society = Society.create()
  .withId('blog-team')
  .addAgent(a => a
    .withId('writer').withRole(writerRole).withModel(model))
  .addAgent(a => a
    .withId('editor').withRole(reviewerRole).withModel(model))
  .addTask(t => t
    .withId('draft').withAgents(['writer']).sequential())
  .addTask(t => t
    .withId('review')
    .dependsOn('draft')    // explicit dependency edge
    .withAgents(['editor']).sequential());

Graph Transformation (DAG)

Behind the scenes, SocietyExecutor converts your task declarations into an optimized execution graph. Dependency edges, conditional branches, and resolver nodes are all wired automatically.

N

Nodes

Agents, parallel tasks, conditions, human gates

E

Edges

dependsOn() declarations + implicit sequential links

V

Validation

Unknown agents, duplicate IDs, broken references

Execute & Collect Results

Call .execute(input) to run the entire orchestration. The result contains the final output, per-task results, message history, and execution duration.

step-4-execute.ts
const result = await society.execute('Write about TypeScript...');

console.log(result.output);       // final aggregated output
console.log(result.taskResults);   // per-task results map
console.log(result.duration);     // total execution time (ms)
console.log(result.success);     // boolean
Execution Types

Six orchestration modes

Mix and match within the same workflow to model any real-world collaboration pattern.

Sequential

.sequential()

Agents execute one by one, each receiving the accumulated output of the previous step as context. Ideal for linear pipelines where order and data flow matter.

Best for

  • Writing & editing pipelines
  • Data processing chains
  • Step-by-step analysis

Step-by-step execution

IN
Agent A
Agent B
Agent C
OUT
Middleware

13 built-in middlewares

Composable, priority-ordered middleware chain. Wrap any model or agent with logging, caching, rate limiting, and more.

Observability

logging()timing()metrics(collector)

Resilience

timeout(ms)retry({ maxAttempts })cache({ ttl })rateLimit()circuitBreaker()dedupe()fallback(value)

Transform

validation()transformInput(fn)transformOutput(fn)
middleware-example.ts
import { Society, Middlewares, MiddlewareChain } from 'societyai';

// Build a reusable middleware chain
const chain = MiddlewareChain.create()
  .use(Middlewares.logging())
  .use(Middlewares.timeout(30_000))
  .use(Middlewares.retry({ maxAttempts: 3 }))
  .use(Middlewares.cache({ ttl: 60_000 }))
  .use(Middlewares.circuitBreaker({ threshold: 5 }));

// Pass the chain directly to addMiddleware()
const result = await Society.create()
  .addMiddleware(chain)   // ← Middleware | MiddlewareChain
  .addAgent(...)
  .addTask(...)
  .execute('Run workflow');
Advanced

Hierarchical societies

Wrap an entire society as a model using EngineAsModel. Compose teams inside teams — infinite nesting depth.

How it works

  1. 1.Build an inner society (sub-team)
  2. 2.Wrap it with EngineAsModel
  3. 3.Use it as a regular model in an outer society

Use Cases

  • Manager delegating to sub-teams
  • Nested multi-stage pipelines
  • Reusable domain-specific societies
  • Recursive problem decomposition
hierarchical.ts
import { Society, GraphBuilder, NodeType, EngineAsModel } from 'societyai';

// 1. Build the inner team graph
const codeTeamEngine = GraphBuilder.create()
  .addNode('start',  NodeType.START)
  .addNode('coder',  NodeType.AGENT, { agentId: 'coder' })
  .addNode('tester', NodeType.AGENT, { agentId: 'tester' })
  .addNode('end',    NodeType.END)
  .addEdge('start', 'coder')
  .addEdge('coder',  'tester')
  .addEdge('tester', 'end')
  .build();

// 2. Wrap the inner engine as a model
const codeTeamModel = new EngineAsModel({
  engine: codeTeamEngine,
  agents: [coderAgent, testerAgent],
  name:   'code-team',
});

// 3. Use the entire sub-team as a single agent in an outer society
const result = await Society.create()
  .addAgent(a => a
    .withId('manager')
    .withRole(r => r.withSystemPrompt('You delegate to the team.'))
    .withModel(codeTeamModel)  // ← sub-team as a model
  )
  .addTask(t => t.withId('delegate').withAgents(['manager']).sequential())
  .execute('Build a REST API');
API

Two levels of abstraction

Start high-level and drop down to the graph API only when you need full control.

Recommended

High-Level API

For most use cases. Simple, fluent, fast to write.

Entry Point

Society.create()

Building Blocks

Task + TaskExecutionType

Best For

Standard workflows, rapid prototyping, production pipelines

Advanced

Low-Level API

For complex cases requiring full graph control.

Entry Point

GraphBuilder.create()

Building Blocks

GraphNode + 10 NodeTypes

Best For

Cycles, custom transforms, complex aggregations, hierarchical nesting

Tip: Always start with the High-Level API. Switch to Low-Level only when you need cycles, custom node types, or nested graph composition.

Quick Start

A complete example

Writer → Editor workflow in under 40 lines.

blog-workflow.ts
import { Society } from 'societyai';
// SocietyAI is model-agnostic — bring your own adapter (OpenAI, Anthropic, etc.)
import { MyAIModel } from './my-model-adapter';

const model = new MyAIModel(process.env.OPENAI_API_KEY);

const result = await Society.create()
  .withId('blog-team')

  // ── 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)
  )

  // ── Tasks ────────────────────────────────────────────────────
  .addTask(task => task
    .withId('draft')
    .withAgents(['writer'])
    .withInstructions('Write a paragraph about the benefits of TypeScript.')
    .sequential()
  )
  .addTask(task => task
    .withId('review')
    .dependsOn('draft')           // explicit dependency edge
    .withAgents(['editor'])
    .withInstructions('Review the draft, correct mistakes, and improve tone.')
    .sequential()
  )

  .execute('Start Project');

console.log('Result:', result.output);

Ready to build
intelligent systems?

Start orchestrating your multi-agent workflows today. Open source, MIT licensed, zero runtime dependencies.

MIT License
Open Source
Zero Runtime Dependencies
TypeScript 5.5+