### Best Practice: Start Simple Sequential Tasks Source: https://github.com/benoitpetit/societyai/blob/main/docs/1-basics/getting-started.md This code snippet illustrates the best practice of starting with simple sequential tasks and gradually adding complexity. It shows an initial setup with a single agent and task, emphasizing a scalable approach to agent development. ```typescript // ✅ Start with sequential tasks await Society.create() .addAgent((a) => a.withId('agent1').withModel(model).withRole(role1)) .addTask((t) => t.withId('step1').withAgents(['agent1']).sequential()) .execute(input); // Then add more agents and dependencies as needed ``` -------------------------------- ### Quick Start with SocietyAI and OpenAI Adapter Source: https://github.com/benoitpetit/societyai/blob/main/README.md Example demonstrating how to initialize SocietyAI with the built-in OpenAI adapter to create and execute a simple agent task. It shows agent definition, task creation, and execution. ```typescript import { Society } from 'societyai'; import { ModelAdapters } from 'societyai/adapters'; // Use built-in OpenAI adapter const model = ModelAdapters.openai({ apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4' }); const result = await Society.create() .addAgent(agent => agent .withId('writer') .withRole(r => r.withSystemPrompt('You are a technical writer')) .withModel(model) ) .addTask(t => t .withId('write') .withAgents(['writer']) .sequential() ) .execute('Write about TypeScript'); ``` -------------------------------- ### Example Task Configuration Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/society-builder.md A complete example demonstrating how to configure tasks with dependencies and conditional routing. ```APIDOC ## Example Task Configuration ### Description Demonstrates setting up tasks with IDs, names, agents, instructions, sequential execution, dependencies, and conditional routing. ### Example ```typescript Society.create() .addTask((t) => t .withId('analyze') .withName('Analysis Phase') .withAgents(['analyst']) .withInstructions('Analyze the input data thoroughly') .sequential() .thenGoto('review') ) .addTask((t) => t .withId('review') .withName('Review Phase') .dependsOn('analyze') .withAgents(['reviewer']) .withConditionalNext( (results) => results.get('analyze')?.[0].output.includes('approved'), 'finalize', 'retry' ) .sequential() ); ``` ``` -------------------------------- ### Connect Agents to External Tools with MCPServers (TypeScript) Source: https://context7.com/benoitpetit/societyai/llms.txt Integrate agents with external tools and services using the Model Context Protocol. This example shows how to get pre-built tools for filesystem, Git, Brave Search, and GitHub, and how to define custom MCP servers and tools. ```typescript import { Society, MCPServers } from 'societyai'; // Get MCP tools for filesystem access const fsTools = await MCPServers.filesystem('/workspace'); // Get Git tools const gitTools = await MCPServers.git(); // Web search const searchTools = await MCPServers.braveSearch(process.env.BRAVE_API_KEY); // GitHub integration const githubTools = await MCPServers.github(process.env.GITHUB_TOKEN); // Combine multiple tool sets const result = await Society.create() .addAgent((a) => a .withId('dev-agent') .withRole((r) => r.withSystemPrompt('You are a developer with access to tools.')) .withModel(model) .withTools([...fsTools, ...gitTools, ...githubTools]) ) .addTask((t) => t .withId('develop') .withAgents(['dev-agent']) .withInstructions('Read the README.md, check git status, and summarize.') .sequential() ) .execute('Start development task'); // Custom MCP server import { MCPToolProvider } from 'societyai'; class CustomMCPServer extends MCPToolProvider { constructor() { super('custom-server', 'My custom tool set'); } async getTools() { return [{ name: 'custom_action', description: 'Perform a custom action', parameters: { type: 'object', properties: { input: { type: 'string' } } }, execute: async (args) => `Processed: ${args.input}`, }]; } } ``` -------------------------------- ### Conditional Routing Examples Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/society-builder.md Examples demonstrating different ways to implement conditional logic for task execution flow. ```APIDOC ## Conditional Routing Examples ### Simple Conditional (withConditionalNext) ```typescript Society.create().addTask((t) => t .withId('validate') .withAgents(['validator']) .sequential() .withConditionalNext( (results) => { const output = results.get('analyze')?.[0].output || ''; return output.includes('APPROVED'); }, 'deploy', // Go here if condition is true 'fix-issues' // Go here if condition is false ) ); ``` ### Multi-Path Branching (withBranch) ```typescript Society.create().addTask((t) => t .withId('check-quality') .withAgents(['quality-checker']) .sequential() .withBranch( (results) => { const score = parseInt(results.get('analyze')?.[0].output || '0'); return score >= 80; // Quality threshold }, ['approve', 'publish'], // Multiple tasks if true ['reject', 'notify-team'] // Multiple tasks if false ) ); ``` ### Dynamic Routing (thenResolve) ```typescript Society.create() .addTask(t => t .withId('classify') .withAgents(['classifier']) .sequential() .thenResolve((results) => { const category = results[results.length - 1]?.output; // Route to different experts based on category if (category?.includes('technical')) return 'tech-expert'; if (category?.includes('business')) return 'biz-expert'; if (category?.includes('legal')) return 'legal-expert'; return 'general-expert'; // Default route }) ) .addTask(t => t.withId('tech-expert')...) .addTask(t => t.withId('biz-expert')...) .addTask(t => t.withId('legal-expert')...) .addTask(t => t.withId('general-expert')...) ``` ``` -------------------------------- ### Isolate Benchmark Setup Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/benchmarks.md Best practice for writing benchmarks: separate setup code from the actual benchmarked operation to accurately measure performance. ```typescript // ❌ Bad - includes setup bench('slow', async () => { const graph = createComplexGraph(); // Setup included await graph.execute({ input: 'test', agents }); }); // ✅ Good - setup outside const graph = createComplexGraph(); bench('fast', async () => { await graph.execute({ input: 'test', agents }); }); ``` -------------------------------- ### Minimal Prompt Template Example in TypeScript Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/prompts.md A basic example of a custom prompt template that includes only the system prompt and user input placeholders. This is useful for straightforward agent tasks. ```typescript const role = createRole('writer') .withSystemPrompt('You are a technical writer') .withPromptTemplate('{system}\n\n{input}'); ``` -------------------------------- ### SocietyAI - Quick Start Source: https://github.com/benoitpetit/societyai/blob/main/README.md Demonstrates how to quickly set up and execute a simple workflow using SocietyAI with a built-in OpenAI adapter. ```APIDOC ## SocietyAI - Quick Start Example ### Description This example shows a basic setup of SocietyAI, defining an agent with a specific role and a task to execute. It utilizes the built-in OpenAI adapter for LLM interaction. ### Method N/A (Client-side TypeScript example) ### Endpoint N/A (Client-side TypeScript example) ### Parameters N/A ### Request Example ```typescript import { Society } from 'societyai'; import { ModelAdapters } from 'societyai/adapters'; // Use built-in OpenAI adapter const model = ModelAdapters.openai({ apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4' }); const result = await Society.create() .addAgent(agent => agent .withId('writer') .withRole(r => r.withSystemPrompt('You are a technical writer')) .withModel(model) ) .addTask(t => t .withId('write') .withAgents(['writer']) .sequential() ) .execute('Write about TypeScript'); console.log(result); ``` ### Response #### Success Response (200) - **result** (string) - The output generated by the AI agent. #### Response Example ```json { "example": "The output of the 'Write about TypeScript' task." } ``` ``` -------------------------------- ### Install MCP Servers with npm Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/mcp.md Installs necessary MCP server implementations using npm. These servers provide agents with access to external functionalities. ```bash npm install @modelcontextprotocol/server-filesystem npm install @modelcontextprotocol/server-git ``` -------------------------------- ### Configure Exporters Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/opentelemetry.md Examples for setting up console exporters for development and OTLP exporters for production environments. ```typescript // Console Exporter const observer = createOpenTelemetryObserver({ serviceName: 'dev-app', exporterType: 'console', }); // OTLP Exporter const observer = createOpenTelemetryObserver({ serviceName: 'production-app', exporterType: 'otlp', otlpEndpoint: 'http://localhost:4318', }); ``` -------------------------------- ### SocietyAI CLI Quick Start Commands Source: https://github.com/benoitpetit/societyai/blob/main/docs/1-basics/getting-started.md Demonstrates common commands for the SocietyAI Command Line Interface (CLI), including project initialization, validation, visualization, and running a society. ```bash # Create a new project npx societyai init --template basic --output ./my-project --name my-society cd my-project npm install # Validate your configuration npx societyai validate ./society.ts # Generate visualization npx societyai visualize ./society.ts --format html --output graph.html # Run your society npx societyai run ./society.ts --input "Hello World" --verbose --metrics ``` -------------------------------- ### Install OpenTelemetry Dependencies Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/opentelemetry.md Install the necessary OpenTelemetry packages to enable tracing support in your project. ```bash npm install @opentelemetry/api @opentelemetry/sdk-node ``` -------------------------------- ### Basic Role Creation and Execution - TypeScript Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/prompts.md A fundamental example showing how to create a role with a system prompt and a basic prompt template, then use it to set up agents and execute a task. This illustrates the core workflow of SocietyAI. ```typescript const role = createRole('assistant').withPromptTemplate( 'Lang: {context.lang}\n{input}' ); Society.create().withGlobalContext({ lang: 'en' }); ``` -------------------------------- ### Implement Best Practices for Patterns Source: https://github.com/benoitpetit/societyai/blob/main/docs/5-architecture/patterns.md Examples of best practices including simple sequential chains, scoring results with best(), setting iteration bounds, and applying middleware. ```typescript // Simple sequential pipeline Society.create().addAgent(...).addAgent(...).chain().execute(input); // Parallel analysis with aggregation Society.create().addAgent(...).addAgent(...).scatterGather(...).execute(input); // Quality selection using best() .transformResults( AggregationStrategies.best((result) => { return result.output.split(' ').length; }) ); // Bounded collaborative pattern Society.create().collaborate(3).execute(input); // Combining patterns with middleware const society = SocietyPatterns.review(writer, editor); society .addMiddleware( MiddlewareChain.create() .use(Middlewares.logging()) .use(Middlewares.retry({ maxAttempts: 2 })) ) .execute(input); ``` -------------------------------- ### Apply Basic Streaming Middleware with MiddlewareChain Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Demonstrates how to create a middleware chain using `MiddlewareChain.create()` and apply it to a model's stream. This example logs chunks with a prefix and transforms them to uppercase. It iterates over the transformed stream and prints each chunk. ```typescript import { StreamMiddlewares, MiddlewareChain } from 'societyai'; const chain = MiddlewareChain.create() .use(StreamMiddlewares.logChunks({ prefix: '[Agent]' })) .use(StreamMiddlewares.transformChunk((chunk) => chunk.toUpperCase())); const wrappedModel = chain.wrap(model); // Stream with middleware applied for await (const chunk of wrappedModel.stream('Hello')) { process.stdout.write(chunk); } ``` -------------------------------- ### Collaborative Template Example Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/prompts.md Demonstrates a collaborative debate scenario using prompt templates and multiple agents. ```APIDOC ## Example 5: Collaborative Template This example shows how to set up a collaborative debate between two agents. ### Method N/A (Illustrative Code) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript const role = createRole('debater').withSystemPrompt( 'You are participating in a debate' ).withPromptTemplate(` {system} Debate Topic: {input} Previous Arguments: {messages} Your turn. Provide your argument: `); Society.create() .addAgent((a) => a.withId('pro').withRole(role).withModel(model)) .addAgent((a) => a.withId('con').withRole(role).withModel(model)) .addTask( (s) => s.withId('debate').withAgents(['pro', 'con']).collaborative(3) // 3 rounds ) .execute('Should AI be regulated?'); ``` ### Response #### Success Response (200) N/A (Illustrative Code) #### Response Example **Rendered Prompt (Round 2 for 'con' agent)**: ``` You are participating in a debate Debate Topic: Should AI be regulated? Previous Arguments: [pro → broadcast]: Yes, AI regulation is essential because... [con → broadcast]: No, AI regulation would stifle innovation... [pro → broadcast]: But without safeguards... Your turn. Provide your argument: ``` ``` -------------------------------- ### Implement Custom Storage Adapter (TypeScript) Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/persistence.md Provides an example of creating a custom StorageAdapter by implementing the StorageAdapter interface. This in-memory adapter is useful for testing purposes, storing states in a Map. ```typescript import { StorageAdapter, WorkflowState } from 'societyai'; class InMemoryStorageAdapter implements StorageAdapter { private store = new Map(); async save(id: string, state: WorkflowState): Promise { this.store.set(id, structuredClone(state)); } async load(id: string): Promise { return this.store.get(id) ?? null; } async delete(id: string): Promise { this.store.delete(id); } async list(): Promise { return [...this.store.keys()]; } } ``` -------------------------------- ### Implement Tool Best Practices Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/tools-functions.md Examples of parameter validation using JSON Schema, error handling, and cancellation support for long-running tool operations. ```typescript // Parameter Validation properties: { email: { type: 'string', format: 'email', pattern: '^[a-z0-9.]+@[a-z0-9.]+\\.[a-z]{2,}$' }, age: { type: 'number', minimum: 0, maximum: 150 } } // Error Handling if (!params.id) { throw new Error('Missing required parameter: id'); } // Cancellation Support .withExecutor(async (params, context) => { for (let i = 0; i < 1000; i++) { if (context.signal?.aborted) { throw new Error('Operation cancelled'); } await processItem(i); } }) ``` -------------------------------- ### Configure Built-in Observability Middlewares Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Examples of using built-in middlewares for logging, timing, and metrics collection to monitor workflow execution. ```typescript import { Middlewares, InMemoryMetricsCollector } from 'societyai'; const logging = Middlewares.logging({ prefix: '[MyApp]', logInput: true, logOutput: true }); const timing = Middlewares.timing({ onComplete: (durationMs) => console.log(`Completed in ${durationMs}ms`) }); const collector = new InMemoryMetricsCollector(); const metricsMiddleware = Middlewares.metrics(collector); ``` -------------------------------- ### Query Jaeger for Performance Metrics Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/opentelemetry.md Example queries to filter traces in the Jaeger UI for identifying slow agents, errors, or specific execution modes. ```text # Find slow agents service=my-app AND span.kind=agent AND duration > 5s # Trace errors service=my-app AND error=true # Worker thread traces service=my-app AND executionMode=isolated ``` -------------------------------- ### Tool-Enabled Prompt Template in TypeScript Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/prompts.md Illustrates how to configure a prompt template for agents that utilize tools. The `{tools}` placeholder lists available tools, and the template guides the agent on how to format tool calls. ```typescript import { ToolBuilder } from 'societyai'; const searchTool = ToolBuilder.create('web_search') .withDescription('Search the web for information') .withParameters({ query: { type: 'string', description: 'Search query' }, }) .withExecutor(async ({ query }) => { // ... search implementation }) .build(); const role = createRole('researcher').withSystemPrompt( 'You are a research assistant' ).withPromptTemplate(` {system} Available Tools: {tools} To use a tool, output: {"name": "tool_name", "arguments": {"param": "value"}} Task: {input} `); const agent = createAgent('researcher', role, model).withTools([searchTool]); ``` -------------------------------- ### Build and Execute Graph with GraphBuilder in TypeScript Source: https://github.com/benoitpetit/societyai/blob/main/docs/5-architecture/execution-engine.md Demonstrates how to use the GraphBuilder API to define nodes and edges for creating a directed graph, and then execute it with an initial input. This example showcases adding nodes of different types (START, AGENT, CONDITION, END) and defining conditional edges for control flow. ```typescript import { GraphBuilder, NodeType } from 'societyai'; const engine = GraphBuilder.create() // 1. Define Nodes .addNode('start', NodeType.START) .addNode('analyst', NodeType.AGENT, { agentId: 'analyst' }) .addNode('reviewer', NodeType.AGENT, { agentId: 'reviewer' }) .addNode('decision', NodeType.CONDITION, { condition: (res) => res.includes('LGTM'), }) .addNode('end', NodeType.END) // 2. Define Edges .addEdge('start', 'analyst') .addEdge('analyst', 'decision') .addConditionalEdge({ from: 'decision', condition: (res) => res.includes('LGTM'), truePath: 'end', falsePath: 'reviewer', // Loop back for review }) .addEdge('reviewer', 'analyst') .build(); const result = await engine.execute(initialInput, availableAgents); ``` -------------------------------- ### CLI Command: init Source: https://github.com/benoitpetit/societyai/blob/main/docs/reference/cli.md Initializes a new SocietyAI project with a specified template, output directory, and project name. ```APIDOC ## CLI COMMAND: init ### Description Initializes a new SocietyAI project. Creates necessary files like society.ts, package.json, and README.md based on the selected template. ### Method CLI Command ### Endpoint societyai init ### Parameters #### Options - **--template, -t** (string) - Optional - Template name (default: basic) - **--output, -o** (string) - Optional - Output directory (default: .) - **--name** (string) - Optional - Project name (default: my-society) ### Request Example `npx societyai init --template advanced --name my-project` ### Response #### Success Response - **Output** (string) - Displays project creation status and next steps. ``` -------------------------------- ### Basic SocietyAI Agent with MCP Tools Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/mcp.md Demonstrates how to initialize a SocietyAI agent with MCP tools, such as the filesystem server, allowing the agent to interact with files. ```typescript import { Society, MCPServers } from 'societyai'; import { OpenAIModel } from './my-model-impl'; const model = new OpenAIModel(process.env.OPENAI_API_KEY); // Get MCP tools const fsTools = await MCPServers.filesystem('/workspace'); const society = Society.create() .withId('file-analyzer') .addAgent((a) => a .withId('analyzer') .withRole((r) => r.withSystemPrompt('You analyze files and provide insights.') ) .withModel(model) .withTools(fsTools) // ← Add MCP tools ) .addTask((t) => t.withId('analyze').withAgents(['analyzer'])) .execute('Analyze the README.md file'); ``` -------------------------------- ### Implement InMemoryVectorStore for Prototyping Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/memory.md Shows how to set up a local, RAM-based vector store for testing purposes. Note that this is limited to 10,000 entries and is not recommended for production. ```typescript import { MemoryBuilder, InMemoryVectorStore, VectorStoreAdapter } from 'societyai'; const vectorStore = new InMemoryVectorStore({ dimensions: 1536, distance: 'cosine', maxEntries: 10_000, }); const memory = MemoryBuilder.create() .withLongTermMemory({ vectorStore: new VectorStoreAdapter(vectorStore), embeddingModel: myEmbeddingModel, threshold: 0.75, }) .build(); ``` -------------------------------- ### Install SocietyAI Package Source: https://github.com/benoitpetit/societyai/blob/main/README.md Command to install the SocietyAI library using npm. This is the first step to integrating SocietyAI into a Node.js project. ```bash npm install societyai ``` -------------------------------- ### SocietyObserver Interface and Console Example (TypeScript) Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/society-configuration.md Defines the interface for observing SocietyAI's execution lifecycle events. Includes an example implementation that logs various events to the console. ```typescript interface SocietyObserver { // Required hooks onAgentStart(agentId: string, modelName: string, prompt: unknown): void; onAgentComplete(agentId: string, modelName: string, result: string): void; onAgentError(agentId: string, modelName: string, error: Error): void; onPhaseStart(phase: string): void; onPhaseComplete(phase: string): void; onSocietyStart(prompt: string, agentCount: number): void; onSocietyComplete(finalResult: string): void; // Optional hooks onTaskEnd?(taskId: string, result: TaskResult): void; onNodeStart?(nodeId: string, type: string, input: string): void; onNodeEnd?(nodeId: string, output: string, duration: number): void; onNodeError?(nodeId: string, error: Error): void; } // Example - simple console observer: const observer: SocietyObserver = { onAgentStart: (id, model, prompt) => console.log(`[${id}] Starting with model ${model}`), onAgentComplete: (id, model, result) => console.log(`[${id}] Done → ${result.slice(0, 80)}...`), onAgentError: (id, _model, err) => console.error(`[${id}] Error: ${err.message}`), onPhaseStart: (phase) => console.log(`Phase start: ${phase}`), onPhaseComplete: (phase) => console.log(`Phase end: ${phase}`), onSocietyStart: (prompt, n) => console.log(`Society started — ${n} agents — prompt: ${prompt.slice(0, 60)}`), onSocietyComplete: (result) => console.log(`Society complete → ${result.slice(0, 80)}`), }; await Society.create() .withObserver(observer) .addAgent(/* ... */) .addTask(/* ... */) .execute('Start'); ``` -------------------------------- ### Install TypeScript Execution Dependencies Source: https://github.com/benoitpetit/societyai/blob/main/docs/1-basics/getting-started.md Install the necessary ts-node package to support TypeScript execution within the SocietyAI environment, which is required for resolving certain worker thread errors. ```bash npm install --save-dev ts-node ``` -------------------------------- ### Prompt Overloading Example - TypeScript Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/prompts.md Illustrates a common pitfall in prompt engineering: overloading the prompt with too much information. This example shows a prompt template that includes many placeholders, which can confuse the model. ```typescript .withPromptTemplate(` {system} {memory} {history} {messages} {context} {tools} {input} `); ``` -------------------------------- ### Society Class - Initialization and Agent/Task Configuration Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/society-configuration.md Demonstrates how to initialize the Society builder, add agents with roles and models, and define tasks with dependencies. ```APIDOC ## Society Class - Initialization and Agent/Task Configuration ### Description This snippet illustrates the fundamental usage of the `Society` class, showcasing its fluent API for setting up agents, defining their roles and models, and structuring tasks with sequential execution and dependencies. It's the recommended entry point for creating multi-agent workflows. ### Method `Society.create()` ### Endpoint N/A (Class method) ### Parameters N/A for `create()` ### Request Body N/A ### Request Example ```typescript import { Society } from 'societyai'; const myModel = 'some-model-identifier'; // Replace with your actual model identifier const result = await Society.create() .withId('review-team') .addAgent((a) => a .withId('writer') .withRole((r) => r.withSystemPrompt('You are a technical writer.')) .withModel(myModel) ) .addAgent((a) => a .withId('editor') .withRole((r) => r.withSystemPrompt('You review style and clarity.')) .withModel(myModel) ) .addTask((t) => t.withId('draft').withAgents(['writer']).sequential() ) .addTask((t) => t .withId('review') .dependsOn('draft') .withAgents(['editor']) .sequential() ) .execute('Write a blog post about TypeScript'); console.log(result.output); ``` ### Response #### Success Response (200) - **output** (string) - The final output from the executed workflow. #### Response Example ```json { "output": "The generated blog post content..." } ``` ``` -------------------------------- ### Create Agents using FluentAgentBuilder Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/agents-roles.md Demonstrates two approaches to agent creation: using an inline builder within a Society instance or creating a pre-built agent using the createAgent helper function. ```typescript import { Society, createAgent, createRole } from 'societyai'; // ── Option 1: inline builder inside Society ────────────────────────────────── Society.create() .addAgent((a) => a .withId('analyst') .withRole((r) => r .withName('Data Analyst') .withSystemPrompt('You are an expert data analyst.') .withCapabilities(['analysis']) ) .withModel(myModel) .withTools([calculatorTool, searchTool]) .withRetry({ maxRetries: 3 }) ) .execute('...'); // ── Option 2: pre-built agent via createAgent() ────────────────────────────── const analystRole = createRole('analyst') .withName('Data Analyst') .withSystemPrompt('You are an expert data analyst.') .build(); const agent = createAgent('analyst', analystRole, myModel, { name: 'Senior Analyst', priority: 10, }); Society.create() .useAgent(agent) .addTask(/* ... */) .execute('Analyse this dataset'); ``` -------------------------------- ### Install fast-check for Property-Based Testing Source: https://github.com/benoitpetit/societyai/blob/main/docs/6-advanced-features/advanced-features.md Provides the command to install the 'fast-check' library, which is used for property-based testing within the SocietyAI project to automatically generate random inputs and discover edge cases. ```bash npm install --save-dev fast-check ``` -------------------------------- ### SocietyResult Interface and Usage Example (TypeScript) Source: https://github.com/benoitpetit/societyai/blob/main/docs/2-building-societies/society-configuration.md Defines the structure of the result returned by Society.execute(), including success status, output, task-specific results, messages, duration, and errors. Provides an example of how to access these properties. ```typescript interface SocietyResult { /** Whether the workflow completed without unhandled errors */ success: boolean; /** Final aggregated output string */ output: string; /** Per-task results, keyed by task ID */ taskResults: Map; /** All messages exchanged during collaborative steps */ messages: Message[]; /** Total wall-clock execution time in milliseconds */ duration: number; /** Non-fatal errors encountered during execution (if any) */ errors?: Error[]; } // Example Usage: const result = await Society.create() /* ... */ .execute('Start'); // Final output (last task result by default) console.log(result.output); // Per-task breakdown const draftResults = result.taskResults.get('draft'); console.log(draftResults?.[0].output); // Collaborative message history result.messages.forEach((m) => { console.log(`[${m.from} → ${m.to ?? 'all'}]: ${m.content}`); }); // Timing console.log(`Completed in ${result.duration}ms`); ``` -------------------------------- ### GET /storage/state Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/persistence.md Retrieves the current state of a workflow execution, including its status and history. ```APIDOC ## GET /storage/state ### Description Fetches the WorkflowState object for a specific execution ID. This is used to reconstruct the execution context or check if a workflow is paused. ### Method GET ### Endpoint /storage/state/{executionId} ### Parameters #### Path Parameters - **executionId** (string) - Required - The unique identifier for the workflow execution. ### Response #### Success Response (200) - **executionId** (string) - Unique identifier. - **status** (string) - Current lifecycle status ('active', 'paused', 'completed', 'failed'). - **waitingForNodeId** (string) - Optional - The ID of the node that triggered the pause. - **results** (object) - Serialized results keyed by node ID. #### Response Example { "executionId": "execution-id-123", "status": "paused", "waitingForNodeId": "manager-approval", "results": {} } ``` -------------------------------- ### Track Task Progress Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/observability.md Example of updating a progress bar in the console based on task completion events. ```typescript const totalTasks = 5; let completed = 0; events.on('task:complete', () => { completed++; const pct = Math.round((completed / totalTasks) * 100); process.stdout.write(`\rProgress: ${pct}%`); }); ``` -------------------------------- ### Manage Tools with ToolRegistry Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/tools-functions.md Demonstrates how to register tools globally and execute them by name using the ToolRegistry. ```typescript import { ToolRegistry } from 'societyai'; const registry = new ToolRegistry(); registry.register(calculatorTool); registry.register(searchTool); const result = await registry.execute('calculate', { expression: '2 + 2' }); ``` -------------------------------- ### Initialize SocietyAI Project Source: https://github.com/benoitpetit/societyai/blob/main/docs/reference/cli.md Initializes a new SocietyAI project with specified template, output directory, and project name. Supports various options for customization. ```bash npx societyai init npx societyai init --template advanced npx societyai init -t advanced -o ./projects/ npx societyai init --name my-awesome-society ``` -------------------------------- ### Initialize File Storage Adapter (TypeScript) Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/persistence.md Demonstrates how to initialize the built-in FileStorageAdapter for saving agent society states to the local file system. It specifies a base directory for storing state files. ```typescript import { FileStorageAdapter } from 'societyai'; const storage = new FileStorageAdapter({ baseDir: './.society-data' }); ``` -------------------------------- ### Monitor Workflow Lifecycle Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/observability.md Demonstrates how to listen for workflow-level events to track start, completion, and error states. ```typescript events.on('society:start', (e) => { console.log(`Workflow "${e.workflowName}" started with ${e.agentCount} agents`); }); events.on('society:complete', (e) => { console.log(`Workflow completed in ${e.duration}ms`); console.log('Output:', e.result.output); }); events.on('society:error', (e) => { console.error(`Workflow failed:`, e.error.message); }); ``` -------------------------------- ### Implement Real-Time Event Logging Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/observability.md Example of using the SocietyEventEmitter to log all incoming events with timestamps for debugging purposes. ```typescript import { SocietyEventEmitter } from 'societyai'; const events = new SocietyEventEmitter(); events.onAny((eventName, data) => { console.log(`[${new Date().toISOString()}] [${eventName}]`, data); }); ``` -------------------------------- ### Creating a Society Instance Source: https://github.com/benoitpetit/societyai/blob/main/docs/1-basics/core-concepts.md Demonstrates the creation of a Society instance using a fluent builder API. It shows how to initialize a society, assign an ID, add agents, define tasks, and initiate execution. ```typescript import { Society } from 'societyai'; const result = await Society.create() .withId('my-team') .addAgent(/* ... */) .addTask(/* ... */) .execute('Start'); ``` -------------------------------- ### Configure Built-in Transformation Middlewares Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Examples of using built-in middlewares to validate inputs/outputs and transform data flowing through the workflow. ```typescript import { Middlewares } from 'societyai'; const validation = Middlewares.validation({ validateInput: (input) => !input ? 'Input cannot be empty' : true, validateOutput: (output) => output.length < 10 ? 'Output too short' : true }); const transformInput = Middlewares.transformInput((input) => `[Sanitized] ${String(input).trim()}`); const transformOutput = Middlewares.transformOutput((output) => output.trim().replace(/\n{3,}/g, '\n\n')); ``` -------------------------------- ### Implement Logging Middleware Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md A practical example of a logging middleware that tracks execution duration and logs errors during the request lifecycle. ```typescript import { MiddlewareFn } from 'societyai'; const loggingFn: MiddlewareFn = async (ctx, next) => { console.log(`[${ctx.agentId ?? 'unknown'}] Sending prompt:`, ctx.input); const startTime = Date.now(); try { const result = await next(ctx); const duration = Date.now() - startTime; console.log(`[${ctx.agentId ?? 'unknown'}] Response in ${duration}ms`); return result; } catch (error) { console.error(`[${ctx.agentId ?? 'unknown'}] Error:`, error); throw error; } }; ``` -------------------------------- ### Compose Middlewares using MiddlewareChain.create() Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Demonstrates middleware composition using `MiddlewareChain.create()` with various built-in middlewares like logging, timeout, retry, cache, and circuit breaker. It also shows how to add a raw `MiddlewareFn` and how to reorder the chain by priority using `.sortByPriority()`. ```typescript import { MiddlewareChain, Middlewares } from 'societyai'; 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, timeout: 60_000 })); ``` ```typescript chain.use(async (ctx, next) => { ctx.metadata.set('traceId', crypto.randomUUID()); return next(ctx); }); ``` ```typescript chain.sortByPriority(); ``` -------------------------------- ### Adapter Comparison Source: https://github.com/benoitpetit/societyai/blob/main/docs/6-advanced-features/advanced-features.md A comparative overview of SocietyAI's storage adapters: FileStorageAdapter, RedisStorageAdapter, and PostgresStorageAdapter. ```APIDOC ## Storage Adapter Comparison ### Description This table compares the features of the different storage adapters available in SocietyAI. ### Method N/A ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response #### Success Response (200) ```markdown | Feature | `FileStorageAdapter` | `RedisStorageAdapter` | `PostgresStorageAdapter` | |---|---|---|---| | **Peer dependency** | None | `ioredis` | `pg` | | **Distribution** | Single process | Multi-instance | Multi-instance | | **TTL / expiry** | No | Yes | Via `cleanup()` | | **Queries** | No | No | Yes | | **ACID** | No | No | Yes | | **Best for** | Dev / single server | High-throughput | Audit trail / compliance | ``` ### Response Example N/A ``` -------------------------------- ### Define MCP Tool Schema Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/mcp.md Provides the TypeScript interface for MCP tools and a concrete example of a file-reading tool implementation. ```typescript interface Tool { name: string; description: string; parameters: { type: 'object'; properties: { [key: string]: { type: string; description?: string; } }; required?: string[]; }; execute: (args: any) => Promise; } const readFileTool = { name: 'read_file', description: 'Read the contents of a file', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Path to the file to read' } }, required: ['path'] }, execute: async (args) => { const content = await fs.readFile(args.path, 'utf-8'); return content; } }; ``` -------------------------------- ### Configure Memory Architecture with MemoryBuilder Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/memory.md Demonstrates how to initialize a memory system using the MemoryBuilder, including short-term message limits, long-term vector storage via Pinecone, and entity extraction. ```typescript import { MemoryBuilder } from 'societyai'; const memory = MemoryBuilder.create() .withShortTermMemory({ maxMessages: 20, summarizeAfter: 15, }) .withLongTermMemory({ provider: new PineconeProvider({ apiKey: process.env.PINECONE_API_KEY }), embeddingModel: 'text-embedding-3-small', threshold: 0.8, }) .withEntityMemory() .build(); ``` -------------------------------- ### Create a Custom MCP Server Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/mcp.md Shows how to define and implement a custom MCP server by extending the MCPToolProvider class. This allows for unique tool integrations tailored to specific needs. ```typescript import { MCPToolProvider } from 'societyai'; class CustomMCPServer extends MCPToolProvider { constructor() { super('custom-server', 'My custom tool set'); } async getTools() { return [ { name: 'custom_action', description: 'Perform a custom action', parameters: { type: 'object', properties: { input: { type: 'string' }, }, }, execute: async (args) => { // Your custom logic return `Processed: ${args.input}`; }, }, ]; } } // Use it const custom = new CustomMCPServer(); const tools = await custom.getTools(); const society = Society.create().addAgent((a) => a.withId('agent').withModel(model).withTools(tools)); ``` -------------------------------- ### Configure Built-in Middlewares Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Examples of using built-in middleware factories for rate limiting, caching, and exponential backoff retry logic. ```typescript import { Middlewares } from 'societyai'; const rateLimitMiddleware = Middlewares.rateLimit({ maxRequests: 10, windowMs: 60 * 1000, onLimitReached: () => console.warn('Rate limit reached') }); const cachingMiddleware = Middlewares.cache({ ttl: 3_600_000, keyGenerator: (input) => JSON.stringify(input).slice(0, 100) }); const retryMiddleware = Middlewares.retry({ maxAttempts: 3, delay: 1_000, backoffFactor: 2, retryOn: (error) => error.message.includes('rate_limit') || error.message.includes('timeout') }); ``` -------------------------------- ### Initialize Various LLM Adapters for SocietyAI Source: https://github.com/benoitpetit/societyai/blob/main/README.md Illustrates how to instantiate different language model adapters for use with SocietyAI, including OpenAI, Anthropic, Google Gemini, Azure OpenAI, Ollama (local), and a Mock adapter for testing. ```typescript import { ModelAdapters } from 'societyai/adapters'; // OpenAI const openai = ModelAdapters.openai({ apiKey, model: 'gpt-4' }); // Anthropic const anthropic = ModelAdapters.anthropic({ apiKey, model: 'claude-3-opus' }); // Google Gemini const gemini = ModelAdapters.gemini({ apiKey, model: 'gemini-pro' }); // Azure OpenAI const azure = ModelAdapters.azureOpenAI({ apiKey, endpoint, deployment }); // Ollama (local) const ollama = ModelAdapters.ollama({ model: 'llama2', baseURL }); // Mock (for testing) import { MockModel } from 'societyai/adapters'; const mock = new MockModel(); ``` -------------------------------- ### Create a Web Search Tool with SocietyAI Source: https://github.com/benoitpetit/societyai/blob/main/docs/3-capabilities/tools-functions.md Shows how to implement a mock web search tool that accepts a query and an optional maxResults parameter. It demonstrates handling default values and asynchronous API fetching. ```typescript const webSearchTool = ToolBuilder.create() .withName('web_search') .withDescription('Search the web for information on a given query') .withParameters({ type: 'object', properties: { query: { type: 'string', description: 'Search query' }, maxResults: { type: 'number', description: 'Maximum number of results to return', minimum: 1, maximum: 10, default: 5 } }, required: ['query'] }) .withExecutor(async (params) => { const maxResults = params.maxResults || 5; const results = await fetch(`https://api.search.com/query?q=${encodeURIComponent(params.query)}&limit=${maxResults}`) .then(res => res.json()); return { query: params.query, results: results.items.map(item => ({ title: item.title, url: item.url, snippet: item.snippet })) }; }) .build(); ``` -------------------------------- ### Declaring Explicit Task Dependencies Source: https://github.com/benoitpetit/societyai/blob/main/docs/1-basics/getting-started.md This example demonstrates how to use the `.dependsOn()` method to establish explicit ordering between tasks in a SocietyAI workflow. ```APIDOC ## POST /api/tasks/dependency ### Description Declares explicit ordering between tasks using the `.dependsOn()` method. ### Method POST ### Endpoint /api/tasks/dependency ### Parameters #### Request Body - **tasks** (array) - Required - An array of task definitions. - **id** (string) - Required - Unique identifier for the task. - **dependsOn** (string) - Optional - The ID of the task this task depends on. - **agents** (array) - Required - List of agents assigned to the task. - **execution_type** (string) - Required - Type of execution (e.g., 'sequential'). ### Request Example ```json { "tasks": [ { "id": "step1", "agents": ["writer"], "execution_type": "sequential" }, { "id": "step2", "dependsOn": "step1", "agents": ["editor"], "execution_type": "sequential" } ] } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Task dependencies declared successfully." } ``` ``` -------------------------------- ### Initialize OpenTelemetry Observer Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/opentelemetry.md Configure and attach an OpenTelemetry observer to a Society instance to start tracing execution phases and agent activities. ```typescript import { Society, createOpenTelemetryObserver } from 'societyai'; import { OpenAIModel } from './my-model-impl'; const observer = createOpenTelemetryObserver({ serviceName: 'my-app', exporterType: 'console', }); const model = new OpenAIModel(process.env.OPENAI_API_KEY); const result = await Society.create() .withId('traced-society') .withObserver(observer) .addAgent((a) => a .withId('writer') .withRole((r) => r.withSystemPrompt('You write content.')) .withModel(model) ) .addTask((t) => t.withId('write').withAgents(['writer'])) .execute('Write an article about TypeScript'); await observer.shutdown(); ``` -------------------------------- ### Tool Schema Definition Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/mcp.md Defines the schema for MCP tools, which follows the OpenAI function calling format, including an example of a `read_file` tool. ```APIDOC ## Tool Schema ### Description MCP tools follow OpenAI function calling format. ### Method N/A (Schema Definition) ### Endpoint N/A ### Parameters #### Tool Interface ```typescript interface Tool { name: string; description: string; parameters: { type: 'object'; properties: { [key: string]: { type: string; description?: string; }; }; required?: string[]; }; execute: (args: any) => Promise; } ``` ### Request Example #### Example Tool: `read_file` ```typescript { name: 'read_file', description: 'Read the contents of a file', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Path to the file to read' } }, required: ['path'] }, execute: async (args) => { const content = await fs.readFile(args.path, 'utf-8'); return content; } } ``` ### Response N/A ### Response Example N/A ``` -------------------------------- ### Compose and Apply Streaming Middlewares Source: https://github.com/benoitpetit/societyai/blob/main/docs/4-advanced/middleware.md Illustrates composing multiple streaming middlewares using `composeStreamingMiddleware` and applying them to an existing stream with `applyStreamingMiddleware`. This example composes logging, trimming, and throttling, then applies filtering and transformation to a source stream, finally logging the processed chunks. ```typescript import { composeStreamingMiddleware, applyStreamingMiddleware } from 'societyai'; // Compose multiple streaming middlewares const composed = composeStreamingMiddleware([ StreamMiddlewares.logChunks(), StreamMiddlewares.transformChunk((chunk) => chunk.trim()), StreamMiddlewares.throttle(50), ]); // Apply to an existing stream const sourceStream = model.stream('Hello'); const transformedStream = applyStreamingMiddleware(sourceStream, [ StreamMiddlewares.filterChunks((chunk) => chunk.length > 0), StreamMiddlewares.transformChunk((chunk) => `[${chunk}]`), ]); for await (const chunk of transformedStream) { console.log(chunk); } ```